7

我编写了以下代码,尝试将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 中弹出错误:

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

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

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

4

4 回答 4

6

复制构造函数不会隐式生成,因为您有一个用户定义的构造函数,这就是您尝试复制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

现场演示

于 2014-10-26T14:29:09.437 回答
2

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

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

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';

在您的实验中的多个位置,并真正了解每一步之后发生的情况。这应该可以帮助您分析并继续您的设计。

于 2014-10-26T15:13:52.093 回答
2

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

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

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

如果T最终成为CopyConstructible,正如您想要的那样,您必须通过访问指针手动处理副本,就像您在main. 复制构造函数可能应该做同样的事情。

于 2014-10-26T15:05:55.097 回答
2

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

隐式复制赋值运算符和构造函数的S格式不正确,因此会出现错误消息。

但是,您可以S p = std::move(s);按原样 使用std::unique_ptrMove Constructible 和 Move Assignable,

于 2014-10-26T14:28:14.353 回答