title: Is it safe to return a std::string by value?
body: <p>In the following code, a string is encapsulated within a class, Foo.</p>
  
  <p>The call to Foo::getText() returns the string by value.  This creates a second instance of the string object, but both string objects now point to the same char buffer on the heap.</p>
  
  <p>When the Foo instance is deleted, the the encapsulated string is automatically destructed, and therefore the char buffer on the heap is deleted.</p>
  
  <p>Even though <code>getText()</code> returns a string by value, the resulting string object still relies on the lifetime of the original string object in order to retain the char buffer to which they mutually point.</p>
  
  <p>Doesn't this mean that the printing of the <code>retval</code> to the terminal is an invalid access to memory that has already been free'd on the heap?</p>
  
  <pre><code>class Foo
  {
      Foo(const char* text) :
         str(text)
      {
      }
  
      std::string getText()
      {
          return str;
      }
  
      std::string str;
  };
  
  int main()
  {
      Foo pFoo = new Foo("text");
      std::string retval = foo.getText();
      delete pFoo;
      cout &lt;&lt; retval;  // invalid memory access to char buffer?
  }
  </code></pre>
  
  <p>I think a lot of people assume that, because the string was returned by value, they need not be concerned about the lifetime of the original string within Foo.  This problem isn't strictly related to strings, but really applies to any class with encapsulated pointers that are free'd upon destruction.  But what's the best practice here when it comes to strings?</p>
  
  <ol>
  <li>Never return string by value?</li>
  <li>Only return strings by value if the lifetime of the original string is guaranteed?</li>
  <li>Always make a copy of the string?  <code>return std::string(retval.c_str());</code></li>
  <li>Enforce a contract with the caller of <code>getText()</code>?</li>
  </ol>
  
  <p>EDIT:</p>
  
  <p>I think I was misled by RVO.  All three strings in this example return a c_str at the same address.  Is RVO to blame?</p>
  
  <pre><code>class Obj
  {
  public:
      Obj() : s("text")
      {
          std::printf("%p\n", s.c_str());
      }
  
      std::string getText() { return s; }
  
      std::string s;
  };
  
  int main()
  {
      Obj* pObj = new Obj();
      std::string s1(pObj-&gt;getText());
      std::string s2 = pObj-&gt;getText();
      delete pObj;
      std::printf("%p\n", s1.c_str());
      std::printf("%p\n", s2.c_str());
  }
  </code></pre>
  
  <p>Result:</p>
  
  <pre><code>0x600022888
  0x600022888
  0x600022888
  </code></pre>