我需要处理关于c ++“string”对象的内存分配,范围和删除吗?
例如:
#include <string>
const char* func1() {
const char* s = "this is a literal string";
return s;
}
string func2() {
std::string s = "this is a literal string";
return s;
}
const char* func3() {
std::string s = "this is a literal string";
return s.c_str();
}
void func() {
const char* s1 = func1();
std::string s2 = func2();
const char* s3 = func3();
delete s1; //?
delete s3; //?
}
func2:我不需要'删除's2。 func3:我需要'删除s3'吗?
顺便说一下,func1正确吗?离开func1范围后,字符内存内容是否仍然可用?如果是,我不再需要它时应该删除吗?答案 0 :(得分:16)
func1()
返回指向字符串文字的指针。您不能删除字符串文字。 func2()
(可能是您省略了std::
前缀)返回std::string
。它照顾好自己。 func3()
返回一个指向由std::string
对象管理的字符串的指针,该对象在函数退出时被销毁。函数返回后,不得触摸该指针。 您必须处理此函数返回的内存:
const char* func4() {
char* s = new char[100];
// fill char array with a string
return s;
}
但是,手动资源管理很棘手。对于初学者,如果一个函数返回一个裸指针,你不知道它是指向一个对象(char
)还是一个数组,以及是否需要删除它。你应该避免这一切,只要坚持std::string
。
答案 1 :(得分:3)
你对s3有一个不同的问题,即函数func3()在函数返回时返回一个超出范围的对象的指针。不。
澄清:func3()中的本地字符串对象将在函数返回时停止存在,因此无需删除。但是,您仍然有一个指向其内部缓冲区的指针,您将返回该指针。你无法使用它。
这里非常好,详细的过去答案,以免产生更多混乱:Is it more efficient to return a const reference
答案 2 :(得分:1)
我将相关代码剪切到每个函数并处理其返回值,并在下面发表评论:
const char* func1() {
const char* s = "this is a literal string";
return s;
}
const char* s1 = func1();
delete s1; //?
您无法删除s1
,因为它指向的字符串不会存在于堆中。
string func2() {
string s = "this is a literal string";
return s;
}
string s2 = func2();
这很好。 func2
的{{1}}超出了范围并进行了清理。 s
将复制s2
中的字符串,并在s
结束时自行清理。
func
const char* func3() {
string s = "this is a literal string";
return s.c_str();
}
const char* s3 = func3();
delete s3; //?
返回一个指向已释放字符串的指针。执行func3
后,您将获得双重免费例外。
答案 3 :(得分:1)
在func3中,您的字符串本地是由编译器调用隐式构造函数string(const char*)
创建的,其内部缓冲区使用字符串文字的副本进行初始化。然后返回一个指向字符串内部缓冲区的指针,该指针会立即超出范围,并在函数返回后立即释放。