当我没有用户定义的析构函数时编译完全正常的代码(在GCC 4.7.2上),即使提供空用户定义的析构函数也会产生错误:
#include <memory>
class Test
{
std::unique_ptr<int> val;
};
template <typename Type>
class B
{
public:
//destructor:
// if I comment this out, the code compiles just fine:
~B() { }
private:
Test a;
};
int main()
{
auto s = B<int>();
}
析构函数未被注释时产生的错误中的突出点是:
对于任何有兴趣的人来说,完整的错误输出位于本文的最后部分。
我知道unique_ptr
不能复制构造(除非参数是rvalue),因此编译器不可能为类{{1}生成有效的隐式复制构造函数}。
我无法弄清楚为什么定义一个空析构函数应该突然需要这些复制工具。显然,当使用像Test
这样的东西时,这是不可能提供的。
这里有人能够告诉我为什么会这样吗?
未对析构函数进行注释时完成错误输出:
unique_ptr
答案 0 :(得分:14)
如果定义~B()
,则会禁止B
的移动构造函数,因此编译器会尝试生成复制构造函数,但会失败,因为unique_ptr
不是可复制构造的。
如果省略~B()
,则生成B
的移动构造函数,并在main
中使用。
您可以请求自动生成的移动构造函数:
B(B &&) = default;
这是与C ++ 03代码向后兼容的标准中的一项功能;根据规则三,编写自己的析构函数(等)的代码被假定为管理自己的资源,因此除非明确请求,否则自动生成移动构造函数是不合适的。
答案 1 :(得分:3)
嗯,你自己说的;当您提供用户定义的析构函数时,您将禁止编译器生成隐式移动构造函数之类的内容。用户定义的析构函数的内容(无论是空的还是其他的)都是完全不相关的。
时,才会将其隐式声明为默认值
[C++11: 12.7/9]:
如果类X
的定义未明确声明移动构造函数,则当且仅当:
X
没有用户声明的复制构造函数,X
没有用户声明的副本分配运算符X
没有用户声明的移动分配运算符X
没有用户声明的析构函数,- 移动构造函数不会被隐式定义为已删除。
[注意: 当没有隐式声明或显式提供移动构造函数时,否则会调用移动构造函数的表达式可能会调用复制构造函数。 - 尾注]
说明中的文字指出了您所看到的确切情况,导致编译失败,因为unique_ptr
无法被复制;虽然你没有复制它,虽然s
的初始化可能不需要复制/移动,但操作仍然需要可用(每[C++11: 12.8/31-32]
)。