Преобразование Lvalue в rvalue для типов классов: происходит ли копирование?

(Я задавал этот вопрос раньше, но не привел жизнеспособного примера, поэтому я удалил предыдущий. Надеюсь, что на этом я понял пример правильно.)

Случай:

#include <iostream>

struct S
{
S() = default;

S(const S &)
{
std::cout << "Copying" << std::endl;
}

S& operator=(const S &)
{
std::cout << "Copy assignment" << std::endl;
return *this;
}
};

int main()
{
S s{};
S s2{};
S &ref = s;
ref = s2;
}

Насколько я понимаю, ref = s2; включает в себя преобразование l2r, так как это «встроенное прямое присваивание», ожидаемое для каждой ссылки, и rvalue в качестве правильного аргумента.

Я читал некоторые из SO вопросов, касающихся преобразования lvalue в rvalue, но я все еще не уверен, было ли это связано с копированием объектов, и если да, то что это за копирование.

Допустим, мы говорим о типах классов.

Из [conv.lval] / 2:

В противном случае, если T имеет тип класса, преобразование копирует и инициализирует временное значение типа T из glvalue, и результат преобразования является предварительным значением для временного.

Итак, инициализация копирования включена как часть преобразования lvalue-to-rvalue.

Итак, на примере ref = s2;с определяемым пользователем конструктором копирования, например, печатает «Копирование», будет ли печататься «Копирование» во время выполнения вышеупомянутого оператора?

Ну, очевидно, это не так. Но это означает, что я что-то здесь неправильно понимаю.

Является ли инициализация копирования во время преобразования lvalue-в-значение чем-то вроде простой memcpy, а не инициализацией копирования в полном смысле этого слова?

Как все это работает? 🙂

0

Решение

Насколько я понимаю, ref = s2; включает в себя преобразование l2r, так как это «встроенное прямое присваивание», ожидаемое для каждой ссылки, и rvalue в качестве правильного аргумента.

Ваша ошибка в интерпретации оператора присваивания здесь встроенная. Это не. Единственными типами, которые имеют встроенный оператор присваивания, являются фундаментальные типы (указатели, char, intи т. д.) Имеется тип класса, который имеет перегруженный оператор присваивания (предоставленный пользователем или неявно сгенерированный компилятором).

ref = s2; просто вызывает S::operator=(S const&), Он ведет себя так, как будто вы только что набрали ref.operator=(s2), В реализации этой функции нет преобразования lvalue в rvalue, поэтому никакая другая копия не создается. Все, что происходит, это то, что строка печатается. Нет дополнительной инициализации копии и т. Д.

Если вы реализовали свой оператор присваивания по-другому, как:

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

Затем произойдет преобразование lvalue в rvalue для фактического вызова этой функции, и вы увидите, как вызывается ваш конструктор копирования.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]