Вызов конструктора копирования внутри оператора присваивания, в качестве левого операнда присваивания требуется значение lvalue - PullRequest
0 голосов
/ 04 октября 2019

Я пытаюсь вызвать мой конструктор копирования в моей перегрузке оператора присваивания. Я присваиваю результат конструктора копирования указателю с именем temp, а затем устанавливаю указатель this равным temp. Этот результат дает мне ошибку: lvalue требуется как левый операнд присваивания. Я думал, что это указатель на мой объект. Почему возникает проблема с переназначением указателя на другой объект?

В проходящем случае я определяю это (* this) и устанавливаю его равным temp. Для меня это означает, что я говорю, что фактический объект равен указателю. Я неверно истолковываю значение этого слова?

Пропускающий регистр:

Foo *temp = new Foo(other); //invokes copy constructor
*this = temp;

Пропускающий регистр:

Foo *temp = new Foo(other); //invokes copy constructor
this = temp;

Полный исходный код:

TreeNode::TreeNode(TreeNode *other) {
    this->leftChild = other->leftChild;
    this->rightChild = other->rightChild;
    this->data = other->data;
}

TreeNode& TreeNode::operator=(TreeNode *other) {
    if(this != other) {
        TreeNode *temp = new TreeNode(other);
        this = temp;
    }
    return *this;
}

1 Ответ

0 голосов
/ 04 октября 2019

1) this - это встроенное выражение rvalue, которое есть у каждого класса (то есть оно не может быть изменено в соответствии со стандартом C ++), и оно всегда указывает на экземпляр класса (объекта), выполняющего вызов функции.

2) *this всегда является lvalue, то есть он должен иметь адрес в памяти, то есть он представляет объект, который может быть изменен.

Поэтому, когда вы разыменовываете это:

*this = temp

У вас есть lvalue, связанный с пробелом в памяти, но не с

this = temp

Для подробного обсуждения значений и этого:

Что такое«rvalue reference для * this»?

Тип указателя «this»

Таким образом, этот код кажется немного проблематичным. Рассмотрим, что происходит, когда вы делаете что-то вроде:

treenode1 = treenode2;  //assuming both are pointers to TreeNode objects

Компилятор видит lvalue treenode1 (к которому объект «this» всегда будет ссылаться во время операции), затем видит «=», замечает перегрузку,затем использует указатель treenode2 для создания НОВОЙ копии объекта, на который указывает treenode2 (привязывает значение lvalue temp к новому объекту), затем пытается скопировать значения в temp в исходный объект, связанный с treenode1 (у нас теперь есть три TreeNodes, Я верю).

Чего вы не хотите, так это чтобы временный объект зависал после выполнения этой запутанной операции, я полагаю, так как это могло бы вызвать утечку памяти. Так что вам нужно удалить его раньше. Поэтому, если вам по какой-то причине нужно было сделать это, решением является оператор присваивания перемещения, который предназначен для использования с временными объектами. Вероятно, лучше всего вообще избегать этого паттерна, однако он может привести к утечкам памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...