相关代码演示了链接方法调用:
<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>
但是,断言在某些编译器(如 GCC 和 Visual Studio)中失败,而它在 Clang 中传递。
由于以下原因,此代码表现出未指定的行为计算子表达式的未指定顺序,因为函数参数以无序的顺序计算。链式函数调用为每个函数调用引入从左到右的计算顺序,但每个调用的参数仅在它们所属的成员函数调用之前排序。
在代码中,子表达式 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 编程语言》第四版中的 C 代码链接方法调用是否具有明确定义的行为?的详细内容。更多信息请关注PHP中文网其他相关文章!