【问题标题】:Deleted copy constructor when member is an unique_ptr [duplicate]当成员是unique_ptr时删除了复制构造函数[重复]
【发布时间】:2019-06-16 03:27:08
【问题描述】:

这段代码运行良好:

class Test
{
    int* ptr = new int(10);
};

int main()
{       
     Test o;
     Test t = o;
}

但是当我们使用 unique_ptr 而不是 raw ptr 时,我们得到一个错误:

error: use of deleted function 'Test::Test(const Test&)'

以及示例代码:

class Test
{
     std::unique_ptr<int> ptr = std::make_unique<int>(1);
};

int main()
{       
     Test o;
     Test t = o;
}

发生了什么事?

【问题讨论】:

  • 当然unique_ptr 没有复制构造函数,只有移动构造函数。如果您想复制Test,请使用shared_ptr(或按照链接答案的建议进行深层复制)。
  • 提示在名称中。如果每个人都能拥有一个指针,它就不是唯一的指针了。
  • 其实原代码不是好的。它有内存泄漏,切换到std::unique_ptr 允许编译器防止这种情况(通过不允许您的代码)。

标签: c++


【解决方案1】:

发生了什么事?

您不能创建第二个 Test 实例,因为这意味着您需要一个 unique_ptr 的副本,这是不可能的。 unique_ptr 只能移动。尝试实现一个移动赋值运算符并像这样移动o

class Test
{
public:
    Test() = default;

    Test(Test&& other) noexcept
        : ptr(std::move(other.ptr))
    {
    }

private:
    std::unique_ptr<int> ptr = std::make_unique<int>(1);
};

int main()
{
    Test o;
    Test t = std::move(o);
}

如果你想复制unique_ptr底层的int,你需要像这样定义一个自定义的复制构造函数:

class Test
{
public:
    Test() = default;

    Test(const Test& other)
        : 
    ptr(new int(*other.ptr))
    {

    }

    Test(Test&& other) noexcept
        : ptr(std::move(other.ptr))
    {
    }

private:
    std::unique_ptr<int> ptr = std::make_unique<int>(1);
};

int main()
{
    Test o;
    Test t = o;
}

但是,注意,指针指向两个 DIFFERENT 整数。 如果你想要共享所有权,你必须(并且应该)像这样使用 shared_ptr:

class Test
{
private:
    std::shared_ptr<int> ptr = std::make_shared<int>(1);
};

int main()
{
    Test o;
    Test t = o;
}

【讨论】:

  • @user463035818 但这不是指针的副本。您现在有两个不同的指针指向两个不同的对象,这与 OP 的第一个示例不同。
  • @user463035818 我们可能正在讨论答案的不同部分:P
  • @LightnessRacesinOrbit 我可能不得不重新加载才能看到编辑内容......现在我对答案很好。 cmets 已删除
  • 我可能会像这样实现复制构造函数:Test(const Test&amp; other) : Test() { *ptr = *(other.ptr); } 或者Test(int i = 0) : ptr(make_unique&lt;int&gt;(i)) {} Test(const Test&amp; other) : Test(*(other.ptr)) { }。这样Test 的每个实例都可以平等地使用make_unique,并且在类中有一个分配点,而不是让默认构造的实例使用make_unique,而复制的实例使用new。但是,这只是我。无论哪种方式都会“工作”。
  • @RemyLebeau 好点。在这种情况下,我什至可能不会考虑以任何一种方式实现它,因为复制的意义有限。
【解决方案2】:

发生了什么事?

您已从裸指针转换为强制所有权语义的指针。一个很聪明的人。

这确实是unique_ptr的目的

它强制执行唯一所有权

你不能复制它;只移动它。

如果您确实需要 Test 可复制并能够共享 ints,您可能正在寻找 shared_ptr

【讨论】:

  • 感谢您的回答。但是我在哪里可以找到这样的规则:当类具有 unique_ptr 成员时,从类中删除复制构造函数?
  • 编译器必须调用已删除的 unique_ptr 的复制构造函数。 MSVC 发出以下错误'Test::Test(const Test &amp;)': attempting to reference a deleted function
  • @KeyB0rys 正如 Nathan 所示。从逻辑上讲,当类的一部分被定义为不可复制时,如何复制该类?这没有任何意义。
猜你喜欢
  • 2013-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-23
相关资源
最近更新 更多