-3

看下面的简单代码:

#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

4 回答 4

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”。由于这是未指定的,因此它可能会从一个版本的编译器更改为下一个版本,甚至在您更改标志时使用相同的编译器,或者(理论上)可能会因月相而异......

于 2010-02-09T17:46:01.063 回答
8

C++ 实现可以自由地以任何顺序评估参数。在这种情况下,如果首先评估 ++i1,您将得到一个空字符串。

于 2010-02-09T17:41:27.730 回答
3

C++ 标准没有指定函数参数的计算顺序,使其依赖于实现。C++ 要求在输入函数之前对函数的参数进行完全评估(并发布所有副作用),但实现可以自由地以任何顺序评估参数

在您的情况下i++,在使两个参数相同之前进行了评估,导致一个空字符串。

有关此行为的更多信息,请访问comp.compilers 新闻组

于 2010-02-09T17:43:11.233 回答
3

不是错误。

参数的顺序

s1.append(i1, ++i1);

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

于 2010-02-09T17:43:31.353 回答