views:

314

answers:

4

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?

+9  A: 

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.

Martin York
Thanks. That does the trick :)
+3  A: 

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);
Todd Gardner
It's MSVC++ brain-deadness that allows accepting an rvalue. Of course it's not valid, as you point out.
Johannes Schaub - litb
DoSomethingByRef(String("My string")); would compile on vc2008
@hammer: go back to litb comment: "It's MSVC++ brain-deadness..." :)
David Rodríguez - dribeas
A: 

Make:

DoSomethingByRef(const String &str);

RC
A: 

"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.

San Jacinto