best way to return an std::string that local to a function

前端 未结 6 639
陌清茗
陌清茗 2021-01-30 16:07

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\");
    ret         


        
相关标签:
6条回答
  • 2021-01-30 16:34

    It depends on use case. If instance should keep responsibility for string, stings should be returned by const reference. The problem is, what to do, if there is no object to return. With pointers the invalid object could be signalized using 0. Such a "null-object" could be also used with references (e.g. NullString in code snippet). Of cause better way to signal 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;
    
      try{
        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;
    }
    

    Best regards, Valentin Heinitz

    0 讨论(0)
  • 2021-01-30 16:40

    No. That is not true. Even if mystring has gone out of scope and is destroyed, ret has a copy of mystring as the function MyFunc returns by value.

    0 讨论(0)
  • 2021-01-30 16:40

    There will be a problem if your code is like:

    std::string& MyFunc()
    {
        std::string mystring("test");
        return mystring;
    }
    

    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 ex:

    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).

    0 讨论(0)
  • 2021-01-30 16:41

    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.

    0 讨论(0)
  • 2021-01-30 16:41

    Have you tried it? The string is copied when it's returned. Well that's the official line, actually the copy is probably optimised away, but either way it's safe to use.

    0 讨论(0)
  • 2021-01-30 16:48

    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.

    0 讨论(0)
提交回复
热议问题