I'm a C++ beginner and would like to understand why
return std::list<int>();
needs parentheses, but
std::list<int> foo;
doesn't need parentheses. What's the difference between these constructor calls?
I'm a C++ beginner and would like to understand why
return std::list<int>();
needs parentheses, but
std::list<int> foo;
doesn't need parentheses. What's the difference between these constructor calls?
look at it this way:
1) you need to create an object
2) you need to return it.
let's say the compiler looks at the expression
return Foo;
, the compiler thinks "hey! he wants me to return a type! a type is not a thing that I can return! I need a true variable here!"so you can write something like
or make it shorter - call the default constructor of
Foo
, then return the Anonymous object I just created. you treat the constructor as a function that produces an object.does the code
return createDefaultFoo();
looks much more reasonable? well, this is whatFoo()
does, it creates and returns anonymousFoo
obejctin this line :
the compiler can tell you want an object named
foo
from the typestd::list<int>
. so the()
are redundand. as answered here, adding the()
will make the compiler think you declare a function.Both statements call default constructor.
This is same as:
Here an object is created (using default constructor) and object is returned.
Here object
foo
is created using the default constructor.Here are other way to do the same in
C++11
:Neither of these are constructor calls.
The first is an explicit type conversion, which creates an object of type
std::list<int>
.The second is a variable definition which creates an object of type
std::list<int>
.The default-constructor (constructor taking no arguments) is called as part of the creation in both cases.
Although you might see such things talked about as "constructor calls", there's no syntactic construct to explicitly and singularly call a constructor in C++.
The reason one needs parentheses when the other doesn't is because they are two separate language constructs with different syntax rather than two ways to call a constructor.
Note that if you add parentheses to your second example, you actually declare a function rather than defining a variable:
This is commonly known as the most-vexing-parse. C++11 introduced braced-initialization to get around this:
The Standardese, for those so inclined
(Quotes from N3337)
"But
T()
sure looks like a constructor call, why is it not?"In that context,
T()
is known as an explicit type conversion with functional notation:So this creates a prvalue which is value-initialized.
So this calls the constructor as part of the value-initialization, which is part of an explicit type conversion. As stated above, there is no way to call a constructor directly. The standard says:
So constructors don't have names and we declare/define them with a syntax exception which the language defines.
"This seems like an academic distinction, does this matter in practice?"
Maybe, maybe not. My opinion is that interpreting syntax like the above as pure constructor calls paints an incorrect picture of what a constructor is. A constructor initializes an object; it doesn't allocate that object's memory, return the initialized object, bind a symbol to that object or anything else which is done by variable definitions and type conversions. Furthermore, it can create confusion like that of the OP, who expected uniform syntax because he thought those two constructs are both constructor calls.
Why use inexact synecdoche when we have formal terms which avoid confusion?