-2

I would like to ask for a clarification of the constructors calls order in the following program.

What I tried:
The output starts with 1 3 2. I tried to debug it to see why the function "f" calls the 3rd argument's ctor before the 2nd's and I don't really get it.
I tried to put the argument "1" as the last one (of-course I also changed the function signature as needed) and still, "1" is the first argument calls it's ctor.
I tried to do different orders of calls and have some assumption about whats going on.

It seems like it calls the ctors from the last argument to the first while the argument isn't an int (float etc..) type, if it is one of these types it calls their ctor first in the same order (from last to first while passing over the others)

So, any thoughts? I would like to know what is really going on. Thanks.

#include <conio.h>
#include <iostream>
using namespace std;

class A {
int i;
public:
    A(int i) : i(i) {
         cout << i << endl;
    }
    A(const A &o) : i(o.i) {
        cout << i << endl;
    }
    ~A() {
        cout << i << endl;
    }
    friend A f(const A &, A , A *);
};

A f(const A &a, A b, A *c) {
    return *c;
}

void main() {
    f(1, A(2), &A(3));
}
  • `&A(3)` must not compile. Do you use MSVC? – Maxim Egorushkin Jul 10 '18 at 09:32
  • 5
    The order of function parameters evaluation is unspecified. – Ron Jul 10 '18 at 09:32
  • I use visual studio. So there is no way to know what the output would be in this case? Because it seems like it keeps on some order.. well, Thanks for your answers – Mark Elishaev Jul 10 '18 at 09:33
  • @Maxim Why wouldn't it compile? Missing parenthesis? C++ standard forbidding to take explicit address of temporary (why, since it would be easily circumvented with helper function returning pointer to its reference argument)? Just want to know... – hyde Jul 10 '18 at 09:37
  • 2
    @hyde Can't take an address of a temporary. – Maxim Egorushkin Jul 10 '18 at 09:38
  • Returning a pointer to one of its argument is generally undefined behavior. The pointer becomes invalid as soon as the function returns and the temporary object used as argument is destroyed. – Goswin von Brederlow Jul 10 '18 at 09:46
  • 1
    @Mark - If you use Visual Studio you should really, really consider setting the warning level to [Level 4 (/W4)](https://learn.microsoft.com/en-us/cpp/build/reference/compiler-option-warning-level). That would have told you that *"return type of 'main' should be 'int'"*, *"'a': unreferenced formal parameter"* in function f, and *"nonstandard extension used: class rvalue used as lvalue"* when taking the address of a temporary. The compiler is rather helpful, if you just let it. – Bo Persson Jul 10 '18 at 10:43
  • Thanks for letting me know.. I'm new to all of this so still don't know the more deeper details. – Mark Elishaev Jul 10 '18 at 10:48
  • `conio.h` is unnecessary and should be avoided anyhow; also, I'd stay away from `using namespace std;`, as explained here : https://softwareengineering.stackexchange.com/questions/236404/what-is-using-namespace-pollution – schaiba Jul 10 '18 at 11:14

1 Answers1

5

The order of evaluation of function arguments is unspecified in C++. It does not go from left to right. When you have a function accepting multiple parameters:

void foo(A a, B b, C c);

it doesn't mean the parameters will be evaluated in the a -> b -> c order. Don't confuse the function signature (evaluation) with the block of statements (execution) inside the function definition.

Also, taking an address of a temporary as you have with the &A(3) should result in error, you don't need the <conio.h> header and you should avoid using the using namespace std;.

Ron
  • 14,674
  • 4
  • 34
  • 47
  • 2
    You should mention that it depends on the implementation and can and will change at any time. E.g. because the optimizer feels like it. – Goswin von Brederlow Jul 10 '18 at 09:46
  • If I get what you say, this means that on each run of the program I would get different output because the temporary objects initialized in different order, but each time I get the same one on this specific implementation. And about the temporary address, for some reason i don't get an error, it just runs without even any warnings. – Mark Elishaev Jul 10 '18 at 09:58
  • @MarkElishaev -- not "would" get different output, but "could". In practice, when you run the **same** executable you'll get the same behavior. If you recompile the same code with the same compiler and the same compiler options you'll get the same behavior. Change anything and all bets are off. – Pete Becker Jul 10 '18 at 11:32
  • Thank you, now it really clarifies it for me. – Mark Elishaev Jul 10 '18 at 11:35