C ++: returns std :: string link from stack memory

To begin with, I read this topic: C ++ Return link / memory stack . But there the question was with std::vector<int> as an object. But, although the behavior of std::string was different. Wasn't this class specifically used to use strings without worrying about memory leaks and misuse of memory?

So, I already know that this is wrong:

 std::vector<t> &function() { vector<t> v; return v; } 

But is it also wrong?

 std::string &function() { string s = "Faz"; s += "Far"; s += "Boo"; return s; } 

thanks


Additional question (EDIT): So, I'm right when I say return (by value) std::string does not copy the sequence char only a pointer to the array char * and t_size for length?

If this statement is true, is this the right way to create a deep copy of a string (to avoid substitution, it will change the string)?

 string orig = "Baz"; string copy = string(orig); 
+6
source share
5 answers

You are really close to making these functions work:

 std::string function() { string s = "Faz"; s += "Far"; s += "Boo"; return s; } 

Just make them return a copy instead of a link and you are set up. This is what you want, a copy of the string based on the stack.

This is getting better because return value optimization (RVO) will only create a row once and return it, just as if you created it on the heap and returned a link to it, all behind the scenes!

+17
source

It doesn't matter what type is; this pattern is always completely, 100% incorrect for any type of T object:

 T& f() { T x; return x; } // x is destroyed here and the returned reference is thus unusable 

If you are returning a link from a function, you must ensure that the object to which it refers will still exist after the function returns. Since objects with automatic storage time are destroyed at the end of the block in which they are declared, they are guaranteed not to exist after the function returns.

+21
source

Do not return links, return value:

 std::string function() // no ref { string s = "Faz"; s += "Far"; s += "Boo"; return s; } 

If your compiler can perform named optimization of the return value, for example, NRVO (which is most likely), this will turn it into something roughly equivalent to the following, which avoids any extraneous copies:

 // Turn the return value into an output parameter: void function(std::string& s) { s = "Faz"; s += "Far"; s += "Boo"; } // ... and at the callsite, // instead of: std::string x = function(); // It does this something equivalent to this: std::string x; // allocates x in the caller stack frame function(x); // passes x by reference 

Regarding the additional question:

The line copy constructor always performs a deep copy. So, if there are copies, there is no problem with the alias. But when returning by value using NRVO, as you can see above, no copies are made.

You can create copies using several different syntaxes:

 string orig = "Baz"; string copy1 = string(orig); string copy2(orig); string copy3 = orig; 

The second and third have no semantic difference: they are both just initialized. The first creates a temporary value by explicitly invoking the copy constructor, and then initializes the variable with a copy. But the compiler can make a copy of elision here (and it is very likely that this will happen) and make only one copy.

+5
source

The problem with this (regardless of type) is that you are returning a memory reference that goes out of scope as soon as you hit return.

 std::string &function() { string s = "Faz"; s += "Far"; s += "Boo"; // s is about to go out scope here and therefore the caller cannot access it return s; } 

You want to change the type of the return value so that it doesn’t refer, but to the value, so a copy of s is returned.

 std::string function() { string s = "Faz"; s += "Far"; s += "Boo"; // copy of s is returned to caller, which is good return s; } 
+1
source

You can take the address of the returned string and compare it with the address of the original string, as shown below:

 #include <iostream> using namespace std; string f() { string orig = "Baz"; string copy1 = string(orig); string copy2(orig); string copy3 = orig; cout << "orig addr: " << &orig << endl; cout << "copy1 addr: " << &copy1 << endl; cout << "copy2 addr: " << &copy2 << endl; cout << "copy3 addr: " << &copy3 << endl; return orig; } int main() { string ret = f(); cout << "ret addr: " << &ret << endl; } 

I got the following:

orig addr: 0x7ffccb085230
copy1 addr: 0x7ffccb0851a0
copy2 addr: 0x7ffccb0851c0
copy3 addr: 0x7ffccb0851e0
ret addr: 0x7ffccb085230

You see that orig and ret point to the same instance of a string in memory, so orig returned by reference. copy1 , copy2 , copy3 are copies of orig , as they point to different objects in memory.

0
source

Source: https://habr.com/ru/post/890774/


All Articles