How to avoid explicitly calling a constructor when passing temporary object by reference in C++?

StackOverflow https://stackoverflow.com/questions/1008272

  •  06-07-2019
  •  | 
  •  

Question

Let's say I have a class:

class String
{
public:
     String(char *str);
};

And two functions:

void DoSomethingByVal(String Str);
void DoSomethingByRef(String &Str);

If I call DoSomethingByVal like this:

DoSomethingByVal("My string");

the compiler figures out that it should create a temporary String object and call the char* constructor.

However, if I try to use DoSomethingByRef the same way, I get a "Can't convert parameter from 'char *' to 'String &'" error.

Instead, I have to explicitly create an instance:

DoSomethingByRef(String("My string"));

which can get preety annoying.

Is there any way to avoid this?

Was it helpful?

Solution

You need to pass by const reference:

For:

void DoSomethingByVal(String Str);

In this situation the compiler first creates a temporary variable. Then the temporary variable is copy constructed into the parameter.

For:

void DoSomethingByRef(String const& Str);

In this situation the compiler creates a temporary variable. But temporary variables can not be bound to a reference they can only be bound to a const reference so your original function can not be called. Note the std::string objects constructor takes a const reference is the parameter to the copy constructor and that is why the first version works as the temporary is bound to the const reference parameter of the copy constructor only.

OTHER TIPS

Hmm, I'm not sure if

void DoSomethingByRef(String &Str);
DoSomethingByRef(String("My string"));

would actually compile. An rvalue can't bind to a reference to non-const (because a ref to non-const is stating you will modify the value, and it wouldn't make sense to modify a temporary). Are you sure you aren't doing:

String str("My string");
DoSomethingByRef(str);

If you want DoSomethingByVal to take an rvalue, the parameter has to be a reference to const:

void DoSomethingByRef(const String &Str);

Make:

DoSomethingByRef(const String &str);

"My String" is not a String, it is a c-string, a char*, if you will. You need to put that c-string into a String object, and THEN you can pass the new String object by reference.

Another point, you are already passing a char*... that's pretty lightweight, just a pointer. Why worry about passing a new object by reference? Just allocate a new object inside that constructor from the heap and copy the c-string into it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top