【发布时间】:2010-09-08 06:32:07
【问题描述】:
我假设char* = "string" 与char* = new char[6] 相同。我相信这些字符串是在堆而不是堆栈上创建的。那么当我用完它们时我需要销毁它们或释放它们的内存还是它们会被自己销毁?
【问题讨论】:
我假设char* = "string" 与char* = new char[6] 相同。我相信这些字符串是在堆而不是堆栈上创建的。那么当我用完它们时我需要销毁它们或释放它们的内存还是它们会被自己销毁?
【问题讨论】:
让我们看看 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[] 的输出。因此,您应该尽可能释放它。【讨论】:
g++ -ggdb -std=c++98 a.cpp 中添加-c 标志。
游戏的名称是“只摧毁你创造的东西”。这是对:
malloc/free
calloc/free
new/delete
new []/delete []
由于您使用new [] 创建了第二个字符串,因此您有责任使用delete [] 销毁它。完成后致电delete [] string2。
现在,如果您的代码足够复杂并且难以跟踪删除,请考虑使用作用域指针或自动指针。 boost 库中的 boost::scoped_ptr 类是一个很好的起点。还请查看RAII 成语,非常方便且有用的东西。
【讨论】:
它们不一样。您的第一个示例是一个常量字符串,因此绝对不是从堆中分配的。您的第二个示例是 6 个字符的运行时内存分配,它来自堆。你不想删除你的第一个例子,但你需要delete []你的第二个例子。
【讨论】:
我假设当我执行
char* = "string"时,它与char* = new char[6]相同。
没有。第一个所做的是创建一个常量。修改它是未定义的行为。但要回答你的问题;不,你不必摧毁它们。请注意,尽可能使用std::string。
【讨论】:
没有。当您使用malloc 函数(在C 中)或new 运算符(在C++ 中)自己手动分配内存时,您只需要手动释放字符串。如果不使用malloc 或new,则char* 或字符串将在堆栈上创建或作为编译时常量。
【讨论】:
.rodata部分而不是堆栈中。
没有。当你说:
const char* c = "Hello World!";
您将 c 分配给一个“预先存在的”字符串常量,它与以下内容不同:
char* c = new char[6];
只有在后一种情况下,您才在堆上分配内存。所以你会在完成后调用 delete。
【讨论】:
new 始终是一个分配,而定义一个字符串内联实际上将数据嵌入程序本身并且不能更改(一些编译器通过一个聪明的技巧允许这样做,不要打扰)。
某些编译器会键入内联字符串,因此您无法修改缓冲区。
char* const sz1 = "string"; // embedded string, immutable buffer
char* sz2 = new char[10]; // allocated string, should be deleted
【讨论】:
您不知道字符串文字的存储位置。它甚至可能是只读内存,所以你的代码应该是这样的:
const char* c = "string";
new char 数组应该像任何其他动态分配的内存区域一样被删除。
【讨论】: