unique_ptr,移动构造函数,以及为什么总是尝试访问私有成员

unique_ptr, move constructor, and why always attempt to access private member

本文关键字:访问 成员 为什么 ptr 移动 构造函数 unique      更新时间:2023-10-16

我经常遇到这个问题,我相信移动构造函数是有序的,但我认为复制构造函数是问题所在,隐藏它似乎不起作用。

代码:

template <class T>
class LinkedList{
public:
    //
    LinkedList() {}
    LinkedList(const T &data);
    LinkedList(const T &data, const LinkedList &node);
    LinkedList(const LinkedList &object);
    LinkedList &operator=(const LinkedList &object);
    ~LinkedList() {}
    std::shared_ptr<LinkedList> push_back(const T& data);
private:
    T data;
    std::unique_ptr<LinkedList> link;
    std::unique_ptr<LinkedList> LinkFactory(const LinkedList &node);
    std::shared_ptr<LinkedList> CreateStartNode(const T &data);
    std::shared_ptr<LinkedList> CreateNode(const T &data, const LinkedList &node);
};

发生错误的特定行是:

LinkedList<T>::LinkedList(const LinkedList<T> &object) : data(object.data),  
link(std::move(object.link)) {}

我试图移动而不是复制复制构造函数内的链接,但无济于事。 如果移动构造函数是设计而不是合成的,那会更好吗?

你不能

移动常量对象,而且由于object被声明为const,object.link也是const。

这看起来像是一个损坏的设计,因为通常该构造函数是一个复制构造函数,但您试图将链接移出参数,这意味着您试图窃取它拥有的资源。你有一个 LinkFactory 方法,看起来你应该使用它,如果它做到了名称所承诺的。

采用lvalue引用的构造函数是复制构造函数,而不是移动构造函数。如果引用const则无法修改现有对象,因此无法从中移动。(你不应该删除const,因为这会给你一个奇怪的破坏性复制语义,并且移动语义被添加到语言中以避免这种奇怪)。

由于unique_ptr成员,您的类不可复制,因此您根本不应提供复制构造函数。您可以提供一个移动构造函数:

LinkedList<T>::LinkedList(LinkedList<T> && object) : 
    data(object.data), link(std::move(object.link)) {}

但是没有必要,因为隐式生成的移动构造函数会这样做(唯一的区别是数据是移动而不是复制)。

请记住,通常,命名变量无法移动,除非您明确这样做:

LinkedList<int> l1;
LinkedList<int> l2(l1);             // ERROR: tries to copy
LinkedList<int> l3(std::move(l1));  // OK: explicit move

您要实现的语义是什么? 在您的副本中构造函数,则const要复制的对象(即通常正确);尝试在其中移动任何东西都需要它是非恒量。 这看起来像是一个设计缺陷,但如果不是,将链接mutable可能是答案。

我定义我的复制构造函数如下,并且使用unique_ptr没有编译时或链接错误:

LinkedList<T>::LinkedList(const LinkedList &other){
data = other.data;
link(std::move(other.link.get()));
}

我感谢大家回答这个问题。