-3

look at the following simple code:

#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;
}

what would you expect the output to be?

would you, like me, expect it to be:

1
234567890

wrong! it is:

234567890

i.e. the first string is empty.

seams that prefix increment operator is problematic with iterators. or am I missing something?

dmckee --- ex-moderator kitten
  • 98,632
  • 24
  • 142
  • 234
davka
  • 13,974
  • 11
  • 61
  • 86
  • 7
    I am not one of the downvoters here, but I suggestion that they arise from your suggestion that you have found a compiler bug. Everyone has a "Have I found a bug in ?" moment early on (in my case it was libm), and they are all wrong. If you every do discover a bug in something that heavily used it will be after you have a good deal of experience with the tool in question. – dmckee --- ex-moderator kitten Feb 09 '10 at 17:51
  • 2
    Why the downvotes? Is SO full of GCC developers that have felt personally alluded? (I mean developers *of* GCC) – Manuel Feb 09 '10 at 17:51
  • 2
    @Manuel: downvoting because of the way the question was asked. See http://catb.org/~esr/faqs/smart-questions.html#id382249 . Even if this had been a bug, this isn't the right forum for bug reports. And the title is uselessly generic. At least there was a good repro recipe. – user9876 Feb 09 '10 at 17:55
  • I wouldn't be surprised if this is a duplicate, but I don't find the proposed question (http://stackoverflow.com/questions/621542/compilers-and-argument-order-of-evaluation-in-c) convincing. The early question is trying to catalog that *actual* behavior of common compilers. – dmckee --- ex-moderator kitten Feb 09 '10 at 18:00
  • 1
    Well IMO a friendlier reaction would have been for someone with enough rep. to edit the title. – Manuel Feb 09 '10 at 18:06
  • @ALL, thanks, I do feel stupid for forgetting such a fundamental thing. Well, when you get used to look for the complicated stuff you sometimes overlook the basics. I am not a kind of guy who shouts "bug in the compiler" whenever he has a problem, usually... – davka Feb 10 '10 at 09:11

4 Answers4

14

You're missing something: this really has nothing to do with iterators. The order in which arguments to a function are evaluated is unspecified. As such your: append(i1, ++i1); would depend on unspecified behavior, regardless of the type of i1. Just for example, given something a lot simpler like:

void print(int a, int b) { 
    std::cout << a << " " << b << "\n";
}

int main() { 
    int a =0;
    print(a, ++a);
    return 0;
}

Your output could perfectly reasonably be the "0 1" you seem to expect, but it could also perfectly reasonably be: "1 1". Since this is unspecified, it could change from one version of the compiler to the next, or even with the same compiler when you change flags, or (in theory) could vary depending on the phase of the moon...

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
8

C++ implementations are free to evaluate arguments in any order. In this case, if ++i1 is evaluated first, you will get an empty string.

ergosys
  • 47,835
  • 5
  • 49
  • 70
3

The C++ standard does not specify anything about the order in which the function arguments are evaluated, making it implementation dependent. C++ requires that the arguments to a function be completely evaluated (and all side-effects posted) prior to entering the function, but the implementation is free to evaluate the arguments in any order

In your case i++ got evaluated before making both the parameters same, resulting in an empty string.

More info on this behavior here on comp.compilers newsgroup

codaddict
  • 445,704
  • 82
  • 492
  • 529
3

Not a bug.

The order in which the arguments to

s1.append(i1, ++i1);

are evaluated is not specified by the standard. The compiler is free to use any order it chooses. In this case, it evaluates the second argument (++i1) before the first (i1) and you specify a null range to copy.

dmckee --- ex-moderator kitten
  • 98,632
  • 24
  • 142
  • 234