Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

In C++ what is the best way to return a function local std::string variable from the function?

std::string MyFunc()
    std::string mystring("test");
    return mystring;
std::string ret = MyFunc(); // ret has no value because mystring has already gone out of scope...???
                You are returning by-value, not by reference. As such it doesn't matter that 'mystring' is gone.
– Chris Becke
                Oct 20, 2010 at 10:47
                Won't the internal (heap) data be deleted too when the original string object goes out of scope and gets destructed? If that's the case, does returning make a deep copy?
– martian17
                Sep 14, 2021 at 2:25

So, the way you've written it is OK. Just one advice - if you can construct the string like this, I mean - you can do it in one row, it's sometimes better to do it like this:

std::string MyFunc()
    return "test";

Or if it's more "complicated", for example:

std::string MyFunct( const std::string& s1,
                     const std::string& s2,
                     const char* szOtherString )
    return std::string( "test1" ) + s1 + std::string( szOtherString ) + s2;

This will give a hint to your compiler to do more optimization, so it could do one less copy of your string (RVO).

Why the explicit cast, anyway? Doesn’t that cloud the issue? Just doing return "foo"; works like a charm. – Konrad Rudolph Oct 20, 2010 at 12:04

None of the previous answers contained the key notion here. That notion is move semantics. The std::string class has the move constructor, which means it has move semantics. Move semantics imply that the object is not copied to a different location on function return, thus, providing faster function execution time.

Try to step debug into a function that returns std::string and examine the innards of that object that is about to be return. You shall see a member field pointer address xxx. And then, examine the std::string variable that received the function's return value. You shall see the same pointer address xxx in that object.

This means, no copying has occurred, ladies and gentlemen. This is the move semantics, God bless America!

Good answer...but really @daparic...what on earth does America have to do with this post, let alone StackOverflow [on a forum used by software developers globally]? – David Carr Jan 12 at 5:09

As mentioned, the std::string is copied. So even the original local variable has gone out of scope, the caller gets a copy of the std::string.

I think reading on RVO can totally clear your confusion. In this case, it's accurately referred to as NRVO (Named RVO) but the spirit is the same.

Bonus reading: The problem with using RVO is that it's not the most flexible thing in the world. One of the big buzzes of C++0x is rvalue references which intends to solve that problem.

There are two flavors of RVO: URVO (Unnamed RVO) relates to temporaries and NRVO (Named RVO) relates to local variables. URVO is usually simpler (for the compiler). NRVO is more difficult, because with named variables you could have various return statement, each returning a different variable. At this point the optimizer has to pick 1 variable as the one being optimized, and all the other paths will yield a copy. – Matthieu M. Oct 20, 2010 at 11:27 Actually, in the case of a class like std::string with a non-trivial copy constructor, it can't be optimised away, but it will be in cases where the class does have a trivial copy constructor. – user325117 Oct 20, 2010 at 10:50 "in the case of a class...with a non-trivial constructor, it can't be optimised away" -- Oh, but it can, and usually is. Try this: std::string * sp; std::string func() { std::string s("bla"); sp = &s; return s; } int main() { std::string s = func(); if(sp == &s) std::cout << "YAY"; else std::cout << "BOO"; } -- On my compiler (VS) It prints YAY. – Benjamin Lindley Oct 20, 2010 at 10:55 what PigBen wrote of course results in undefined behavior, but even under defined circumstances the compiler has the right elide the copy sometimes. Google for RVO and NRVO. – avakar Oct 20, 2010 at 11:23

Well, ret will have a value of mystring after MyFunc(). In case of returning the result by value a temporary object is constructed by copying the local one.

As for me, there are some interesting details about the topic in these sections of C++ FAQ Lite.

It depends on the use case. If an instance should keep responsibility for a string, strings should be returned by a const reference. The problem is, what to do, if there isn't any object to return. With pointers, the invalid object could be signaled using 0. Such a "null-object" could be also used with references (e.g., NullString in the code snippet).

Of course, a better way to signal an invalid return value is throwing exceptions.

Another use case is if the responsibility for the string is transferred to the caller. In this case auto_ptr should be used. The code below shows all this use cases.

#include <string>
#include <memory> //auto_ptr
#include <iostream>
using std::string;
using std::auto_ptr;
using std::cout;
using std::endl;
static const string NullString("NullString\0");
///// Use-Case: GETTER //////////////////
//assume, string should be found in a list
//  and returned by const reference
//Variant 1: Pseudo null object
const string & getString( bool exists ) {
  //string found in list
  if( exists ) {
    static const string str("String from list");
    return str;
  //string is NOT found in list
  return NullString;
//Variant 2: exception
const string & getStringEx( bool available ) {
  //string found in list
  if( available ) {
    static const string str("String from list");
    return str;
  throw 0; //no valid value to return
///// Use-Case: CREATER /////////////////
auto_ptr<string> createString( bool ok )
  if( ok ){
    return auto_ptr<string>(new string("A piece of big text"));
  }else{
    return auto_ptr<string>();
int main(){
  bool ok=true, fail=false;
  string str;
  str = getString( ok );
  cout << str << ", IsNull:"<<( str == NullString )<<endl;
  str = getString( fail );
  cout << str << ", IsNull:"<<( str == NullString )<<endl;
    str = getStringEx( ok );
    cout << str <<endl;
    str = getStringEx( fail );
    cout << str <<endl; //line won't be reached because of ex.
  catch (...)
    cout << "EX: no valid value to return available\n";
  auto_ptr<string> ptext = createString( ok );
  if ( ptext.get() ){
    cout << *ptext << endl;
  } else {
      cout << " Error, no text available" << endl;
  ptext = createString( fail );
  if ( ptext.get() ){
    cout << *ptext << endl;
  } else {
      cout << " Error, no text available"<<endl;
  return 0;
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.