我有一些关于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)这似乎是一个潜在的内存泄漏,因为我依赖别人来调用这个人的删除。我应该在这里使用什么模式?
答案 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);
}