2015-06-26 12 views
16

Na przykład:i = i ++; jest niezdefiniowany. Czy i = foo (i ++) również jest niezdefiniowane?

int foo(int i) { return i; } 

int main() 
{ 
    int i = 0; 

    i = i++;  // Undefined 
    i = foo(i++); // ? 

    return 0; 
} 

Co obecna norma ISO C++ byłoby określić w tym przypadku?

EDIT:

Oto gdzie mogę się mylić:

ile nie zaznaczono inaczej, oceny argumentów poszczególnych operatorów i podwyrażeń poszczególnych wyrażeń są unsequenced.

przypadku efektem ubocznym w skalarnej przedmiotu jest unsequenced względem albo innego efektu siebie na tej samej skalarnej obiektu lub obliczania wartości stosując wartość samej skalarnej obiektu i nie są one potencjalnie zbieżnego (1.10) nieokreślone jest zachowanie .

We wszystkich przypadkach przyporządkowanie jest zsekwencjonowany po wartość obliczania prawo i lewo argumentów, a przed obliczania wartości wyrażenia przypisania

Każda ewaluacja w funkcji wywołującej (w tym innych wywołań funkcji), które w innym przypadku nie jest specyficznie oznaczony przed lub po wykonaniu treści wywoływanej funkcji w sposób nieokreślony sekwencyjnie z względem wykonania wywoływanej funkcji.

Więc wydaje się, że można mieć do obliczenia wartości po lewej stronie przypisania (tylko i), a efekt uboczny po prawej stronie (modyfikacja i z i++), które nie są wyświetlane sekwencyjnie w odniesieniu do siebie nawzajem.

EDIT2:

Dla każdego, kto znajdzie się tutaj, jest naprawdę świetny wyjaśnienie o sekwencjonowanie że znalazłem here.

+5

'foo (i ++)' jest w porządku, 'foo (i, i ++)' jest niezdefiniowane –

+0

foo (i ++) tworzy kopię, nie zwiększając jej wartości, jeśli spróbujesz wydrukować i po wywołaniu funkcji. Ale foo (++ i) faktycznie to robi. Spójrz na zbiór –

+1

'foo (i ++)' jest w porządku, 'foo ((i, i ++))' jest również w porządku. – haccks

Odpowiedz

15

Ostatnie zdanie w swoim cytatem mówi „który nie jest inaczej zsekwencjonowany przed lub po wykonaniu korpusu zwanej funkcji” więc pytanie o to, czy przyrost i przypisanie są "inaczej sekwencyjnie sekwencjonowane przed lub po" ciele funkcji.

1,9 [intro.execution] p15 ma odpowiedź:

Przy wywołaniu funkcji (czy funkcja jest inline), co obliczanie wartości i niepożądanym związane z każdym ekspresji argumentu lub z wyrażenie postfiksowe określające wywoływaną funkcję, jest zsekwencjonowane przed wykonaniem każdego wyrażenia lub instrukcji w treści wywoływanej funkcji.[] Uwaga: Wartość i skutki uboczne powiązane z różnymi wyrażeniami argumentów są niesekwencjonowane. - koniec uwaga]

Więc przyrost i dzieje przed ciele funkcji i przypisanie do i dzieje po powrocie funkcji, więc jest doskonale zdefiniowane.

W terminologii przed C++ 11 wywołanie funkcji wprowadza punkt sekwencji między przyrostem a przydziałem.

+0

Czy możesz sprawdzić moją edycję? Do przypisania: "zadanie jest sekwencjonowane po obliczeniu wartości prawego i lewego argumentu". Więc możesz mieć obliczenia wartości po lewej stronie zadania, po prostu 'i'. Następnie możesz ocenić 'i ++' przed wywołaniem funkcji 'foo'. Spowodowałoby to obliczenie wartości na "i" oraz efekt uboczny z przyrostu, które są nieoddzielne względem siebie, co jest niezdefiniowanym zachowaniem. – Justin

+0

Ze standardu: "obliczenia wartości (w tym określenie tożsamości obiektu do oceny wartości i pobranie wartości poprzednio przypisanej do obiektu do oceny wartości)." – Justin

+0

Kluczem jest to, że nie ma żadnego efektu ubocznego dla obliczenia wartości lewej strony, a wartość LHS nie jest potrzebna. Jest to ocena l-wartości, więc po prostu określa tożsamość obiektu. Efekt uboczny występuje tylko po powrocie funkcji i musi to być po ocenie argumentu funkcji. "Jeśli ** efekt uboczny na obiekcie skalarnym ** nie jest zmieniony w stosunku do __innego efektu ubocznego dla tego samego obiektu skalarnego__ lub obliczenia wartości ** przy użyciu wartości tego samego obiektu skalarnego ** i nie są one potencjalnie współbieżne (1.10), ** zachowanie jest niezdefiniowane. ** " –

11

i = foo(i++); jest w porządku, ponieważ i++ jest wykonywane przed wywołaniem foo(). Wykonano kopię i, a następnie i została zwiększona, a następnie kopia została przekazana do foo(). To jest tak samo jak robi to wyraźnie:

int tmp = i++; 
i = foo(tmp); 
Powiązane problemy