繁体   English   中英

通过解除引用复制std :: unique_ptr的值

[英]Copying std::unique_ptr's value via dereferencing

我编写了以下代码,我尝试将unique_ptr对象的值复制到结构中。

#include <iostream>
#include <memory>
using namespace std;

struct S {
    S(int X = 0, int Y = 0):x(X), y(Y){}

    // S(const S&) {}
    // S& operator=(const S&) { return *this; }

    int x;
    int y;
    std::unique_ptr<S> ptr;
};

int main() {
    S s;
    s.ptr = std::unique_ptr<S>(new S(1, 4));
    S p = *s.ptr; // Copy the pointer's value
    return 0;
}

它在Visual C ++ 2012中弹出错误:

智能感知:没有合适的用户定义从“S”到“S”的转换
IntelliSense:没有运算符“=”匹配这些操作数操作数类型是:std :: unique_ptr> = std :: unique_ptr>
错误C2248:'std :: unique_ptr <_Ty> :: unique_ptr':无法访问类'std :: unique_ptr <_Ty>'中声明的私有成员

除非我取消注释我尝试定义复制构造函数和=运算符的行。 这消除了编译器错误,但没有消除IntelliSense错误。 无论错误列表中显示的IntelliSense错误如何,它都会编译。

那么,为什么不能只使用默认函数并用它们编译呢? 我是以正确的方式做价值的副本吗? 如果需要,我应该如何定义复制构造函数?

复制构造函数不会隐式生成,因为您有一个用户定义的构造函数,为什么复制S尝试失败的原因。

但仍然, unique_ptr不可复制,只能移动 ,所以你可以使用S移动构造函数

S(S&& other) : x(other.x), y(other.y), ptr(std::move(other.ptr))
{

}

并称之为:

S p = std::move(s); // Move s to p

现场演示

std::unique_ptr既不是Copy Constructible也不是Copy Assignable。

S的隐式复制赋值运算符和构造函数将生成错误,因此将出现错误消息。

但是你可以使用S p = std::move(s); 因为std::unique_ptr是Move Constructible和Move Assignable,

那么,为什么不能只使用默认函数并用它们编译呢?

据我所知, unique_ptr容器背后的想法是它只处理其内容的生命(指向T的指针),直到从该职责中解除(使用swapreset方法),或者有效地破坏了其内容(当它本身就被摧毁了)。 unique_ptr的第二个重要属性是它必须允许T不完整类型(以便支持不透明指针)。 这意味着包含的值可能不是CopyConstructible 因此,不能允许unique_ptr本身为CopyConstructible

我是以正确的方式做价值的副本吗? 如果需要,我应该如何定义复制构造函数?

如果T最终是CopyConstructible ,你想要这样做,你必须通过访问指针手动处理副本,就像你在main 复制构造函数应该做同样的事情。

不是一个完整的答案,只是提供信息:

我强烈建议您在实验中添加可见性:

std::ostream&
operator<<(std::ostream& os, const S& s)
{
    os << '{' << s.x << ", " << s.y << ", ";
    if (s.ptr != nullptr)
        os << s.ptr.get() << ':' << *s.ptr;
    else
        os << "nullptr";
    return os << '}';
}

现在你可以这样说:

cout << "s = " << s << '\n';

在实验的多个地方,真正了解每个步骤后发生的事情。 这应该可以帮助您分析并继续设计。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM