STL容器如何复制对象?

时间:2009-11-07 13:35:54

标签: c++ stl constructor

我知道像vector这样的STL容器会在添加对象时复制它。 push_back方法如下:

void push_back ( const T& x );

我很惊讶地看到它将该项目作为引用。我写了一个示例程序,看它是如何工作的。

struct Foo
{
    Foo()
    {
        std::cout << "Inside Foo constructor" << std::endl;
    }

    Foo(const Foo& f)
    {
        std::cout << "inside copy constructor" << std::endl;
    }
};

Foo f;
std::vector<Foo> foos;
foos.push_back(f);

这会复制对象,我可以看到它正在调用 copy-constructor

我的问题是,当push_back将项目作为参考时,它是如何调用copy-constructor的?或者我在这里遗漏了什么?

有什么想法..?

3 个答案:

答案 0 :(得分:12)

它可能使用“placement new”在其内部数组中就地构造对象。展示位置new不会分配任何内存;它只是将对象放在您指定的位置,并调用构造函数。语法为new (address) Class(constructor_arguments)

调用复制构造函数T::T(T const &)以就地创建副本。像这样(简化):

template<T>
void vector<T>::push_back(T const &item) {
    // resize if necessary
    new (&d_array[d_size++]) T(item);
}

请注意T必须有一个复制构造函数才能生效。默认情况下(如果你什么都不做),它会免费获得一个。如果您明确定义它,public必须vector<T>才能正常工作。

Here's how GNU's libstdc++ does it,但我怀疑它会非常有启发性。有一个分配器(vector的第二个模板参数)使得它不那么简单。

答案 1 :(得分:3)

C ++ SDK总是将const T &作为效率的函数参数。

在您的情况下,如果以T作为参数,则复制操作将完成两次,一次用于将其传递给函数push_back(f),一次用于将其添加到容器中。以const T&为参数,只需要一份副本!

答案 2 :(得分:1)

它使用placement new运算符并将其复制构造为单元化内存;

placement new在内存中的指定地址创建一个新元素,在vector case中,当前end();

void push_back(const T& val){
::new (&*end()) T(val);
[increase end]
}

查看具有相当清晰代码的http://spotep.com/dev/devector.h(与大多数STL实现相反)。