2

I have a class with 4 constructors, and a function as below:

using namespace std;

class ABC {
public:
    ABC() {
        cout << "ABC()\n";
    }

    ABC(int) {
        cout << "ABC(int)\n";
    }

    ABC(ABC&) {
        cout << "ABC(&)\n";
    }

    ABC(ABC&&) {
        cout << "ABC(&&)\n";
    }
};


void ff(ABC t) { }

Please help me to explain some behaviours that seem strange to me (I use MSVC 2016 to compile):

1) Why do I get warning C4930: "'ABC a1(ABC (__cdecl *)(void))': prototyped function not called (was a variable definition intended?)" with the following code:

void main() {
    ABC a1(ABC());
    ff(ABC(5));
}

and on execution, I expect to get the following output:

ABC()
ABC(&&)
ABC(int)
ABC(&&)

but what I really get is

ABC(int)

2) Now if I change to

void main() {
    ABC a1(ABC(5));
    ff(ABC(5));
}

there is no more warning. But on execution, what I expect to get is

ABC(int)
ABC(&&)
ABC(int)
ABC(&&)

but what I really get is

ABC(int)
ABC(int)

3) Now

void main() {
    ABC( ABC() );
    ff(ABC(5));
}

It even doesn't compile. I get error C2660: "'ABC': function does not take 1 arguments".

4) Finally, why the following compiles while 3) doesn't?

void main() {
    ff(ABC(5));
}
kien
  • 197
  • 9

1 Answers1

5

Due to the problem known as the most vexing parse in C++, the line

ABC a1(ABC());

declares a1 to be a function whose return type is ABC and whose argument type is a function that takes no argument and returns ABC.


The line

ABC(ABC());

is a harder to dissect but it is also a declaration of a function, not the definition of a variable.

int(a);

is a valid declaration of the variable a. It is same as:

int a;

Similarly, the line with ABC is same as:

ABC ABC();

Here ABC has overloaded meaning. The first ABC is the type name. The second ABC is the function name (due to the most vexing parse). It declares ABC to be a function that takes no arguments and returns an object of type ABC. For the rest of the function, ABC is the function name, not the type name. Consequently,

ff(ABC(5));

is invalid since in that context ABC is a function that takes no arguments.


I don't have an answer to the question of why the move constructor does not get called.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    second problem seems to be OP's mistakely used the same code as in 1. I guess it is `ABC a1(ABC(5));` instead – Slava Aug 03 '17 at 19:45
  • 1
    And seems OP asks why call to move ctor is missing. – Slava Aug 03 '17 at 19:46
  • I'm not positive, but I think the move constructors aren't called because the compiler has the option to exclude them for efficiency purposes. – Andy Aug 04 '17 at 02:27
  • @R Sahu: Thanks a lot for your explaination about MVP. But I am still waiting for answer for the move constructor to complete. – kien Aug 04 '17 at 09:31