3

I was looking at some example questions of CPPInstitute's CPA-21-01 exam, and am a bit confused about Question #11. It states the following:

What is the output of the following program?

#include <iostream>

using namespace std;

class A {
public:
    A() {
        a.a = a.b = 1;
    }
    struct { int a,b; } a;
    int b(void);
};

int A::b(void)
{
    int x=a.a;
    a.a=a.b;
    a.b=x;
    return x;
}

int main(void) {
    A a;
    a.a.a = 0;
    a.b();
    cout << a.b() << a.a.b << endl;

    return 0;
}

A. The program will cause a compilation error

B. 10

C. 01

D. 11

It can be boiled down a more minimal example:

int swap_and_return(int& a, int& b) {
    std::swap(a,b);
    return a;
}

int main() {

    int a = 0;
    int b = 1;

    cout << swap_and_return(a,b) << a << endl;

    return 0;
}

So far so good; The answer key says it's B.

Let's say you choose D.

According to this, the execution order is arbitrary:

15) In a function call, value computations and side effects of the initialization of every parameter are indeterminately sequenced with respect to value computations and side effects of any other parameter.

There has already been a similar question here

I think the cout line can be translated into cout.operator<<(a.b()).operator<<(a.a.b);, meaning there should be a sequence point and behavior should be deterministic?

In practice, the following results are obtained:

MS cl.exe, Debug: 10

MS cl.exe, Release: 11

GCC, C++11: 11

Clang: 11

Needless to say, I am a bit confused now, because they say it's answer B when it appears that indeed order of execution is arbitrary.

Could anyone please explain whether I am right about the execution order and what it should be then?

Thanks!

namezero
  • 2,203
  • 3
  • 24
  • 37
  • 1
    C++17 fixed this issue. – Eljay Feb 24 '19 at 18:39
  • What is so reprehensible about this question to deserve two minus votes withing minutes? – namezero Feb 24 '19 at 18:44
  • To be fair, the code has a really high cognitive load (that is, it's hard to read and to follow) and people may have been expecting you to reduce it to a more SO-friendly [MCVE] as a result. Tolerance/patience is quite low these days. Though, personally, I don't think it was worth a downvote. Certainly the question itself is sound and I doubt anyone will disagree with me there. – Lightness Races in Orbit Feb 24 '19 at 18:46
  • Oh and there's also a lot of knee-jerk downvoting of sequence-point-related questions because of (a) the sheer volume we get that are identical, and that (b) are represented by really stupid code posited by bad professors to students. But (c) none of that's your fault, and (d) this question isn't really an instance of that anyway. – Lightness Races in Orbit Feb 24 '19 at 18:47
  • @LightnessRacesinOrbit Thank you, I have added a more minimal example to demonstrate the issue at hand. – namezero Feb 24 '19 at 18:58
  • The difference to the similar examples you find everywhere and on SO is that the side effect in this example occurs inside a function call and not directly within parameter evaluation. – namezero Feb 24 '19 at 19:15

1 Answers1

4

Before C++17, you're right, and the quiz does not allow for the right answer.

Since then, the answer is deterministic.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 2
    Thank you; I understand now that since C++17 the evaluation order will match the operator's associativity. I will write them to update the question, since before the 17 standard there really seems to be no appropriate answer, and with 17 their answer is wrong. – namezero Feb 24 '19 at 19:01
  • Just to follow up, since C++17 is means all side-effects of operator chaining guaranteed to be evaluated in order of the operator's associativity and before not? – namezero Feb 24 '19 at 19:10
  • 1
    @namezero I think that's true but ask on the linked question for clarification – Lightness Races in Orbit Feb 24 '19 at 20:33