你能用C ++破坏和重建一个向量的元素吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你能用C ++破坏和重建一个向量的元素吗?相关的知识,希望对你有一定的参考价值。

从外部破坏和构造向量元素是否合法?假设您将一组元素保留在您开始构建的状态中,当然?并假设不做任何明显愚蠢的事情,比如在相同的元素上调用析构函数两次,或类似的。

抛开异常,我想象的是以下内容:

int main ()
{
  std::vector<std::string> v (10, "Hello");

  v [2].std::string::~string ();

  new (&v [2]) std::string ("World");
}

或者这样的事情会是UB吗?其他标准容器呢?

答案

这是完全有效的,就像你总是可以显式地调用任何对象的析构函数一样。但是,它可能是愚蠢的。在摧毁和复活元素之间,向量处于无法被破坏的状态。如果由于某种原因调用了析构函数,则会获得UB。这特别危险,因为你可能不会一个接一个地做这两个步骤。

现在,你不只是为了好玩而这样做。如果你想要,例如要擦除一个元素,你可以创建一个临时的,与元素交换然后销毁临时元素。这样,你就不会有这个窗口,你不能破坏矢量。此外,这种方法甚至适用于像std::string元素这样的非常重要的情况,也适用于更复杂的矢量元素。

另一答案

你可以这样做,但是矢量中的插槽在破坏和重建之间是无效的。如果由于某种原因(可能是异常),在重构之前调用向量的DTOR,接着会出现未定义的行为。

以下是一个更安全的替代方案。任何合理质量的std :: string实现都将构造一个带有“World”的新std :: string,然后使用rvalue-assignment运算符(move-semantics)将其放入向量槽。执行此任务期间没有任何周期受到伤害。

#include <string>
#include <iostream>

int main()
{ 
    v[2] ="World";
    std::cout << v[2] << std::endl;
    return 0;
}

以上是关于你能用C ++破坏和重建一个向量的元素吗?的主要内容,如果未能解决你的问题,请参考以下文章

在混合 C 和 C++ 代码编程中捕获异常后对象不会被破坏

你能调试自动矢量化循环吗?

(透彻理解)最精锐代码::堆的三种基本操作新建-插入-删除

反汇编区段加密代码

C++0x 中的缩小转换。只是我,还是这听起来像是一个重大变化?

删除 '#include <algorithm>' 不会破坏代码