C ++放置新的vs复制赋值

时间:2015-04-24 08:49:40

标签: c++ placement-new

在某处,我读到该向量内部使用placement new作为对象构造。当我尝试实现类似的容器时,我通常最终得到像

这样的分配

_elements = new Type[capacity]

然后我追加像这样的新对象

void append(const T& element) {
    // reallocation in case if capacity is equal to size
    _elements[size++] = element;
}

这种结构在复制和构建之间是否存在任何性能或其他差异?

1 个答案:

答案 0 :(得分:9)

  

这种结构在复制和构建之间是否存在任何性能或其他差异?

当然可以。如果构造一个数组:

_elements = new Type[capacity]

...然后必须初始化数组的元素,直到容量。这意味着将创建许多“默认”Type对象。另一方面,当使用placement new时,您不会初始化数组,而只是分配空间,并根据需要构造对象。这是更高效和语义上的不同,因为没有创建初始对象(请记住,创建它们可能有副作用)。

使用一种确实在其默认构造函数中确实具有明显副作用的类型,可能有助于您理解并进行一些实验:

class Type
{
    public:
    Type()
    {
       cout << "Created Type." << endl;
    }
};

使用上述Type,如果您执行new Type[3],则会看到三条消息打印到cout。另一方面,如果您创建容量为3的std::vector<Type>,则不应看到打印到cout的任何消息。

你的追加方法:

void append(const T& element) {
    // reallocation in case if capacity is equal to size
    _elements[size++] = element;
}

调用T的赋值运算符。因此,将对象添加到容器中需要:

  1. 首先使用默认构造函数
  2. 构造对象
  3. 调用赋值运算符
  4. 将此与标准库容器进行对比:

    1. 使用复制构造函数(并通过放置`new')
    2. 构造对象
    3. 无需转让。
    4. 另一个考虑因素是,如果new Type[x]没有可访问的默认构造函数,则通常无法调用Type。如果您将上例中的public:更改为private:,您将会看到此情况。但是仍然可以创建一个(空)std::vector<Type>,只要你将另一个(可用的)构造函数添加到Type,你仍然可以在其中添加对象。