Код ниже демонстрирует это различие:
#include <iostream>
#include <string>
int main()
{
char s[] = "ABCD";
std::string str(s);
char *p = s;
while(*p) {
*p++ = tolower(*p); // <-- incr after assignment
}
std::cout << s << std::endl;
std::string::iterator it = str.begin(), end = str.end();
while(it != end) {
*it++ = tolower(*it); // <-- incr before assignment ?
}
std::cout << str << std::endl;
return 0;
}
это производит вывод:
abcd
bcd
если мы разделяем операцию присвоения и увеличиваем оператор:
while(it != end) {
*it = tolower(*it); // <-- incr before assignment ?
it++;
}
вывод будет как ожидалось.
Что случилось с исходным кодом?
$ g++ --version
g++ (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
Copyright (C) 2004 Free Software Foundation, Inc.
Проблема в том, что порядок вычисления аргументов operator =
не указан. Это соответствует стандарту C ++ 5.2.2 / 8. Рассмотрим следующее:
*it++ = tolower(*it);
равно
operator=( *it++, tolower(*it) );
Теперь * it ++
может быть вычислено до tolower (* it)
и наоборот.
Грамматика работает точно так же для указателей и итераторов. Операции, подразумеваемые операторами, превращаются в вызовы функций для объектов типа класса (таких как большинство итераторов).
Проблема с вашим кодом не в приоритете операторов, хотя в обеих этих строках нет последовательности между операцией приращения и вторым чтением той же переменной, которая увеличивается в другом месте в операторе. Из-за этого у вас неопределенное поведение, поэтому он может видеть любое поведение вашей программы, включая результаты, которые вы видите.
*p++ = tolower(*p);
*it++ = tolower(*it);
Вам необходимо переформулировать это утверждение таким образом, чтобы определить последовательность. Я предполагаю, что вы хотите что-то вроде этого.
char c = tolower(*p);
*p++ = c;
*it++ = tolower(*it);
*p++ = tolower(*p);
Обе эти строки вызывают неопределенное поведение. Вы не можете изменить значение переменной более одного раза в одном операторе (++ изменяет один раз, operator = изменяет дважды).
Поэтому неудивительно, что вы получаете разные значения.