I'm changing an old routine that used to take an integer parameter so that it now takes a const reference to an object. I was hoping that the compiler would tell me where the function is called from (because the parameter type is wrong), but the object has a constructor that takes an integer, so rather than failing, the compiler creates a temporary object, passing it the integer, and passes a reference to that to the routine. Sample code:
class thing {
public:
thing( int x ) {
printf( "Creating a thing(%d)\n", x );
}
};
class X {
public:
X( const thing &t ) {
printf( "Creating an X from a thing\n" );
}
};
int main( int, char ** ) {
thing a_thing( 5 );
X an_x( 6 );
return 1;
}
I want the X an_x( 6 )
line to not compile, because there is no X
constructor that takes an int
. But it does compile, and the output looks like:
Creating a thing(5)
Creating a thing(6)
Creating an X from a thing
How can I keep the thing( int )
constructor, but disallow the temporary object?
Temporary objects are often created during execution of a C++ program. Result of C++ operators (unary, binary, logical, etc.) and return-by-value functions always give rise to temporary objects. For built-in types, the cost of creating temporaries is minimal because compilers often use CPU registers to manipulate them.
1 Answer. To explain: Whenever the compiler creates a temporary object, copy constructor is used to copy the values from existing object to the temporary object.
It is sometimes necessary for the compiler to create temporary objects. They are used during reference initialization and during evaluation of expressions including standard type conversions, argument passing, function returns, and evaluation of the throw expression.
Explanation: The temporary object is not created. If object is returned by reference, a particular memory location will be denoted with another name and hence same address values will be used.
Use the explicit
keyword in the thing constructor.
class thing {
public:
explicit thing( int x ) {
printf( "Creating a thing(%d)\n", x );
}
};
This will prevent the compiler from implicitly calling the thing constructor when it finds an integer.
The explicit
keyword works perfectly in my example, but I realized later that my real world code was failing on an overloaded method, not the constructor. (My fault for asking a question that was similar to, but not the same as, my actual problem.) As Mark Ransom pointed out in the comments on the accepted answer, explicit
only works on constructors. I came up with a workaround that solved my problem, so I figured I'd post it here. New sample code:
class thing {
public:
thing( int x ) {
printf( "Creating a thing(%d)\n", x );
}
};
class X {
public:
void do_something( const thing &t ) {
printf( "Creating an X from a thing\n" );
}
};
int main( int, char ** ) {
thing a_thing( 5 );
X an_x;
an_x.do_something( 6 );
return 1;
}
This code shows the same output as the original code, but I can't use explicit
to fix it. Instead, I added a private method that takes an int
:
private:
void do_something( int x );
Now, the compiler doesn't create the temporary object, it gives an error because I am trying to call a private method from outside the class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With