如何返回一个字符串从函数字面
-
21-09-2019 - |
题
我总是困惑返回字符串文字或从一个功能的字符串。有人告诉我,有可能是内存泄漏,因为你不知道什么时候记忆将被删除多少?
例如,在下面的代码,如何实现foo()
以使代码的输出的“Hello World”?
void foo ( ) // you can add parameters here.
{
}
int main ()
{
char *c;
foo ( );
printf ("%s",c);
return 0;
}
此外,如果foo()
的返回类型不是void,但您可以回到char*
,什么应该是什么?
解决方案
我假设大家不能修改主。为了让你的程序工作不泄漏,你需要的东西有静态存储:
void foo(char*& pC) // reference
{
static char theString[] = "thingadongdong";
pC = theString;
}
但实际上,这并不是非常常规C ++代码。你会使用std::string
和std::cout
,所以你不要的的的担心内存:
std::string foo(void)
{
return "better thingadongdong";
}
int main(void)
{
// memory management is done
std::cout << foo() << std::endl;
}
如果你想知道,如果事情需要手动释放,它是被做了错事。
其他提示
由于原有使用的char *的功能已被弃用,你能不能简单地用一个字符串?
const char* func1 () {return "string literal";}
string func2 () {return "another string literal";}
这两种正常工作,没有编译器警告。
然而
char* func3 () {return "yet another string literal";}
将不编译的。也不会
char* func4 () {return &"a ref to a string literal?";}
Stroustrup的说,在 “C ++编程语言”(第三版):
“字符串文字是静态分配的,使得它是安全的从函数返回一个。
const char* error_message (int i)`
{
//...
return "range error";
}
在存储保持的范围误差 error_messages()的一个调用之后不会消失。“
所以每一个程序文字串在其自身的小片的存储器,持续的节目的持续时间(即是静态分配)分配的。 把常量的字符*让编译器的前端知道你不打算(也不能)修改字符串常量的小片的内存这可能是危险的,所以他们就让尽管字符串字面量是转换这个任务幻灯片为char *已被弃用。
,而不是返回到字符串必须复制字符串文字成字符串类型,存储器呼叫者是负责的对象。
不管怎样不存在内存泄漏:单字符串文字得到其自己的一块内存被清理在程序终止;返回为const char *指针返回到文字的一块内存(知道你不能改变它);和返回到一个字符串进行复印到由呼叫者清理一个字符串对象存在于呼叫者的代码。
虽然它似乎有点丑陋符号的角度来看,我猜他们离开为const char *,以保持廉价替代品(包括无份)。
我总是困惑返回字符串文字或从一个功能的字符串。
<强>不可变的,文字串强>
据我了解,你是安全的返回一个字符串,如果直接返回类型声明为const,宣布该字符串不打算改变。这意味着你不必担心字符串/内存泄漏的寿命。
<强>可变的,非文字串强>
不过,如果你需要一个字符串,你可以就地改变,你需要考虑串的寿命和它存储在内存分配的大小。 这将成为一个问题,因为你再也不能轻率地返回包含在每次调用函数的字符串相同的内存,因为先前的使用可能已经改变内存中的内容,和/或可能仍然在使用。因此,新的内存块必须分配给持有返回的字符串。
这是其中的泄漏的可能性时,并且其中选择需要进行关于应该发生的分配和解除分配,其中。你可以有本身的功能分配,出现这种情况的文档中的内存和状态,并在其中规定,调用者必须释放内存时不再需要它(防止泄漏)。这意味着函数可以简单地返回一个char *。
另一种选择是在一些存储器到由呼叫者分配的函数来传递,并具有功能地方存储器内的字符串。在这种情况下,呼叫者都分配并负责释放该存储器。
最后,我提到过存储器和字符串的大小需要使用可变的字符串时进行管理。分配必须既足够大最初的功能,也为任何改变那些功能后作出,内存被释放之前设定的字符串。未能正确地做到这一点可以通过编写串地龙,以适应在最初分配的内存会导致缓冲区溢出;这是极其危险的,你的程序的健康和安全。它可能会导致非常硬错误和安全漏洞被发现。(因为错误的来源 - 溢流 - 可以从当程序失败所见的症状相去甚远)
像这样:
void foo(char ** pChar)
{
// Make sure the string is shorter
// than the buffer
*pChar = new char[256];
strcpy(*pChar,"Hello World!");
}
然后调用它是这样的:
foo(&c);
由于在评论中提到,要小心你存储的字符串比缓冲区小,否则你会得到一个...堆栈溢出! (双关语意)