另一个C++学习时刻:从函数返回字符串

JnB*_*ymn 14 c++ string pointers reference

我有一些关于C++的基本问题.考虑以下代码,我尝试返回一个字符串.

const std::string&
NumberHolder::getValueString() {
    char valueCharArray[100];
    sprintf_s(valueCharArray,"%f",_value);
    std::string valueString(valueCharArray);
    return valueString;
}
Run Code Online (Sandbox Code Playgroud)

我试图返回一个字符串,其中包含一个名为_value的类成员的值.但是我收到警告,我正在尝试传回指向局部变量的指针.这当然是件坏事.如果我在这一点上对C++有足够的了解,这意味着我传回的指针在有人试图使用它时就已经有了对它的调用.所以我修改:

const std::string&
NumberHolder::getValueString() {
    char valueCharArray[100];
    sprintf_s(valueCharArray,"%f",_value);
    std::string valueString = new std::string(valueCharArray);
    return (*valueString);
}
Run Code Online (Sandbox Code Playgroud)

这应该在堆栈上创建一个指针,该指针将在此函数之外生存.这里有两个问题:1)它无论如何都不编译,我不明白为什么(错误= 无法从'std :: string*'转换为'std :: basic_string <_Elem,_Traits,_Ax>')和2 )这似乎是一个潜在的内存泄漏,因为我依赖别人来调用这个人的删除.我应该在这里使用什么模式?

In *_*ico 26

你打败了std::string在堆上分配它的意义!

只需按以下方式返回值:

std::string NumberHolder::getValueString()
{ 
    char valueCharArray[100]; 
    sprintf_s(valueCharArray,"%f",_value); 
    return std::string(valueCharArray); 
} 
Run Code Online (Sandbox Code Playgroud)

几乎现在每个编译器都会对return语句进行返回值优化(RVO),因此不应该复制.考虑以下:

NumberHolder holder;
// ...
std::string returnedString = holder.getValueString();
Run Code Online (Sandbox Code Playgroud)

与RVO,编译器会生成用于上述实现的代码NumberHolder::getValueString(),这样std::string在的位置构成returnedString,因此不需要拷贝.

  • 是的,您正在创建一个匿名的`std :: string`,但编译器实际上针对这种特定情况进行了优化,并通过直接在返回值的位置上构造`std :: string`来消除副本. (2认同)

Jam*_*lis 16

您收到此警告是因为您返回对本地字符串的引用,而不是本地字符串的副本.函数返回后,本地字符串将被销毁,并且您返回的引用无效.因此,您需要按值返回字符串,而不是通过引用:

std::string NumberHolder::getValueString()
Run Code Online (Sandbox Code Playgroud)

  • @John:根本不要在堆上创建`std :: string`.只需返回本地字符串_by value_.你的第一个例子很好; 只需更改返回类型. (5认同)