- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
void iseq(int a, int b){ assert(a==b); }
void ismt(int a, int b){ assert(a+1==b); }
int main(int argc, char **argv){
{ int j=100, *jp; jp=&argc; iseq(j++, j); assert(j==101); } //100, 100
{ int j=100, *jp; iseq(j++, j); jp=&j; assert(j==101); } //100, 100
{ int j=100, *jp; iseq(j++, j); assert(&j && j==101); } //100, 100
{ int j=100, *jp; ismt(j++, j); assert(j==101); } //100, 100
{ int j=100, *jp; jp=&j; printf("\n%d, %d\n", j++, j); assert(j==101); } //100, 100
{ int j=100, *jp; printf("%d, %d\n", j++, j); jp=&j; assert(j==101); } //100, 100
{ int j=100, *jp; printf("%d, %d\n", j++, j); assert(&j && j==101); } //100, 100
{ int j=100; printf("%d, %d\n", j++, j); assert(j==101); } //100, 101
{ int j=100, *jp; jp=&j; printf("\n%d, %d\n", ++j, j); assert(j==101); } //101, 100
{ int j=100, *jp; printf("%d, %d\n", ++j, j); jp=&j; assert(j==101); } //101, 100
{ int j=100; printf("%d, %d\n", ++j, j); assert(j==101); } //101, 101
return 0;
}
Кто нибудь знает почему ЭТО работает так? Проверял на нескольких компиляторах везде такой эффект.
Когда адрес переменной не нужен - конпелятор может засунуть переменную в регистр и даже не выделять под неё память. Когда берёшь адрес - волей-неволей приходится юзать настоящую переменную. Вот тебе и другие оптимизации с другим поведением.
З.Ы. И если ты поюзал что-то, что в стандарте обозначено как undefined (а порядок вычисления аргументов как раз таки не определён) - на результат даже фаза луны влиять будет, не то что взятие адреса...
Ты знал, что make_shared сделали не только для оптимизации пирфоманса? Вызов
может течь, если bar() бросает исключения. Потому что код может выполняться в последовательности 1) new 5; 2) bar(); 3) std::shared_ptr(...).
Но при чем здесь shared_ptr? я не знаю что это
Ответа foo(koko(bar()), baz()) вполне достаточно.
не совсем
память выделенная на стеке, освободится в том числе в случае исключения, но в примере с shared_ptr - память выделяется через new в куче, её нужно освобождать через delete, это должен сделать сам shared_ptr, но из-за исключения до него дело не дойдёт.
http://coliru.stacked-crooked.com/a/3b10ae5964ab8cc2
http://coliru.stacked-crooked.com/a/3251602c5a8a92e8
Обрати внимание, как шланг без всяких флагов сообщил, что в коде баг.
У gcc как оказалось это предупреждение по умолчанию выключено. С "-Wall" он выдал такие же предупреждения что и clang.
g: sequence point
А ведь уже несколько поколений сишников и крестовиков сталкиваются с подобными UB! Так и представляю картину - камин, кресло-качалка, в нём сидит дедушка и внуку рассказывает: "А вот как-то кодил я на плюсах, да угораздило-ж меня два инкремента в одну точку следования всунуть!..".
Можно найти условия, при которых и один инкремент сглючит. Надо всего лишь в том же выражении использовать ту же переменную ещё раз.
Преинкремент по идее должен быть менее коварным, чем постинкремент, но оптимизация может помочь испортить и его.