我认为这char* = "string"
与char* = new char[6]
. 我相信这些字符串是在堆而不是堆栈上创建的。那么,当我用完它们时,我是否需要销毁它们或释放它们的内存,或者它们是否会被自己销毁?
8 回答
malloc
不需要。当您使用函数(在 C 中)或new
运算符(在 C++ 中)手动分配内存时,您只需要手动释放字符串。如果不使用malloc
or new
,则char*
or 字符串将在堆栈上创建或作为编译时常量。
不,当你说:
const char* c = "Hello World!";
您将 c 分配给一个“预先存在的”字符串常量,它与以下内容不同:
char* c = new char[6];
只有在后一种情况下,您才在堆上分配内存。所以你会在完成后调用 delete 。
我假设当我做
char* = "string"
与char* = new char[6]
.
不,第一个做的是创建一个常量。修改它是未定义的行为。但要回答你的问题;不,你不必摧毁它们。只是一个说明,总是std::string
尽可能使用。
游戏的名称是“只摧毁你创造的东西”。这是对:
malloc
/free
calloc
/free
new
/delete
new []
/delete []
由于您使用 . 创建了第二个字符串new []
,因此您有责任使用 . 销毁它delete []
。完成后打电话delete [] string2
。
现在,如果您的代码足够复杂并且难以跟踪删除,请考虑使用范围指针或自动指针。boost 库中的boost::scoped_ptr
类是一个很好的起点。还要查看RAII成语,非常方便和有用的东西。
他们不一样。您的第一个示例是一个常量字符串,因此绝对不是从堆中分配的。您的第二个示例是 6 个字符的运行时内存分配,它来自堆。你不想删除你的第一个例子,但你需要delete []
你的第二个例子。
您不知道字符串文字的存储位置。它甚至可能是只读内存,因此您的代码应为:
const char* c = "string";
并且应该像任何其他动态分配的内存区域一样delete d新的 char 数组。
让我们看看 GCC 4.8 x86-64 Linux 做了什么
程序:
#include <cstdio>
int main() {
const char *s = "abc";
char *sn = new char[4];
sn[3] = '\0';
std::printf("%s\n", s);
std::printf("%s\n", sn);
}
编译和反编译:
g++ -c -ggdb -o a.o -std=c++98 a.cpp
objdump -CSr a.o
输出包含:
const char *s = "abc";
8: 48 c7 45 f0 00 00 00 movq $0x0,-0x10(%rbp)
f: 00
c: R_X86_64_32S .rodata
char *sn = new char[4];
10: bf 04 00 00 00 mov $0x4,%edi
15: e8 00 00 00 00 callq 1a <main+0x1a>
16: R_X86_64_PC32 operator new[](unsigned long)-0x4
1a: 48 89 45 f8 mov %rax,-0x8(%rbp)
解释:
char *s = "abc"
进入.rodata
。所以你不能free
以任何方式。char *sn = new char[4];
来自 的输出operator new[]
。所以你应该尽可能释放它。
new 始终是分配,而定义字符串内联实际上将数据嵌入程序本身并且无法更改(某些编译器通过巧妙的技巧允许这样做,不要打扰)。
一些编译器键入内联字符串,因此您无法修改缓冲区。
char* const sz1 = "string"; // embedded string, immutable buffer
char* sz2 = new char[10]; // allocated string, should be deleted