operator =シーケンスポイントにならない正当な理由はありますか? C と C++ の両方で。
反例を考えるのが苦手です。
リクエストにより:
一般に、物事はシーケンスポイントである理由が必要です。シーケンスポイントにならない理由は必要ありません。これがデフォルトです。
たとえば、&&短絡動作のためにシーケンスポイントである必要があります。左側がfalseの場合、右側を評価してはなりません。(これは最適化だけではありません。右側が副作用をもたらす可能性があり、および/またはのように左側が真であることに依存する可能性がありますptr && ptr->data。)したがって、右側の前に左側を最初に評価する必要があります-右側、右側を評価する必要があるかどうかを確認するため。
この理由は存在しません。=なぜなら、両側に対して行う「評価」がありますが(ただし、両側に表示できるものにはさまざまな制限があります。左側は左辺値である必要があります。これlは「 left "、btw;これは" location "の略で、メモリ内の場所のように-一時的またはリテラルに割り当てることはできません)、どちらの側が最初に評価されるかは関係ありません-両方の側が前に評価される限り実際の割り当て。
どちらかの側をもう一方の前に評価する必要がない理由はたくさんあります。さらに興味深い質問は、代入演算子自体が何かを行う前に、副作用を含む両側の評価が必要かどうかです。このような要件により、エイリアシングの制限が緩和されることをお勧めしますが、場合によっては、コンパイラーにより多くの作業が必要になります。たとえば、「foo」と「bar」が、アドレスが重複する大きな構造体へのポインタであるとします。ステートメント「*foo=*bar;」現在の標準では未定義の動作を表します。オペランドの評価と割り当ての間にシーケンスポイントがあった場合、そのようなステートメントは「機能する」ことが保証されます。このような保証は、代入演算子にとってより複雑なものを必要とします。
例:
unsigned char foo [100];
typedef struct {int x、int y;} POINT;
POINT * p1 =(POINT *)foo;
POINT * p2 =(POINT *)(&(p1-> y));
上記の宣言を踏まえると、次のステートメントには厳密に定義された動作が示され、未定義の動作は含まれていないと思います。
p1->y=何らかの値; //p2->xをある値に設定します p2->x=ある値; //p1->yをある値に設定します * p1 = mystruct; //p2->xをmystruct.yに設定します * p2 = mystruct; //p1->xをmystruct.xに設定します
ただし、次の2つのステートメントには、未定義動作が含まれます。
* p1 = * p2; * p2 = * p1;
等号にシーケンスポイントがある場合、コンパイラはp1とp2を比較するか、ソースオペランドを一時的な場所にコピーしてから宛先にコピーする必要があります。ただし、この標準では、上記の2つのステートメントは両方とも未定義動作と見なされることが明確になっています。この標準では、構造体を重複しない構造体にコピーするときに正しく機能するコードをコンパイラーが生成する必要がありますが、構造体が重複する場合にコンパイラーが実行できることには制限がありません。「FrinkRules!」を送信するループにプロセッサを入れるコンパイラ。開いているすべてのTCPソケットは、そうすることで標準に違反することはありません。
それは(一種の)です。operator= (エンジニアが定義できるもの (別名、クラス タイプのユーザー定義 operator=)) は、関数呼び出しの単なる構文糖衣です。その結果、関数呼び出しと同じ「シーケンス ポイント」セマンティクスを持ちます。
組み込み型について考えるのであれば、それは良いことだと思います。
最適化の妨げになるため、あまり多くのシーケンス ポイントを導入することは望ましくありません。