C 中的链接 STL 方法是否保留求值顺序?
在 Bjarne Stroustrup 的《C 编程语言》第 4 版中,以下代码片段举例说明了方法链接:
<code class="cpp">void f2() { 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>
此代码从左到右评估语句,增量更改字符串 s。但是,根据所使用的编译器,此表达式的行为是不明确的:
揭示未指定的行为
由于不确定性,代码表现出未指定的行为子表达式的求值顺序,尽管不调用未定义的行为。问题的关键在于链式函数调用中函数参数的求值顺序。
具体而言,对于以下子表达式:
它们的求值顺序对于以下内容是不确定的:
这意味着可以在替换调用之前或之后评估 find 调用,从而影响 s 的长度,从而改变 find 调用的结果。
使用自定义查找函数的插图
为了演示这种歧义,代码的修改版本使用自定义 my_find 函数,该函数报告每个子表达式求值中搜索字符串的位置:
<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: " << pos << std::endl; return pos; }</code>
使用不同的编译器运行此代码会根据计算顺序产生不同的结果:
C 17 更改
C 17 标准 (p0145r3) 对表达式求值顺序规则进行了改进,以解决这种歧义。它加强了后缀表达式及其表达式列表的求值顺序,如下所示:
这可确保链式方法调用按预期顺序进行计算,从而解决了 C 17 中的未定义行为。
以上是STL 方法链接是否保留 C 中的求值顺序?的详细内容。更多信息请关注PHP中文网其他相关文章!