为什么在下面的代码中出现一对“额外”的复制构造函数和破坏?
当Dingledong的构造函数将STL容器作为参数时,就会发生这种情况(我尝试过std :: vector和std :: list)。其他事情可能会发生吗?如果构造方法改为使用指针,则不会发生。如果我改为在堆上分配ding(Dingledong * ding = new Dingledong(v)),也不会发生这种情况。
#include <list>
#include <iostream>
class Dingledong{
public:
Dingledong(std::list<int> numbers)
{
std::cout << "construction\n";
numbers_ = numbers;
}
Dingledong(Dingledong const& other)
{
std::cout << "COPY construction\n";
}
~Dingledong()
{
std::cout << "destructed\n";
// I would do some cleanup here.. unsubscribe from events, whatever..
// but the destructor is called sooner than I would expect and thus
// the cleanup is done prematurely.
}
std::list<int> numbers_;
};
void diller()
{
std::cout << "diller started.. " << std::endl;
std::list<int> v = std::list<int>(34);
// Having an STL container as parameter in constructor causes Dingledong's copy constructor to
// be used to create a temporary Dingledong which is immediately destructed again. Why?
Dingledong ding = Dingledong(v);
std::cout << "Has ding been destructed?\n";
}
int main()
{
diller();
system("pause");
}
输出:
diller started...
construction
COPY construction // I didn't expect this to happen
destructed // I didn't expect this to happen
Has ding been destructed?
destructed
先感谢您!
这段代码:
Dingledong ding = Dingledong(v);
方法:
Dingledong
,使用初始化v
ding
,使用临时对象初始化。复制构造函数在此处进入步骤2。如果您不想要副本,请不要编写指定副本的代码。例如:
Dingledong ding(v); // no copy
编译器可以实现一个称为复制省略的功能,其中可以优化此临时对象(即使复制构造函数具有副作用),但是它们不必这样做,在这种情况下,没有理由依赖于此。
您可以通过添加move-constructor来改进代码,在这种情况下(如果编译器不执行复制省略),该操作将是移动而不是复制,从而降低了成本。
也有你的构造一个浪费副本(numbers
从复制v
,然后numbers_
从复制numbers
,并且也numbers_
被初始化,然后分配,而不是仅仅被初始化)。这将是一个更好的构造函数:
Dingledong(std::list<int> numbers): numbers_( std::move(numbers) )
{
std::cout << "construction\n";
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句