Passing by reference, returning an object

Hi everyone,

in the code below, 1. and 2. show how I'd like to be using my function.. and 3. shows the way the compiler will let me. Is there any way to use a function that takes object references like I am trying to do in 1. and 2.?

I'm using (string &) as the parameter because as I understand it, a copy of the string will be made if I use (string) as the parameter, and I don't want this overhead.

Secondly, is line 25 safe? When I initialise str2 to the return value of foo_string, does this create a copy and store it at str2? Or does str2 reference volatile memory where foo_string was previously storing it's ret_val variable?



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <string>
#include <iostream>

using std::string;

string foo_string(string &);

int main()
{
    using namespace std;
   
    //1. invalid
    cout << "1. = " << foo_string("Hello!") << endl;
    
    //2. invalid
    cout << "2. = " << foo_string(string("Hello!")) << endl;
    
    //3. valid
    string str = "Hello!";
    cout << "3. = " << foo_string(str) << endl;

    string str2 = foo_string(str);

}

string foo_string(string & in_string)
{
    string ret_val(in_string);
    ret_val.insert(3,"!!");
    return ret_val;
}


1. gives:
invalid initialization of non-const reference of type ‘std::string&’ from an rvalue of type ‘const char*’

2. gives:
invalid initialization of non-const reference of type ‘std::string&’ from an rvalue of type ‘std::string’



Thanks!

Tom.
Last edited on
Okay, so the following works. I have made the parameter (const string&)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <string>
#include <iostream>

using std::string;

string foo_string(const string &);

int main()
{
    using namespace std;
   
    //1. valid
    cout << "1. = " << foo_string("Hello!") << endl;

    string str = "Hellooo!";

    string str2 = foo_string(str);

}

string foo_string(const string & in_string)
{
    string ret_val(in_string);
    ret_val.insert(3,"!!");
    return ret_val;
}


Why is this?

And also from before: is line 17 safe?
string str2 = foo_string(str);
Is this making a copy of foo_string's return value and putting it at str2?
Last edited on
1) Non-const references can only be bound to l-values (variables and the like). Const references accept r-values.
2) Implicit conversions produce r-values (temporaries).
3) Passing a C-style string to a function that expects string& parameter requires conversion.
You have 2 and 3 and non-const reference parameter, which means that you violate 1.

Other than that, passing STL strings by const reference in your case is complete overkill, since you immediately create a local copy. You could pass the argument by value and then the replica would be created for you during the call and you would not need the local variable. Like this:
1
2
3
4
5
string foo_string(string in_string)
{
    in_string.insert(3,"!!");
    return in_string;
}

Also, the string class is frequently implemented using the copy-on-write idiom, meaning that passing by const reference may turn out to be even less efficient.

There is a somewhat obscure wikipedia entry (http://en.wikipedia.org/wiki/Copy-on-write). I'm sure you can google something better.

Regards
Thanks for the insight simeonz.

The reason for the overkill: The ret_val copy in foo_string() was just for the second thing I was testing, if string str2 = foo_string(str); was safe or not. I think that it is, and that a copy of the ret_val is created and assigned to str2 before it is destroyed.

Tom.
Topic archived. No new replies allowed.