Ответ 1
Нет. Это неправда. Даже если mystring
вышел из сферы действия и уничтожен, ret
имеет копию mystring, поскольку функция MyFunc
возвращает значение.
В С++, каков наилучший способ вернуть функцию local 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...???
Нет. Это неправда. Даже если mystring
вышел из сферы действия и уничтожен, ret
имеет копию mystring, поскольку функция MyFunc
возвращает значение.
Будет проблема, если ваш код похож:
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).
Вы пробовали? Строка копируется при ее возврате. Хорошо, что официальная строка, на самом деле копия, вероятно, оптимизирована, но в любом случае она безопасна в использовании.
Как уже упоминалось, копируется std::string. Таким образом, даже исходная локальная переменная вышла за пределы области действия, вызывающая сторона получает копию std::string.
Я думаю, что чтение на RVO может полностью очистить ваше замешательство. В этом случае он точно упоминается как NRVO (Именованный RVO), но дух тот же.
Чтение бонусов: проблема с использованием RVO заключается в том, что это не самая гибкая вещь в мире. Одним из больших жуков С++ 0x является ссылки rvalue, которые намереваются решить эту проблему.
Ну, ret будет иметь значение mystring после MyFunc(). В случае возврата результата по значению временный объект создается путем копирования локального.
Что касается меня, есть несколько интересных подробностей о теме в этих разделах С++ FAQ Lite.
Это зависит от варианта использования. Если экземпляр должен нести ответственность за строку, жало должно быть возвращено ссылкой const. Проблема в том, что делать, если нет объекта для возврата. С указателями недопустимый объект может быть сигнализирован с использованием 0. Такой "нулевой объект" может также использоваться со ссылками (например, NullString в фрагменте кода). Из-за лучшего способа подачи недопустимого возвращаемого значения выбрасываются исключения.
Другой вариант использования - если ответственность за строку передается вызывающему. В этом случае следует использовать auto_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;
}
С уважением, Валентин Хейниц