Объясните, пожалуйста, почему выполняется my_int++ = ++my_int; в приведённом ниже примере.
Для встроенных типов постфиксный инкремент возвращает r-value.
Тут, насколько я понимаю, после выполнения постфиксного ++ создается временная копия объекта, которая будет разрушена после ; (выход из scope).
И она l-value (?).
Распишите, пожалуйста механизмы происходящего. Запутался.
Здравствуйте, BugZ, Вы писали:
BZ>Здравствуйте, Константин Л., Вы писали:
КЛ>>//copy ctor и operator = совчем не обяз. определять. Дефолтные сойдут
BZ>Были определены исключительно для удобства отладки.
BZ>>> my_int++ = ++my_int; //UB
BZ>Что означает UB?
Undefined bеhavior — неопределнное поведение. В двух словах — результат работы твоей программы не определен.
Причем этот вопрос появляется с регулярностью в месяц.
Искать по ключевым словам: UB, точки следования, sequence points
Re[3]: Постфиксный инкремент для пользовательского типа.
Здравствуйте, BugZ, Вы писали:
BZ>Здравствуйте, Константин Л., Вы писали:
BZ>>>>> my_int++ = ++my_int; //UB
BZ>С неопределенным поведением понятно, благодарю... А если как-нибудь упростить пример:
Результат identity(x) — non-const rvalue. Отсюда всё и следует. То, что выражение — rvalue, будет влиять только в том случае, если кто-то попытается напрямую взять его адрес. Хотя адрес у него есть и добыть его можно, см. ниже. В данном же выражении всего лишь вызывается (неконстантная) функция-член, а именно operator =.
Это на самом деле удобно, например:
std::string s = getSomePath() /* rvalue */ .replace(0, 4, "/tmp") /* то же самое rvalue -- избежали копирования */;
Поэтому я против возвращения константных значений из функций. Всё равно, что запирать на замок чемодан, выбрасываемый на свалку.
На грабли с rvalue наступают ленивые программеры, которые пишут так:
Казалось бы — замечательный способ открыть файл, записать туда строчку и сразу же его закрыть. Но на самом деле эта инструкция выводит совсем другое. Почему?
С какой это радости undefined? Максимум, unspecified. Тип-то пользовательский, и операторы перегружены.
Это такой тест на замыленность сознания экспертов Как увидел кучу инкрементов, так сразу UB.
Причина в другом.
Здесь выражение выглядит так
x++ = ++x;
// предстаёт как
x.post_increment().assignment( x.pre_increment() );
У rvalue x.post_increment() можно вызвать неконстантный метод assignment(). А вот превратить rvalue в неконстантное lvalue нельзя.
Т.е. если бы, например, было
MyInt& operator += (MyInt& lhs, MyInt const& rhs);
// = всегда трактуется как член (даже если определён неявно), и его нельзя сделать внешним.
// остальные - можно.
x++ += ++x;
то компилятор бы справедливо выругался.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[3]: Постфиксный инкремент для пользовательского типа.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Константин Л., Вы писали:
К>С какой это радости undefined? Максимум, unspecified. Тип-то пользовательский, и операторы перегружены.
К>Это такой тест на замыленность сознания экспертов Как увидел кучу инкрементов, так сразу UB.
К>Причина в другом. К>Здесь выражение выглядит так К>
К>x++ = ++x;
К>// предстаёт как
К>x.post_increment().assignment( x.pre_increment() );
К>
ну чтож...согласен
Re[2]: Постфиксный инкремент для пользовательского типа.