为什么std :: string连接运算符的工作方式类似于右关联运算符?

Wil*_*cat 10 c++ string gcc visual-c++-2012

运行从我的宠物项目中提取的以下MWE并使用GCC 4.9.1编译(以及4.8.1)

#include <iostream>
#include <string>
#include <sstream>

class InputStringStream
{
public:
    InputStringStream(const std::string& str) : istringstream(str), currentLine() {}
    std::string readLine()
    {
        std::getline(istringstream, currentLine);
        return currentLine;
    }

private:
    std::istringstream istringstream;
    std::string currentLine;
};

int main()
{
    std::string s = std::string("line1\nline2\nline3");
    InputStringStream stream(s);
    std::cout << stream.readLine() + "\n" + stream.readLine() + "\n" + stream.readLine() << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

产生以下输出

line3
line2
line1
Run Code Online (Sandbox Code Playgroud)

虽然我期待

line1
line2
line3
Run Code Online (Sandbox Code Playgroud)

我做错了什么?

PS使用Apple LLVM编译器版本5.1编译的相同代码产生了我的期望.Visual C++ 2012在GCC方面.

Ker*_* SB 16

函数参数的评估顺序是未指定的,所以你做错了就是持有错误的,无根据的信念和期望.(重载运算符喜欢+<<只是普通的函数调用.)

您必须以确定的顺序提取流元素,这是您的责任.例如:

std::cout << stream.readLine() + '\n';
std::cout << stream.readLine() + '\n';
std::cout << stream.readLine() + '\n';
Run Code Online (Sandbox Code Playgroud)

更好的是,避免冗余和临时字符串:

for (auto i : { 1, 2, 3 }) { std::cout << stream.readLine() << '\n'; }
Run Code Online (Sandbox Code Playgroud)

  • 与`for(int i = 0; i <3; ++ i)`相比,for-Loop非常性感 (7认同)

Yu *_*Hao 11

问题不在于关联性,在这个表达式中:

stream.readLine() + "\n" + stream.readLine() + "\n" + stream.readLine() 
Run Code Online (Sandbox Code Playgroud)

它是未指定的,stream.readLine()首先被称为.