Home > Backend Development > C++ > Does Undefined Behavior Lurk in std::string Chaining in Bjarne Stroustrup\'s Code?

Does Undefined Behavior Lurk in std::string Chaining in Bjarne Stroustrup\'s Code?

Susan Sarandon
Release: 2024-10-23 18:14:58
Original
626 people have browsed it

Does Undefined Behavior Lurk in std::string Chaining in Bjarne Stroustrup's Code?

Does std::string's Chaining Expression in Bjarne Stroustrup's Code Exhibit Undefined Behavior?

In Bjarne Stroustrup's "The C Programming Language" 4th edition, a code snippet exemplifies chaining using std::string's replace method:

<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>
Copy after login

This code, however, exhibits unspecified behavior instead of invoking undefined behavior.

The reason for this unspecified behavior lies in the order of evaluation, which is unspecified for sub-expressions of chained function calls. In this case, the s.find function calls are evaluated either before or after the first s.replace call, altering the resulting string's length and affecting the subsequent find call's result.

The example in the question demonstrates this: when evaluated by different compilers (clang, gcc), differing results are obtained due to varying evaluation orders.

Details

Function arguments have an unspecified evaluation order, and while chaining function calls introduces a left-to-right evaluation order for each function invocation, the arguments of each call are sequenced before only with respect to that particular function call.

In the example, this indeterminacy arises in the evaluation of s.find("even") and s.find(" don't") with respect to s.replace(0, 4, "").

Ignoring further sub-expression breakdowns, the sequence of evaluation steps and their interdependence can be depicted as follows:

Step 1: s.replace(0, 4, "")  // A
Step 2: s.find("even")       // B
Step 3: s.replace(B, 4, "only") // C
Step 4: s.find("don't")      // D
Step 5: s.replace(D, 6, "")   // E
Copy after login

While A is sequenced before B, which in turn is sequenced before C, there is no sequencing relationship between B and D with respect to A. As a result, D can be evaluated either before or after A, leading to different outcomes based on the sequence chosen.

C 17 Changes

The C 17 standard strengthens the order of evaluation rules for postfix-expressions and their expression-list, giving the code in question well-specified behavior. The sequencing is as follows:

  • The postfix-expression is sequenced before each expression in the expression-list.
  • The initialization of each parameter is indeterminately sequenced with respect to that of any other parameter.

Hence, in C 17 and later, this code will always evaluate correctly.

The above is the detailed content of Does Undefined Behavior Lurk in std::string Chaining in Bjarne Stroustrup\'s Code?. For more information, please follow other related articles on the PHP Chinese website!

source:php
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template