以下代码编译的当且仅当我删除Foo的自定义析构函数。
struct Foo {
std::unique_ptr <int> bar;
~Foo (void) {} // This Line
};
std::vector <Foo> foos;
foos.push_back (Foo ());以下是我对这种情况的理解:
它失败了,因为unique_ptrs不能被复制,而且std::vector::push_back (thing)调用thing's复制构造函数。如果我编写Foo --一个显式移动bar的自定义复制构造函数,那么一切都会好的。
但是,禁用This Line将导致代码编译。
我认为即使没有This Line,这也不能编译,因为我仍然在尝试push_back一个unique_ptr。
为什么在没有自定义析构函数的情况下这会成功,为什么添加自定义析构函数会导致它失败?
编辑:在Debian 64位上使用gcc -std=gnu++11
发布于 2014-03-01 07:25:00
我不能保证这就是你的情况,但这与我最近看到的一些事情有关:
您不能复制唯一的指针,但可以移动它们。
在C++11中,如果不定义析构函数,就会得到默认的移动构造函数,但是如果定义了析构函数,编译器就不必提供移动构造函数,在这种情况下,代码会失败。(我知道Visual不会这样做,但是在我使用Xcode的Mac上,我仍然得到了move构造函数。)
所以,我认为这就是你的案子发生的事。尝试提供析构函数和其他构造函数/赋值运算符,以查看它是否修复了某些内容。(参见关于五条规则的讨论。)
发布于 2014-03-01 07:34:14
按照标准"12.8.9复制和移动类对象class.copy“
如果类X的定义没有显式声明移动构造函数,则将隐式声明为defaulted当且仅当:
因此,如果类没有用户定义的析构函数,则将声明一个移动构造函数。根据标准的"12.8.15“,这将调用unique_ptr类成员的move-构造函数:
非联合类X的隐式定义复制/移动构造函数执行其基和成员的成员级复制/移动。
如果类具有用户定义的析构函数,则应显式声明移动构造函数:
struct Foo {
std::unique_ptr <int> bar;
Foo() = default;
Foo(Foo&&) = default;
~Foo (void) {} // This Line
};发布于 2014-03-01 07:47:27
显式析构函数使编译器不生成默认的移动构造函数和默认的分配移动运算符,这两个是unique_ptr在所有权转移中所必需的。因此,如果要实现析构函数,则必须实现这些参数:
Foo(){}
Foo &operator=(Foo &&o) {
if (this != &o)
bar = std::move(o.bar);
return *this;
}
Foo(Foo &&o) : bar(std::move(o.bar)) {}因为不应该复制Foo,所以我建议只移除复制构造函数和赋值操作符:
Foo(Foo const &) = delete;
Foo &operator=(Foo const &) = delete; 编辑
实际上,五条规则更好地解释了这一点,如果您实现了以下任何一种方法,那么在google上很容易找到:
destructor
copy constructor
move constructor
copy assignment operator
move assignment operator您应该考虑实现所有这些(或删除),尤其是在使用使用移动语义的unique_ptr时。
当您注释掉析构函数时,输入零规则。
https://stackoverflow.com/questions/22111387
复制相似问题