Re: Постфиксный инкремент для пользовательского типа.
От: Roman Odaisky Украина  
Дата: 09.04.07 13:21
Оценка: 5 (2) +1
Здравствуйте, BugZ, Вы писали:

BZ>Объясните, пожалуйста, почему выполняется my_int++ = ++my_int; в приведённом ниже примере.


Я понимаю, затруднения вызывает вот такое?
template <class X>
X identity(X x)
{
    return x;
}

int main()
{
    std::string s1("hello");
    std::string s2("world");
    identity(s1) = s2; // no-op

    std::cout << s1 << " " << s2 << std::endl; // hello world
}

Результат identity(x) — non-const rvalue. Отсюда всё и следует. То, что выражение — rvalue, будет влиять только в том случае, если кто-то попытается напрямую взять его адрес. Хотя адрес у него есть и добыть его можно, см. ниже. В данном же выражении всего лишь вызывается (неконстантная) функция-член, а именно operator =.

Это на самом деле удобно, например:

std::string s = getSomePath() /* rvalue */ .replace(0, 4, "/tmp") /* то же самое rvalue -- избежали копирования */;


Поэтому я против возвращения константных значений из функций. Всё равно, что запирать на замок чемодан, выбрасываемый на свалку.



На грабли с rvalue наступают ленивые программеры, которые пишут так:
std::ofstream("/tmp/file") << "hello" << std::endl;

Казалось бы — замечательный способ открыть файл, записать туда строчку и сразу же его закрыть. Но на самом деле эта инструкция выводит совсем другое. Почему?
ostream& ostream::operator <<(void const *); // выводит адрес
ostream& operator <<(ostream &, char const *); // выводит строку

Который из них вызовется? Неконстантные ссылки к rvalue не привязываются, поэтому второй оператор выпадает из рассмотрения!

Чтобы вышеуказанный элегантный метод заработал, надо взять адрес rvalue-выражения std::ofstream("/tmp/file"). Легко:
ostream& ostream::flush();

Вот и адрес, voilà:
std::ofstream("/tmp/file").flush() << "hello" << std::endl;
До последнего не верил в пирамиду Лебедева.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.