首页 > 解决方案 > 我需要什么才能返回具有 unique_ptr 成员的对象?

问题描述

假设我有这个对象:

struct foo {
    std::unique_ptr<int> mem;
    virtual ~foo() = default;
};

我不能再返回foo在函数中创建的对象:

foo make_foo() {
    foo result;

    result.mem = std::make_unique<int>({});
    return result;
}

正如可能表明的那样,我需要析构函数是虚拟的,因为这将是一个基类。但即使我使用默认析构函数,这还不够,我仍然无法返回在函数中创建的对象。

我得到错误:

error C2280: foo::foo(const foo &): attempting to reference a deleted function

有没有办法解决这个问题?

标签: c++returncopy-constructorunique-ptrvirtual-destructor

解决方案


根据[class.copy.ctor]/8

如果类 X 的定义没有显式声明移动构造函数,当且仅当 [...]

  • X 没有用户声明的析构函数。

自从

virtual ~foo() = default;

是用户声明的析构函数,您不再有移动构造函数,因此它尝试使用复制构造函数,但不能因为您有一个不可复制的成员而被删除。

要取回移动构造函数并保持默认可构造,您需要添加

foo() = default;
foo(foo&&) = default;
foo &operator=(foo &&) = default; // add this if you want to move assign as well

foo


添加foo() = default;时必须添加的foo(foo&&) = default;原因foo(foo&&) = default;是使用声明的构造函数,如果您有任何用户声明的构造函数,则不再提供默认构造函数。


这是一个“黑客”,但您可以做的是将虚拟析构函数移到另一个类中,然后从该类继承。这将为您提供一个虚拟析构函数,foo而无需声明它并为您提供所需的默认构造函数。那看起来像

struct make_virtual
{
    virtual ~make_virtual() = default;
};

struct foo : make_virtual {
    std::unique_ptr<int> mem;
};

推荐阅读