問題のコードは、メソッド呼び出しの連鎖を示しています。
<code class="cpp">std::string s = "but I have heard it works even if you don't believe in it" ; s.replace(0, 4, "" ).replace( s.find( "even" ), 4, "only" ) .replace( s.find( " don't" ), 6, "" ); assert( s == "I have heard it works only if you believe in it" ) ;</code>
ただし、Clang ではアサートが通過しても、GCC や Visual Studio などの特定のコンパイラではアサートが失敗します。
このコードは、関数の引数は順序付けられていない順序で評価されるため、部分式を評価する順序が指定されていません。連鎖関数呼び出しでは、各関数呼び出しに左から右の評価順序が導入されますが、各呼び出しの引数は、それらが属するメンバー関数呼び出しの前にのみ順序付けされます。
コード内の部分式 s .find("even") と s.find(" don't") は、s.replace(0, 4, "") に関して不定に順序付けされます。評価の順序によっては、潜在的な副作用により結果が異なる場合があります。
コードは次のように分類できます:
s.replace(0, 4, "" ) // A .replace( s.find( "even" ), 4, "only" ) // B .replace( s.find( " don't" ), 6, "" ); // C
A は B より前に順序付けされ、B は C より前に順序付けされます。項目 1 ~ 9 は、次の関係を除いて、相互に関して不定に順序付けされます:
<code class="cpp">std::string::size_type my_find( std::string s, const char *cs ) { std::string::size_type pos = s.find( cs ) ; std::cout << "position " << cs << " found in complete expression: " << pos << std::endl ; return pos ; } int main() { std::string s = "but I have heard it works even if you don't believe in it" ; std::string copy_s = s ; std::cout << "position of even before s.replace(0, 4, \"\" ): " << s.find( "even" ) << std::endl ; std::cout << "position of don't before s.replace(0, 4, \"\" ): " << s.find( " don't" ) << std::endl << std::endl; copy_s.replace(0, 4, "" ) ; std::cout << "position of even after s.replace(0, 4, \"\" ): " << copy_s.find( "even" ) << std::endl ; std::cout << "position of don't after s.replace(0, 4, \"\" ): " << copy_s.find( " don't" ) << std::endl << std::endl; s.replace(0, 4, "" ).replace( my_find( s, "even" ) , 4, "only" ) .replace( my_find( s, " don't" ), 6, "" ); std::cout << "Result: " << s << std::endl ; }</code>
以上がStroustrup の「C プログラミング言語」第 4 版の C コード連鎖メソッド呼び出しには、明確に定義された動作がありますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。