代码之家  ›  专栏  ›  技术社区  ›  Tony The Lion

将std::string本地返回到函数的最佳方法

  •  49
  • Tony The Lion  · 技术社区  · 14 年前

    在C++中,从函数返回函数STD::String变量的最佳方法是什么?

    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...???
    
    6 回复  |  直到 14 年前
        1
  •  70
  •   Chubsdad    14 年前

    不,那不是真的。即使 mystring 已经超出范围被摧毁了, ret 有一个mystring的副本作为函数 MyFunc 按值返回。

        2
  •  23
  •   Kiril Kirov    14 年前

    如果您的代码如下所示,则会出现问题:

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

    所以,你写的方式没问题。只有一个建议-如果你能像这样构造字符串,我的意思是-你可以在一行中这样做,有时候这样做会更好:

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

    或者更“复杂”,例如:

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

    这将给 给你的编译器做更多的优化,这样它就可以少做一份你的字符串(RVO)。

        3
  •  6
  •   kizzx2    14 年前

    如前所述,将复制std::字符串。因此,即使原始的局部变量超出了范围,调用方也会得到std::string的副本。

    我想继续读下去 RVO

    额外阅读 :使用RVO的问题是它不是世界上最灵活的东西。C++ 0x的一大热点是 rvalue references 是为了解决这个问题。

        4
  •  5
  •   Martin Broadhurst    14 年前

    你试过了吗? 返回字符串时将复制该字符串。 好吧,这是官方的说法,实际上这本书可能已经优化过了,但不管怎样,它都是安全的。

        5
  •  3
  •   Paul E.    14 年前

    好吧,ret在MyFunc()之后有一个mystring值。如果按值返回结果,则通过复制本地对象来构造临时对象。

    至于我,在以下几节中有一些关于这个主题的有趣的细节 C++ FAQ Lite .

        6
  •  2
  •   Valentin H    14 年前

    当然,发出无效返回值信号的更好方法是抛出异常。

    另一个用例是字符串的责任是否转移到调用方。在这种情况下,应使用自动ptr。下面的代码显示了所有这些用例。

    #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;
    }
    

    瓦伦丁·海尼茨