我对动态内存分配概念有一点困惑。 如果我们声明一个指针说一个char指针,我们需要分配足够的内存空间。
char* str = (char*)malloc(20*sizeof(char));
str = "This is a string";
但这也有效。
char* str = "This is a string";
那么在这种情况下我们必须分配内存空间?
答案 0 :(得分:7)
在第一个示例中,您有内存泄漏
char* str = (char*)malloc(20*sizeof(char));
str = "This is a string"; // memory leak
已分配的地址将替换为新地址。 新地址是“This is a string”的地址。
你应该改变第二个样本。
const char* str = "This is a string";
因为“这是一个字符串”是写保护区。
答案 1 :(得分:4)
可能是C ++ 98代码段
char* str = (char*)malloc(20*sizeof(char));
str = "This is a string";
执行以下操作:(1)分配20个字节,将指针存储到str
中的内存块,(2)在str
中存储指向文字字符串的指针。您现在无法引用先前分配的块,因此无法释放它。你已经泄露了记忆。
请注意,由于str
已声明为char*
,因此编译器无法实际检测您是否尝试使用修改文字。令人高兴的是,在C ++ 0x中,不能编译。我真的很喜欢改变规则!
代码段
char* str = "This is a string";
在名为char*
的{{1}}变量中存储指向字符串文字的指针,就像在第一个示例中一样,就像该示例一样,它不会使用C ++ 0x编译器进行编译。
而不是这种愚蠢,请使用标准库中的str
,并在代码中自由地使用std::string
。
干杯&第h。,
答案 2 :(得分:2)
在第一个示例中,您动态从堆中分配内存。它可以被修改,并且必须被释放。在第二个示例中,编译器静态分配了内存,并且无法修改,也不能释放。对于字符串文字,您必须使用const char*
而不是char*
来反映这一点并确保安全使用。
答案 3 :(得分:2)
分配给char*
变量使其指向其他内容,那么如果您立即忘记它,为什么要首先分配内存?那是内存泄漏。你可能意味着这个:
char* str = (char*)malloc(20*sizeof(char));
strcpy(str, "This is a string");
// ...
free(str);
这会将第二个字符串复制到第一个字符串。
由于这是标记的C ++,因此您应该使用std::string
:
#include <string>
std::string str = "This is a string";
不需要手动内存分配和释放,并且分配会按照您的想法执行。
答案 4 :(得分:1)
在第一个例子中,你只是做错了。您在堆上分配动态内存并让str
指向它。然后你只是让str
指向一个字符串文字,并且分配的内存被泄露(你没有将字符串复制到已分配的内存中,你只需更改地址str
指向的地址,你就会有在第一个例子中使用strcpy
。
答案 5 :(得分:1)
我想添加到Alexey Malistov's Answer,在第一个示例中通过将“This is a string”复制到str
来避免内存泄漏,如下面的代码所示:
char* str = (char*)malloc(20*sizeof(char));
strcpy(str, "This is a string");
请注意,可以我并不是说你有。它只是增加了一个为这个线程增加价值的答案。
答案 6 :(得分:1)
字符串文字是该语言的一个特例。让我们仔细看看您的代码,以便更好地理解这一点:
首先,在内存中分配一个缓冲区,并将该内存的地址分配给str
:
char* str = (char*)malloc(20*sizeof(char));
然后,您将字符串文字指定给str
。这将覆盖之前保存的str
,因此您将丢失动态分配的缓冲区,从而导致内存泄漏。如果您想修改已分配的缓冲区,则需要在某个时候取消引用str
,如str[0] = 'A'; str[1] = '\0';
中那样。
str = "This is a string";
那么,str
现在的价值是多少?编译器将所有字符串文字放在静态内存中,因此程序中每个字符串文字的生命周期等于整个程序的生命周期。此语句编译为类似于str = (char*)0x1234
的简单赋值,其中0x1234
应该是编译器放置字符串文字的地址。
这解释了为什么这种方法很有效:
char* str = "This is a string";
另请注意,静态内存不能在运行时更改,因此您应该使用const char*
进行此分配。
那么在这种情况下我们必须分配内存空间?
在许多情况下,例如当您需要修改缓冲区时。换一种说法;当你需要指向一些不能成为静态字符串常量的东西时。