为什么std::字符串串联运算符的工作原理类似于右关联运算符
Why std::string concatenation operator works like right-associative one?
运行以下从我的宠物项目中提取并使用GCC 4.9.1(以及4.8.1)编译的MWE
#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("line1nline2nline3");
InputStringStream stream(s);
std::cout << stream.readLine() + "n" + stream.readLine() + "n" + stream.readLine() << std::endl;
return 0;
}
产生以下输出
line3
line2
line1
而我期待
line1
line2
line3
我做错了什么?
附言:使用Apple LLVM编译器5.1版编译的相同代码产生了我所期望的结果。Visual C++2012在GCC方面。
函数参数的求值顺序是未指定,所以你做错的是持有错误的、不必要的信念和期望。(像+
和<<
这样的重载运算符只是普通的函数调用。)
你必须以确定的顺序提取流元素,这是你的责任。例如:
std::cout << stream.readLine() + 'n';
std::cout << stream.readLine() + 'n';
std::cout << stream.readLine() + 'n';
更好的是,避免冗余和临时字符串:
for (auto i : { 1, 2, 3 }) { std::cout << stream.readLine() << 'n'; }
问题不在于关联性,在这个表达式中:
stream.readLine() + "n" + stream.readLine() + "n" + stream.readLine()
未指定先调用哪个stream.readLine()
。
唯一错误的是假设在一个调用stream.readLine()
三次的表达式中,这些表达式的出现顺序与调用顺序匹配。有些编译器可能会先对最后一个调用求值,有些则可能会按顺序求值。理论上,有些人甚至可能会先评估中间的一个。这只是C++的一个一般规则:表达式的求值顺序是不指定的。
在所有实现中获得相同结果的一个简单方法是将这三个结果存储在单独的变量中。
相关文章:
- 类似于strcat()的函数出现问题
- 如何将C++闭包与变量参数同时重用——类似于JavaScript
- 算术运算的结果类似于:C浮点变量中的1/3
- 为什么字符串比较的 == 运算符相对于任一字符串长度线性时间(似乎)?
- 在数组中输入 n 个整数的列表,并以类似于钟摆来回移动的方式排列它们. 输入-1 3 2 5 4,输出5 3 1 2 4
- 创建类似于布尔值的变量类型
- 如何在 Arduino 字符串的开头添加元素.类似于 JS unshift();
- Java 中是否有类似于 C++ 中引用类型"&"的内容?
- C++未知长度字符串的数组,其行为类似于 Python 字符串列表
- C++函数,它将数组、谓词和运算符作为参数,并将运算符应用于满足谓词的数组元素
- 如何创建类似于 QVariant 的变体类
- 对于多个字符(如 ETX/STX 对),是否有类似于 std::quote 的东西
- 初始化命名空间中的变量是否类似于将它们初始化为类成员?
- C++中用于结构的纯数组的类似于TableView/DataFrame的通用功能
- 有没有类似于stoi的函数可以用于模板类
- 如何编写一个类似于kernellist_head的c++风格的双链表实现
- 序列化模式类似于boost::序列化
- 是否有标准的C++函数,类似于地址运算符&?
- 最佳 STL 变换 - 类似于三元运算符的模板函数
- 为什么std::字符串串联运算符的工作原理类似于右关联运算符