析构函数和unique_ptr

25

我有以下代码

class A {
    public:
        A(){}
        ~A(){}
    private:
        std::vector<std::unique_ptr<double> > x;
};

A f() {
    A a;
    return a;
}

int main() {
    A a=f();
    return 0;
}

除非我注释掉析构函数,否则它无法编译(gcc 4.7)。实际上,我在我的代码中并不真正需要这个析构函数,我只是想将其用于调试目的。

然而,我不明白正在发生什么,因此我担心自己做错了些什么。这里到底发生了什么?


4
询问为什么某个东西无法编译时,提供错误提示信息总是有帮助的。 - NPE
@user2183861 不,那里没有回答。这个问题非常不同。 - BЈовић
1个回答

32
那是因为存在一个明确定义的析构函数,阻止了对 A 的移动构造函数的隐式生成。
根据 C++11 标准第 12.8/9 段的规定:
如果类 X 的定义没有显式声明移动构造函数,则当且仅当以下条件均成立时将被隐式声明为默认构造函数:
- X 没有用户声明的拷贝构造函数, - X 没有用户声明的拷贝赋值运算符, - X 没有用户声明的移动赋值运算符, - X 没有用户声明的析构函数,并且 - 移动构造函数不会被隐式定义为已删除。
现在,由于缺少移动构造函数,编译器会尝试调用隐式生成的拷贝构造函数(仍然出于向后兼容而生成)。然而,std::unique_ptr 是不可复制的。因此,会出现错误。
明确定义移动构造函数(或者像评论中 juanchopanza 建议的那样声明一个默认构造函数)可以解决这个问题。

@AndyProwl 这个评论与答案无关,我可以问一下你从哪里得到了C++11标准,是在书中吗?谢谢! - taocp
好的,你还应该添加A&operator=(A&&)以提供移动赋值。 - ipc
@SongWang: 你可以从这里下载最新的草案,但请记住,这比当前官方标准要新(你可以从ISO购买)。 - Andy Prowl
@ipc:实际上,在我看来,不明确定义析构函数是最有意义的。但是,如果一个人不想遵循零规则,他至少应该遵循五个规则。 - Andy Prowl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接