-3
# include <iostream>
# include <string>
using std::string;
using std::cout;
using std::endl;

string func() {

    string abc = "some string";
    return abc;

}

void func1(string s) {

    cout << "I got this: " << s << endl;

} 

int main() {

    func1(func());
}

This gives:

$ ./a.out 
I got this: some string

How/why does this code work ? I wonder because abc went out of scope and got destroyed as soon as the call to func() completed. So a copy of abc cannot be/should not be available in variable s in function func1 Is this understanding correct ?

Ankur Agarwal
  • 23,692
  • 41
  • 137
  • 208

2 Answers2

4

The return value is copied from the local variable, effectively creating a new string object.

However, RVO (returned value optimization) should eliminate this step.

Try single stepping your code in a debugger. You should see the std::string copy constructor called for the return line. Be sure to compile with debug enabled and optimizers off.

VorpalSword
  • 1,223
  • 2
  • 10
  • 25
1

Your code is essentially asking:

"Call func1, and in order for func1 to work I have to receive a string which we can use by calling the copy constructor on that string. The parameter for func1 we want to come from the return value of func (which we know has to be a string since its explicitly defined".

abc goes out of scope only after the copy constructor is called on the return value of func() which passes the value of the string. In theory you could have written it passed by reference or constant reference:

void func1(string& s) {
cout << "I got this: " << s << endl;
} 

Which allows func1 to directly access the string in memory through a pointer (and also change it, if your code was meant to.)

void func1(string const& s) {
cout << "I got this: " << s << endl;
} 

Which provides a constant reference to the string from func(). This ensures that you get a pointer to the data and that you won't change its contents. Typically passing data by constant reference (const&) is desirable because it's very fast and keeps your code from accidentally changing data that it shouldn't.

You really only need to pass by value if you're going to manipulate the data once you pass it to the new function, saving you the resources of creating another new container to handle the manipulation:

void func1(string s) {
s += " some extra stuff to add to the end of the string";  //append some new data
cout << "I got this: " << s << endl;
} 
Collin Abr
  • 26
  • 2