(Я задавал этот вопрос раньше, но не привел жизнеспособного примера, поэтому я удалил предыдущий. Надеюсь, что на этом я понял пример правильно.)
Случай:
#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, а не инициализацией копирования в полном смысле этого слова?
Как все это работает? 🙂
Насколько я понимаю,
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 для фактического вызова этой функции, и вы увидите, как вызывается ваш конструктор копирования.
Других решений пока нет …