Я часто сталкиваюсь с этой проблемой, и я считаю, что конструктор перемещения в порядке, но я думаю, что конструктор копирования — это проблема, и его скрытие, похоже, не работает.
Код:
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
также является постоянным.
Это похоже на сломанный дизайн, так как обычно этот конструктор копия конструктор, но вы пытаетесь переехать ссылка вне параметра, то есть вы пытаетесь украсть принадлежащие ему ресурсы. У вас есть метод 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()));
}
Я благодарю всех за ответ на этот вопрос.