我需要返回具有unique_ptr成员的对象?

时间:2018-09-27 16:14:49

标签: c++ return copy-constructor unique-ptr virtual-destructor

假设我有这个对象:

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

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

2 个答案:

答案 0 :(得分:6)

[class.copy.ctor]/8

  

如果类X的定义未明确声明移动构造函数,则当且仅当[...]

时,非显式构造函数将隐式声明为默认构造函数      
      
  • X没有用户声明的析构函数。
  •   

因为

virtual ~foo() = default;

是用户声明的析构函数,您不再具有move构造函数,因此它尝试使用copy构造函数,但不能执行,因为由于您具有不可复制的成员而将其删除。

要获取move构造函数并保持默认构造值,您需要添加

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;是使用声明的构造函数,如果有任何用户声明的构造函数,则默认构造函数为no不再提供。


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

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

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

答案 1 :(得分:1)

要么提供自己的副本构造函数和默认构造函数,要么将该成员转换为共享指针,或者提供移动构造函数。一种可能的解决方案:

struct foo {
    unique_ptr<int> mem;
    foo() = default;
    foo(const foo& copy);
    virtual ~foo() = default;
};

foo::foo(const foo& copy) : mem(new int(*copy.mem)) {}

foo make_foo() {
    foo result;
    result.mem = make_unique<int>();
    return result;
}