Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I tell the compiler not to create a temporary object?

Tags:

c++

oop

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?

like image 275
Graeme Perrow Avatar asked Feb 06 '09 16:02

Graeme Perrow


People also ask

Is always used when the compiler has to create a 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.

When the compiler generates a temporary object?

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.

When compiler create temporary object in C++?

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.

Is temporary object created in return by reference?

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.


2 Answers

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.

like image 107
Paolo Tedesco Avatar answered Nov 09 '22 02:11

Paolo Tedesco


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.

like image 26
Graeme Perrow Avatar answered Nov 09 '22 02:11

Graeme Perrow