查看以下简单代码:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("1234567890");
string::iterator i1 = s.begin();
string::iterator i2 = s.begin();
string s1, s2;
s1.append(i1, ++i1);
s2.append(++i2, s.end());
cout << s1 << endl;
cout << s2 << endl;
}
您对输出的期望是什么?
你会像我一样期待它:
1
234567890
错了! 它是:
234567890
即。第一个字符串是空的。
前缀增量运算符的接缝在迭代器中存在问题。或者我错过了什么?
答案 0 :(得分:14)
你遗漏了一些东西:这与迭代器无关。未指定评估函数的参数的顺序。因此,append(i1, ++i1);
将取决于未指定的行为,无论i1
的类型如何。例如,给出了一些更简单的东西:
void print(int a, int b) {
std::cout << a << " " << b << "\n";
}
int main() {
int a =0;
print(a, ++a);
return 0;
}
你的输出可能完全合理地是你所期望的“0 1”,但它也可以完全合理地是:“1 1”。由于这是未指定的,它可能会从编译器的一个版本更改为下一个版本,或者甚至在更改标志时使用相同的编译器,或者(理论上)可能会根据月亮的相位而变化...
答案 1 :(得分:8)
C ++实现可以按任意顺序自由评估参数。在这种情况下,如果首先评估++ i1,您将得到一个空字符串。
答案 2 :(得分:3)
C ++标准没有指定评估函数参数的顺序,使其依赖于实现。 C ++要求在进入函数之前完全评估函数的参数(并发布所有副作用),但实现可以按任意顺序自由评估参数
在你的情况下i++
在两个参数相同之前得到了评估,结果是一个空字符串。
答案 3 :(得分:3)
不是错误。
参数的顺序
s1.append(i1, ++i1);
未评估标准。编译器可以自由使用它选择的任何订单。在这种情况下,它会在第一个参数(++i1
)之前计算第二个参数(i1
)并指定要复制的空范围。