Стандарты программирования на С++. 101 правило и рекомендация | страница 54



аргумент 0 или 1:

>int i = 0;

>f(i++), g(i); //См. также рекомендацию 31

Примеры

Пример. Инициализация библиотеки при помощи перегруженного оператора >operator, для последовательности инициализаций. Некоторая библиотека пытается упростить добавление нескольких значений в контейнер за один раз путем перегрузки оператора-запятой. Например, для добавления в >vector letters:

>set_cont(letters) += "a", "b";

Все в порядке, пока в один прекрасный день пользователь не напишет:

>set_cont(letters) += getstr(), getstr();

>// порядок не определен при использовании

>// перегруженного оператора ","

Если функция >getstr получает, например, ввод пользователя и он введет строки >"с" и >"d" в указанном порядке, то в действительности строки могут оказаться внесены в любом порядке. Это может оказаться сюрпризом, поскольку при использовании встроенного оператора >operator, такой проблемы не возникает:

>string s; s = getstr(), getstr(); // порядок строго определен

>// при использовании

>// встроенного оператора ","

Исключения

Исключение — специализированные библиотеки шаблонов для научных вычислений, которые в соответствии с дизайном переопределяют все операторы.

Ссылки

[Dewhurst03] §14 • [Meyers96] §7, §25 • [Murray93] §2.4.3 • [Stroustrup00] §6.2.2

31. Не пишите код, который зависит от порядка вычислений аргументов функции

Резюме

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

Обсуждение

На начальных этапах развития языка C регистры процессора были драгоценным ресурсом и компиляторы решали трудные задачи эффективного их использования в сложных выражениях высокоуровневых языков. Для того чтобы позволить компилятору генерировать более быстрый код, создатели C дали распределителю регистров дополнительную степень свободы. При вызове функции порядок вычисления ее аргументов оставался неопределенным. Эта аргументация, вероятно, существенно менее важна в настоящее время, но главное, что порядок вычисления аргументов функций в C++ не определен и варьируется от компилятора к компилятору (см. также рекомендацию 30).

В связи с этим необдуманные действия программиста могут привести к большим неприятностям. Рассмотрим следующий код:

>void Transmogrify(int, int);


>int count = 5;

>Transmogrify(++count, ++count); // Порядок вычислений

>                                // неизвестен

Все, что мы можем сказать определенного, — это то, что при входе в тело функции