3

当我初始化一个 STL 容器时,例如list< vector<char> >使用例如my_list.push_back(vector<char>(5000, 'T')),这是在构造后复制的吗?还是编译器会调用list< vector<char> >自己内部的构造函数?

4

2 回答 2

7

在 C++03push_back中定义为void push_back(const T& x);. 这意味着您正在构造 avector并且对此类时间的 const 引用正在传递给list. 然后list内部调用复制构造函数以存储此类元素的副本。

在 C++11 中有一个额外的定义,void push_back(T&& x);它需要一个对你的 temporal 的右值引用vector,并且会导致内部调用移动构造函数来初始化list.

于 2011-09-29T19:56:02.647 回答
0

编译器很聪明。真聪明。在这种情况下,有一种称为“复制省略”的优化。C++ 标准允许编译器在使用临时对象初始化相同类型的对象时省略副本,并且该对象的复制构造函数没有副作用。

这与更流行的“好像”规则属于同一类优化。只要生成的程序的可观察行为与“好像”完全遵循标准一样,该规则允许编译器几乎可以摆脱它想要的任何东西。

这是一个示例程序。在带有 -O0 和 -O3 的 gcc 4.4.5 上,此代码导致打印“1”。我认为 GCC 在这里是错误的……一些编译器会输出“2”,表示发生了副本。这就是在尝试检测本应无法检测的行为时事情变得棘手的地方。在其中一个编译器中,唯一的判断方法是深入研究生成的程序集。

#include <iostream>

struct elision
{
    explicit elision(int i) : v(i) {
    }

    elision(elision const &copy) : v(copy.v+1) {
    }

    int v;
};

int main()
{
    elision e(elision(1));
    std::cout << e.v << std::endl;
    return 0;
}
于 2011-10-01T01:03:58.733 回答