我知道像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的?或者我在这里遗漏了什么?
有什么想法..?
答案 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实现相反)。