为什么string :: append操作行为奇怪?

时间:2010-02-09 17:37:56

标签: c++ linux gcc stl operator-precedence

查看以下简单代码:

#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

即。第一个字符串是空的。

前缀增量运算符的接缝在迭代器中存在问题。或者我错过了什么?

4 个答案:

答案 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++在两个参数相同之前得到了评估,结果是一个空字符串。

comp.compilers newsgroup

上有关此行为的更多信息

答案 3 :(得分:3)

不是错误。

参数的顺序
s1.append(i1, ++i1);

未评估标准。编译器可以自由使用它选择的任何订单。在这种情况下,它会在第一个参数(++i1)之前计算第二个参数(i1)并指定要复制的空范围。