我的代码经常将 C++ 字符串转换为 CStrings,我想知道如果原始字符串是在堆栈上分配的,CString 是否也会在堆栈上分配?例如:
string s = "Hello world";
char* s2 = s.c_str();
s2
会分配在栈上还是堆上?换句话说,我需要删除 s2
吗?
相反,如果我有这个代码:
string s = new string("Hello, mr. heap...");
char* s2 = s.c_str();
s2
现在会在堆上,因为它的起源在堆上吗?
为了澄清,当我询问 s2
是否在堆上时,我知道指针在堆栈上。我在问它指向的东西是在堆上还是在栈上。
最佳答案
string s = "Hello world";
char* s2 = s.c_str();
Will s2 be allocated on the stack, or in the heap? In other words... Will I need to delete s2?
不,不要 delete s2
!
s2
如果上述代码在函数内部,则在堆栈上;如果代码在全局或命名空间范围内,则 s2
将在一些静态分配的动态初始化数据段中。无论哪种方式,它都是一个指向字符的指针(在这种情况下,它恰好是 'H'
的文本内容的 ASCIIZ 表示中的第一个 s
字符)。该文本本身位于 s
的任何位置object 感觉就像在构建那个表示。允许实现按照他们喜欢的方式执行此操作,但 std::string
的关键实现选择是它是否提供“短字符串优化”,允许将非常短的字符串直接嵌入到 s
对象以及是否 "Hello world"
足够短,可以从优化中受益:
- 如果是,那么
s2
将指向s
内的内存,将按照s2
的说明进行堆栈或静态分配以上 - 否则,在
s
内会有一个指向动态分配(自由存储/堆)内存的指针,其中“Hello world\0”内容的地址由.c_str()
返回会出现,s2
将是该指针值的拷贝。
请注意 c_str()
是 const
,因此要编译您的代码,您需要更改为 const char* s2 = ...
.
您不得delete s2
。 s2
的数据积分仍由 s
拥有和管理对象,将因任何对非 const
的调用而失效s
的方法或通过 s
超出范围。
string s = new string("Hello, mr. heap...");
char* s2 = s.c_str();
Will s2 now be on the heap, as its origin was on the heap?
此代码无法编译,如 s
不是指针,字符串没有像 string(std::string*)
这样的构造函数.您可以将其更改为:
string* s = new string("Hello, mr. heap...");
...或...
string s = *new string("Hello, mr. heap...");
后者会造成内存泄漏并且没有任何用处,所以让我们假设前者。那么:
char* s2 = s.c_str();
...需要成为...
char* s2 = s->c_str();
Will s2 now be on the heap, as its origin was on the heap?
是的。在所有情况下,特别是如果 s
本身在堆上,那么:
- 即使
s
内有一个短字符串优化缓冲区c_str()
产生一个指针,它必须在堆上,否则 - 如果
s
使用指向更多内存的指针来存储文本,该内存也将从堆中分配。
但同样,即使确定 s2
指向堆分配的内存,您的代码不需要释放该内存 - 它会在 s
时自动完成被删除:
string* s = new string("Hello, mr. heap...");
const char* s2 = s->c_str();
...use s2 for something...
delete s; // "destruct" s and deallocate the heap used for it...
当然,通常最好只使用 string s("xyz");
除非您需要超出本地范围的生命周期,以及 std::unique_ptr<std::string>
或 std::shared_ptr<std::string>
否则。
关于c++ - string.c_str() 需要解除分配吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8843604/