このトピックは次のトピックの続編として考えてください。
前回の記事
未定義の動作とシーケンスポイント
これをもう一度考えてみましょう面白いそして複雑な表現(イタリック体のフレーズは上記のトピックから引用したものです *笑* ):
i += ++i;
これは未定義の動作を引き起こすと言います。これを言うとき、私たちは暗黙のうちに次のことを想定していると思います。タイプof はi
組み込み型の 1 つです。
もし、タイプof はi
ユーザー定義型ですか? その型がIndex
この投稿の後半で定義される (下記参照) とします。それでも undefined-behavior が呼び出されるでしょうか?
もしそうなら、なぜですか? と書くことと同等ではないのですi.operator+=(i.operator++());
か、あるいは構文的にはもっと単純ではありませんかi.add(i.inc());
? それとも、それらも未定義の動作を呼び出しますか?
いいえ、なぜですか?結局、オブジェクトはi
変更されます2回連続するシーケンスポイント間。経験則を思い出してください。式は連続する「シーケンスポイント」間でオブジェクトの値を1回だけ変更できる。i += ++i
が式である場合、未定義の動作を呼び出す必要があります。そうであれば、それと同等のi.operator+=(i.operator++());
およびi.add(i.inc());
も未定義の動作を呼び出す必要がありますが、これは正しくないようです。(私の理解する限り)
i += ++i
あるいは、表現そもそも何なのか?もしそうなら、それは何であり、その定義は何なのか?表現?
それが表現であり、同時にその動作がまた明確に定義されている場合、表現に関連付けられたシーケンスポイントの数は、タイプ式に含まれるオペランドの数。私の考えは(部分的にでも)正しいでしょうか?
ちなみに、こんな表現はどうでしょうか?
//Consider two cases:
//1. If a is an array of a built-in type
//2. If a is user-defined type which overloads the subscript operator!
a[++i] = i; //Taken from the previous topic. But here type of `i` is Index.
応答では、この点も考慮する必要があります (動作を確実に把握している場合)。 :-)
は
++++++i;
C++03で明確に定義されているか?結局のところ、これはこれです、
((i.operator++()).operator++()).operator++();
class Index
{
int state;
public:
Index(int s) : state(s) {}
Index& operator++()
{
state++;
return *this;
}
Index& operator+=(const Index & index)
{
state+= index.state;
return *this;
}
operator int()
{
return state;
}
Index & add(const Index & index)
{
state += index.state;
return *this;
}
Index & inc()
{
state++;
return *this;
}
};
ベストアンサー1
コードのようです
i.operator+=(i.operator ++());
シーケンス ポイントに関しては完全に正常に動作します。C++ ISO 標準のセクション 1.9.17 では、シーケンス ポイントと関数の評価について次のように述べられています。
関数を呼び出す場合 (関数がインラインであるかどうかに関係なく)、関数本体の式またはステートメントの実行前に行われるすべての関数引数 (存在する場合) の評価後にシーケンス ポイントが発生します。また、戻り値がコピーされた後、関数の外部の式の実行前にもシーケンス ポイントが発生します。
i.operator ++()
これは、たとえば、 のパラメータとしての評価後にシーケンス ポイントがあることを示しますoperator +=
。つまり、オーバーロードされた演算子は関数であるため、通常のシーケンス ルールが適用されます。
ところで、素晴らしい質問ですね!私がすでに知っていると思っていた(そして知っていると思っていた)言語のニュアンスをすべて理解するように強制しているところが本当に気に入っています。 :-)