13 мар. 2009 г.

Оператор «подёргивания»


Начнём-с с C:
main(){
int i = 0;
--i++;
}
при попытке собрать:
$ gcc main.c -o main
main.c: In function 'main':
main.c:3: error: lvalue required as decrement operand

Внимательно читаем о Lvalue:
In C, the term L-value originally meant something that could be assigned to (coming from left-value, indicating it was on the left side of the = operator)

Т.о. декремент должен быть применён к lvalue, но для Си i++ не есть lvalue.
Схожая ситуация и с Java, javascript.

C++ так же ругается на ошибку, но если расставить скобки, то код работает.
#include <iostream>
int main(){
int i = 0;
std::cout << "(--i)++: " << (--i)++ << ", i: " << i << std::endl;
}

$ g++ main.cpp -o main && ./main 
(--i)++: -1, i: 0

В C++ действует т.н. временная переменная, которой и происходит присваивание временного же значения, которая в итоге будет присвоена обратно i.

А вот, что google выдаёт по запросу "(--i)++" lang:c++:
 805:   {
intelhex::lst_dblock::const_iterator prev = (--i)++; //Get an iterator to the previous element w/o changing i
//Check for gaps between blocks and fill them with NOP's


Логично, предположить, что схожим образом будут действовать и итераторы, для которых определены операции инкремента и декремента:
#include <iostream>
#include <vector>

int main(){
std::vector<int> v;
v.push_back( 5 );
v.push_back( 7 );
v.push_back( 9 );

for(std::vector<int>::iterator it = v.begin(); it != v.end(); ++it){
if (it != v.begin())
std::cout << "prev:" << *(--it)++ << std::endl;
std::cout << *it << std::endl;
}
}
Результат:
5
prev:5
7
prev:7
9


ps. Вот такой вот он «красивый» этот C++ - и как только ещё смеют говорить C++шники, что тернарный оператор сложно читать...

Комментариев нет: