Использование приращения префикса или постфикса (или уменьшения)

Я нашел, что этот код является примером использования запятой в книге на С++ (С++ Primer, 5th Edition):

vector<int>::size_type cnt = ivec.size();
// assign values from size...1 to the elements in ivec
for(vector<int>::size_type ix = 0; ix != ivec.size(); ++ix, --cnt)
    ivec[ix] = cnt;

Я не думаю, что это подходящий пример, потому что порядок оценки, эффекты здесь не имеют значения. Комман-оператор просто позволяет отделить выражения приращения и декремента, которые являются обычным использованием оператора запятой, но не намерение этого раздела в книге. Лучше пример показан на cppreference.com (прокрутите вниз до заголовка Встроенный оператор запятой).

На самом деле я нахожусь в следующем упражнении:

Упражнение 4.31. Программа в этом разделе использовала приращения приращения и сокращения. Объясните, почему мы использовали префикс, а не постфикс. Какие изменения необходимо внести, чтобы использовать постфикс версии? Перепишите программу с помощью постфиксных операторов.

В этом случае нет особых причин предпочитать префикс над операторами постфикса. Порядок оценки не имеет значения. Манипуляция объектами с типом simple типа vector<int>::size_type не должна использоваться на практике при использовании префикса поверх постфикса, поэтому просто известное соглашение предпочитает префикс поверх постфикса, если это имеет значение.

Чтобы дать вам полный контекст, здесь раздел из книги:

4.10 Comma Operator
Оператор запятая принимает два операнда, которые он оценивает слева направо. Подобно логическим И и логическое ИЛИ и условный оператор, оператор запятой гарантирует порядок, в котором его операнды оцениваются.

Левое выражение оценивается и его результат не выполняется. Результатом выражения запятой является значение его правого выражение. Результатом является lvalue, если правый операнд является именующий. Одно общее использование для оператора с запятой находится в цикле for:

vector<int>::size_type cnt = ivec.size();  
// assign values from size...1 to the elements in ivec  
for(vector<int>::size_type ix = 0; ix != ivec.size(); ++ix, --cnt)  
    ivec[ix] = cnt;  

Этот цикл увеличивает ix и уменьшает cnt в выражении в для заголовка. Как ix, так и cnt изменяются при каждой поездке через петля. Пока тест ix преуспевает, мы reset next текущий элемент к текущему значению cnt.

Я прав? Или я просто не понимаю цели этого упражнения?

Ответ 1

Вы правы в использовании префикса или постфиксного оператора инкремента в этом примере не имеет значения, но С++ Primer также говорит, что использовать постфиксную версию, когда это действительно необходимо, в качестве лучшей практики, я цитирую книга из §4.5. Операторы приращения и сокращения

Совет. Используйте только операторы Postfix. Когда необходимо

Читатели из фона C могут быть удивлены тем, что мы используем приращение префикса в написанных нами программах. Причина проста: префиксная версия позволяет избежать ненужной работы. Он увеличивает значение и возвращает инкрементную версию. Оператор постфикса должен сохранять исходное значение, чтобы он мог вернуть невыраженное значение в качестве результата. Если нам не нужна неосвещенная стоимость, вам не нужно делать дополнительную работу, выполняемую оператором postfix.

Для int и указателей компилятор может оптимизировать эту дополнительную работу. Для более сложных типов итераторов эта дополнительная работа потенциально может быть более дорогостоящей. Обычно используя префиксные версии, нам не нужно беспокоиться о том, имеет ли разница в производительности. Более того, и, что еще важнее, мы можем более непосредственно выразить намерение наших программ.