C++ STL 字符串运算符+结合性

C++ STL string operator+ associativity

我在 VC++ 2015

中尝试了以下代码
#include <iostream>
#include <string>

using namespace std;

int foo(int v)
{
    cout << v << endl;
    return 10;
}

string bar(int v)
{
    cout << v << endl;
    return "10";
}

int main()
{
    auto a = foo(1) + foo(2) + foo(3);
    auto b = bar(10) + bar(20) + bar(30);
    cout << "----" << endl << a << endl << b << endl;
    return 0;
}

控制台结果如下

1
2
3
30
20
10
----
30
101010

众所周知,二元+运算符具有从左到右的结合性,可以通过对foo的3次调用来证实。它们按指令顺序从左到右调用。

我的问题是,为什么这似乎不适用于 string::operator+?我是不是误会了什么?

你对associativity and order or evaluation感到困惑。

参数的求值顺序在 C++ 中未指定。如您所述,operator + 的关联性是从左到右。

要了解这一点,请使用 operator -

尝试类似的代码片段

来自 Order or evaluation(强调我的)

Except where noted below, there is no concept of left-to-right or right-to-left evaluation in C++. This is not to be confused with left-to-right and right-to-left associativity of operators: the expression f1() + f2() + f3() is parsed as (f1() + f2()) + f3() due to left-to-right associativity of operator+, but the function call to f3 may be evaluated first, last, or between f1() or f2() at run time.

您假设编译器在执行加法运算符之前为函数调用发出代码。这不一定是真的。实际的操作顺序可以简单地是:

  1. 调用bar(30),保存结果。
  2. 调用bar(20),保存结果。
  3. 调用bar(10),保存结果。
  4. 将第 3 步和第 2 步的结果相加。
  5. 将第 4 步和第 1 步的结果相加。

当然,因为加法是对称的,所以加法的顺序并不重要。

在这种情况下,C++ 不要求函数调用与加法一起立即发生。管理评估顺序的规则实际上非常复杂。可以这么说,在这种情况下,函数调用的顺序没有指定,每个 C++ 实现都可以以任何相对顺序进行函数调用。事实上,每次你 运行 程序时,相对顺序都可能不同(当然不太可能,但这仍然是合规的)。