Reputation: 450
#include <iostream>
struct Box
{
Box() { std::cout << "constructor called" << std::endl; }
Box(const Box&) { std::cout << "Copy constructor called" << std::endl; }
Box(Box&&) { std::cout << "Move constructor called" << std::endl; }
void run() const { std::cout << "Run" << std::endl;}
};
int main()
{
Box a(Box());
a.run();
}
(demo)
In the above code I was expecting either Copy Constuctor
or Move Constructor
to be called on passing anonymous object Box()
as argument. But none of them were called. Reason probably might be copy elision
. But even constructor is not called for anonymous object A()
. Actually, the above code does not compile and on calling run()
function compiler gave following error.
a.cpp: In function ‘int main()’:
a.cpp:28:7: error: request for member ‘run’ in ‘a’, which is of non-class type ‘Box(Box (*)())’
a.run();
So when we type Box a(Box())
what is happening? What is being created?
Upvotes: 6
Views: 544
Reputation: 40150
This is a case of the Most Vexing Parse. When something could be parsed as a function declaration, it is.
Box a(Box())
is the declaration of a function named a
taking a function of type Box (*)()
as argument and returning a Box
.
A solution is to use the (new in C++11) aggregate initialization for constructing your objects:
Box a{Box{}}
(demo)
The MVP is discussed in its simplest form in this stackoverflow question Most vexing parse: why doesn't A a(()); work?
If you do have an expression within then it is valid. For example:
((0));//compiles
To learn more about how languages are defined, and how compilers work, you should learn about Formal language theory or more specifically Context Free Grammars (CFG) and related material like finite state machines. If you are interested in that though the wikipedia pages won't be enough, you'll have to get a book.
Upvotes: 15