Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
返回函数本地的std::字符串的最佳方法 在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...???_C++_Return Value - Fatal编程技术网

返回函数本地的std::字符串的最佳方法 在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...???

返回函数本地的std::字符串的最佳方法 在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...???,c++,return-value,C++,Return Value,不,那不是真的。即使mystring已超出范围并被销毁,ret也有一个mystring的副本,因为函数MyFunc按值返回。您尝试过吗? 返回字符串时将复制该字符串。 这是官方的说法,实际上拷贝可能已经被优化了,但无论哪种方式都可以安全使用。如前所述,std::string是被拷贝的。因此,即使原始局部变量已超出范围,调用方也会获得std::string的副本 我认为继续读下去可以完全消除你的困惑。在这种情况下,它被准确地称为NRVO(命名为RVO),但精神是相同的 额外阅读:使用RVO的问题在

不,那不是真的。即使
mystring
已超出范围并被销毁,
ret
也有一个mystring的副本,因为函数
MyFunc
按值返回。

您尝试过吗? 返回字符串时将复制该字符串。
这是官方的说法,实际上拷贝可能已经被优化了,但无论哪种方式都可以安全使用。

如前所述,std::string是被拷贝的。因此,即使原始局部变量已超出范围,调用方也会获得std::string的副本

我认为继续读下去可以完全消除你的困惑。在这种情况下,它被准确地称为NRVO(命名为RVO),但精神是相同的


额外阅读:使用RVO的问题在于它不是世界上最灵活的东西。C++0x的一个大问题是它打算解决这个问题。

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

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

这将给编译器一个提示,让它做更多的优化,这样它就可以少复制一个字符串()。

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


至于我,在的这些部分中有一些关于这个主题的有趣细节。

这取决于用例。如果一个实例应该对字符串负责,那么字符串应该由const引用返回。问题是,如果没有任何要返回的对象,该怎么办。对于指针,可以使用0向无效对象发送信号。这种“null对象”也可以与引用一起使用(例如,代码段中的null字符串)

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

另一个用例是将字符串的责任转移给调用者。在这种情况下,应使用自动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;
}
#包括
#包括//auto\u ptr
#包括
使用std::string;
使用std::auto_ptr;
使用std::cout;
使用std::endl;
静态常量字符串NullString(“NullString\0”);
/////用例:GETTER//////////////////
//假设字符串应该在列表中找到
//并通过常量引用返回
//变量1:伪空对象
常量字符串和getString(布尔存在){
//在列表中找到字符串
如果(存在){
静态常量字符串str(“列表中的字符串”);
返回str;
}
//在列表中找不到字符串
返回空字符串;
}
//备选案文2:例外情况
常量字符串和getStringEx(bool可用){
//在列表中找到字符串
如果有(可用){
静态常量字符串str(“列表中的字符串”);
返回str;
}
抛出0;//没有要返回的有效值
}
/////用例:CREATER/////////////////
auto_ptr createString(布尔ok)
{
如果(确定){
返回auto_ptr(新字符串(“一段大文本”);
}否则{
返回自动_ptr();
}
}
int main(){
bool ok=真,fail=假;
字符串str;
str=getString(确定);

cout前面的答案中没有一个包含关键概念。该概念是移动语义。
std::string
类具有
move
构造函数,这意味着它具有移动语义。移动语义意味着在函数返回时对象不会复制到其他位置,从而提供更快的函数执行时间

尝试单步调试返回
std::string
的函数,并检查即将返回的对象的内部。您将看到成员字段指针地址
xxx
。然后,检查接收函数返回值的
std::string
变量。您将看到相同的指针地址
xxx
在该对象中


这意味着,没有复制发生,女士们先生们。这是移动语义,上帝保佑美国!

您是通过值返回的,而不是通过引用返回的。因此,“mystring”不存在并不重要。实际上,对于像std::string这样具有非平凡复制构造函数的类,无法对其进行优化,但它可以“如果类…有一个非平凡的构造函数,它不能被优化”--哦,但它可以,而且通常是这样。试试这个:std::string*sp;std::string func(){std::string s(“bla”);sp=&s;return s;}int main(){std::string s=func();如果(sp==&s)std::cout PigBen写的东西当然会导致未定义的行为,但即使在定义的情况下,编译器有时也有权删除副本。谷歌搜索RVO和NRVO。RVO有两种风格:URVO(未命名的RVO)与临时变量相关,NRVO(命名的RVO)与局部变量相关。URVO通常更简单(对于编译器).NRVO更难,因为对于命名变量,您可能有各种
return
语句,每个语句返回不同的变量。此时,优化器必须选择一个变量作为要优化的变量,所有其他路径都将生成一个副本。无论如何,为什么显式强制转换?这不会掩盖问题吗?只需执行
return“foo”;
就像一个符咒。从技术上讲,它不是复制品。这些有趣的细节是什么?你能更具体一些吗?