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

时间:2010-07-19 15:43:50

标签: c++ string reference pointers

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

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

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

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

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

4 个答案:

答案 0 :(得分:26)

你通过在堆上分配std::string来打败它!

只需按以下方式返回值:

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

现在几乎每个编译器都会在return语句中执行return value optimization (RVO),因此不应该复制。请考虑以下事项:

NumberHolder holder;
// ...
std::string returnedString = holder.getValueString();

使用RVO,编译器将为NumberHolder::getValueString()的上述实现生成代码,以便在std::string的位置构建returnedString,因此不需要复制。

答案 1 :(得分:16)

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

std::string NumberHolder::getValueString()

答案 2 :(得分:3)

如果返回临时变量但是将其绑定到const引用中,则第一次尝试是正确的。

const std::string NumberHolder::getValueString(){}

const std::string& val = NumberHolder::getValueString();

const。但是你的第二次尝试是危险的,取决于其他人要删除。

答案 3 :(得分:0)

std::string *valueString = new std::string(valueCharArray);

您需要创建一个指针变量来保存new的结果,因为它返回指针。然而,理想的解决方案实际上只是按价值回报:

std::string NumberHolder::getValueString() {
    ...
    return std::string(valueCharArray);
}