我需要创建一个解析函数,所以我写了这个:
inline const char* parse(const int &arg)
{
return std::to_string(arg).c_str();
}
看起来很合理 - 至少对我来说 - 但是当我尝试使用 std::cout 而不是整数值查看此函数的值时,我得到了一些随机的 ascii 字符。
所以我尝试更改函数,结果是这样的:
inline const char* parse(const int &arg)
{
return (new std::string(std::to_string(arg)))->c_str();
}
它按预期工作,但我想知道的是为什么函数的第一种情况不能正常工作。
另外,出现了一个次要问题(可能是一个愚蠢的问题,因为我是初学者) - 如果我动态创建 std::string ,我应该用 std::move 返回函数的值吗?
return std::move((new std::string(std::to_string(arg)))->c_str());
答案 0 :(得分:1)
inline const char* parse(const int &arg)
{
return std::to_string(arg).c_str();
}
函数 parse
的本地新字符串是从 std::to_string(arg)
创建的,您可以通过 c_str
获得它的内部字符串。 c_str
当然会返回 const char *
,但现在这会产生一个问题。该字符串仍然是函数的本地字符串,但是在函数结束时它被销毁后,究竟返回了什么? c_str
只返回一个指向内部字符串的指针,它不会创建复印件。因此,您有一个悬空指针:它指向已释放的内存。
inline const char* parse(const int &arg)
{
return (new std::string(std::to_string(arg)))->c_str();
}
new
在堆上创建一个字符串。在前面的示例中,在堆栈上创建了一个字符串,该字符串在函数结束后被释放,但堆不是这样工作的。您必须使用 delete
手动删除内存。这会产生另一个问题:您返回 c_str
并且它有效,因为字符串尚未释放,但是现在如何释放字符串?确实,你不能,因为没有指向它的指针,所以你造成了内存泄漏。
您返回 const char *
的原因是:
我需要返回 const char* 因为该函数只能用作另一个函数中的参数(参数的类型是 const char*)。
但是您仍然可以返回 std::string
并在返回值上使用 c_str
。 puts
的示例:
#include <cstdio>
#include <string>
std::string parse(const int &arg)
{
return std::to_string(arg);
}
int main()
{
std::puts(parse(42).c_str());
return 0;
}
答案 1 :(得分:0)
这在第一种情况下会调用未定义的行为。您创建了一个字符串对象,该对象的生命周期在函数返回时结束,因此您返回的指针此时也将无效。
在第二种情况下,你会造成内存泄漏,因为字符串对象永远不会被删除。
你可以做的是复制字符串,即像这样:
return strdup(str.c_str());
当然,调用者必须在完成后释放这个指针。所以主要问题是为什么你不能返回字符串对象本身,这将是安全的方法。
std::string parse(const int &arg)
{
return std::to_string(arg);
}