Reputation: 343
If I call the "func(const generic& ref)" with an integer as argument (instead of a 'generic' object), the constructor generic(int _a) will be called to create a new object.
class generic {
public:
int a;
generic() {}
generic(int _a) : a(_a) {
std::cout << "int constructor was called!";
}
generic(const generic& in) : a(in.a) {
std::cout << "copy constructor was called!";
}
};
void func(const generic& ref) {
std::cout << ref.a;
}
int main() {
generic g(2);
func(g); // this is good.
func(generic(4)); // this is good.
func(8); // this is good...... ?
return 0;
}
The last "func(8)" call creates a new object using the constructor generic(int _a). Is there a name for this kind of construction? Shouldn't the programmer explicitly construct an object before passing the argument? Like this:
func(generic(8));
Is there any benefit in passing the integer alone (other than saving time)?
Upvotes: 3
Views: 208
Reputation: 79461
Is there a name for this kind of construction? Shouldn't the programmer explicitly construct an object before passing the argument?
If you don't want this to happen, you can add the explicit
specifier to your constructor:
explicit generic(int _a) : a(_a)
{
std::cout << "int constructor was called!";
}
An excerpt from the cppreference page:
A constructor that is declared without the function specifier
explicit
is called a converting constructor.
By default, implicit constructor calls are allowed in this circumstance.
Is there any benefit in passing the integer alone (other than saving time)?
Whether you call the method with func(8)
or func(generic(8))
isn't going to change what code executes given the code you have written. If you were to add an overload of func
that takes an int
instead of a generic
, then the calls would suddenly become different. So, although it is ultimately a matter of opinion, I think you are better off being explicit by using func(generic(8))
.
Upvotes: 3
Reputation: 726609
This behavior is part of overload resolution process - specifically.
When you call func()
, the compiler constructs a list of candidates. There's only one candidate, func(const generic& ref)
, so the compiler tries to figure out how to make a call.
It sees that there is no func(int)
defined, so it tries to find a conversion path from int
to generic
. Since there is a constructor of generic
that takes an int
, and there are no other conversions allowing to perform the same call, the compiler takes the construction+call path.
The compiler checks three things, in the order from higher to lower priority:
This means that an exact match of the signature trumps a match that requires a promotion, and a match that requires a promotion trumps a match that needs a conversion.
See "Ranking of implicit conversion sequences" of the document linked above for information on how implicit conversions are applied.
Upvotes: 4