15 Mart 2019 Cuma

C++'ta Sequence Point

C++'ta "Order of Evaluation" işleminin tanımsızlığına rağmen bazı işlemlerin hangi sırada çalışacağı belirlenmiştir. Bu işlemlere sequence point adı verilir. Bazı kitaplarda sequence pointler'in sayısı az gösteriliyor. Ama toplamda 7 tane var.

Assignment Operator Sequence Point'i
Atama işleminden önce sağ tarafın hesaplanması gerekir.
In all cases, the assignment is sequenced after the value computation of the right and left operands,and before the value computation of the assignment expression.
Örnek
Bu yüzden şu işlem tanımlı bir davranış sunar.
++x %= 10;
İşlem şuna denk gelir. Önce x'in değeri 1 artırılır. Sonra x % 10 yapılır ve sonuç yine x değişkenine atanır.

Overloaded Assignment Operator
Açıklaması şöyle.
Before C++17 there was no sequencing between the left- and right-hand side of overloaded assignment operators.
It's first in C++17 that explicit sequencing was introduced (right-hand side is evaluated first).
C++14 ile şu kod map içinde bir key yaratabilir.
map<int, set<string>> junk;
for (int id : GenerateIds()) {
  try {
    junk[id] = GetStuff(); //exception fırlatsa bir junk'a id key eklenebilir.
  } catch (const StuffException& e) {
    ...
  }
}
Comma Operator Sequence Point'i
Comma Operator Sequence Point'i yazısına taşıdım

&& ve || Operator Sequence Point'i
Comma operator gibi işleme soldan sağa doğrudur. Bu yüzden
x = i++ && i++
tanımlı bir koddur.
x = i++ * i++
ise tanımsızdır.

<< Operator Sequence Point'i
Örnek
Şöyle bir örnek olsun
struct S {
  S(int);
};
int operator<<(S, int);
int i, j;
int x = S(i=1) << (i=2);
int y = operator<<(S(j=1), j=2);
Açıklaması şöyle
After performing the initializations, the value of i is 2 (see [expr.shift]), but it is unspecified whether the value of j is  1 or 2.
Aynı kodu şöyle de yazılabilir.
a << b;
operator<<(a, b);
Açıklaması şöyle
The two different syntaxes have different semantics now. The operator syntax has its peculiar semantics, the function call syntax has the (new!) semantics of function calls.
?: Sequence Point'i
Comma operator gibi işlem soldan sağa doğrudur.
Örnek
Şöyle yaparız.
int val = (++i > ++j) ? ++i : ++j;
Örnek
Bu yüzden
cout << (x == 0 ? x++ : x) << endl; //operator in branch
tanımlı bir koddur.

Diğer
C++11 ile bazı değişiklikler yapılmış. Şu kodda aynı satırda değişlen birden fazla değişmesine rağmen artık undefined behavior değil.
#include <iostream>
using namespace std;

int main()
{
  int i = 0;
  cout<<++++++i<<endl;
}

Hiç yorum yok:

Yorum Gönder