2009-11-07 87 views
10

我知道STL容器如vector在添加对象时复制对象。 push_back方法是这样的:STL容器如何复制对象?

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); 

这将复制的对象,我可以看到它在调用拷贝构造

我的问题是,当push_back需要项目作为参考,它是如何调用复制构造?或者我在这里错过了什么?

任何想法..?

回答

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必须对此有一个拷贝构造函数的工作。默认情况下(如果你什么都不做),它会免费获得一个。如果您明确定义它,那么vector<T>必须为public

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

+0

当T有一个无参数构造函数时,这是可以的。但是当它有一个参数化的构造函数时会发生什么?矢量如何初始化新对象? – 2009-11-07 13:45:52

+0

当T有一个_copy constructor_时,这是可以的。默认情况下,如果你实现它,除非你明确地将其设置为'private'或'protected'。 – Thomas 2009-11-07 14:00:36

+0

我编辑了我的答案以澄清。 – Thomas 2009-11-07 14:04:26

1

它使用放置new运算符并将其复制到单位内存中;

新的放置位置会在内存中的指定地址处创建一个新元素,在向量情况下,当前的end();

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

看看http://spotep.com/dev/devector.h它有非常明确的代码(与大多数STL实现相反)。

3

C++ SDK始终将const T &作为函数参数来提高效率。

在你的情况下,如果以T作为参数,复制动作将被执行两次,一次用于将它传递给功能push_back(f),一个用于内部将其添加到容器。并以const T&作为参数只需要一个副本!

+7

没有C++ SDK。 – GManNickG 2010-09-15 03:34:14

+0

好的,我的意思是像C++语言规范,STL等背后的东西... ... - – learner 2010-12-25 20:20:31