函数内的字符串文字:自动变量还是在堆中分配?

我们在里面使用的字符串文字是自动变量吗? 或者它们是否在堆中分配,我们必须手动释放?

我的情况类似于下面显示的代码,其中我将字符串文字分配给类的私有字段(在代码中标记为ONE),并在稍后的程序中检索它并使用它(标记为TWO)。 我是否将堆栈中的变量分配给ONE中的字段? 代码是否可以引用悬空指针,在这种情况下,因为程序足够小,所以可以工作?

我已编译并运行它,它工作正常,但我在我的实际程序中遇到了一个奇怪的崩溃,我将字符串文字分配给类的字段,我怀疑上面提到的情况。

#include  using namespace std; class MemoryLeak { private: char *s; public: MemoryLeak() {} void store() { s = "Storing a string"; // ONE } char *retrieve() { return s; } }; int main() { MemoryLeak *obj = new MemoryLeak(); obj->store(); cout <retrieve() << endl; // TWO delete obj; return 0; } 

我应该将变量“s”声明为char数组而不是指针吗? 我打算使用std :: string,但我只是对此感到好奇。

任何指针或帮助,一如既往,非常感谢:)谢谢。

字符串文字将由编译器放置在二进制文件的初始化数据或文本(代码)段中,而不是驻留在(运行时分配的)内存或堆栈中。 因此,您应该使用指针,因为您将引用编译器已为您生成的字符串文字。 请注意,修改此(通常需要更改内存保护)将更改此文字的所有用法。

修改字符串文字是未定义的行为,并且很可能是程序崩溃的原因(ISO C ++:2.13.4 / 2)。 该标准允许从字符串文字转换为char*以向后兼容C,如果您绝对需要,您应该只在代码中进行转换。

如果您希望将字符串文字视为常量,则可以将成员的类型更改为const char *

如果您的设计要求可以修改s ,那么我建议将其类型更改为std::string

谢谢科迪和理查德。

我找到了这个bug的原因。 这是因为我正在对已经删除的对象进行删除。 我在做:

 if (obj != NULL) delete obj; 

我改成了:

 if (obj != NULL) { delete obj; obj = NULL; } 

学习C ++绝对有趣:)

也许崩溃的原因是你没有0终止字符串?

让我们来看看你的选择。
你还应该做几件事:

  /* * Should initialize s to NULL or a valid string in constructor */ MemoryLeak() { store(); } void store() { // This does not need to be freed because it is a string literal // generated by the compiler. s = "Storing a string"; // ONE // Note this is allowed for backward compatibility but the string is // really stored as a const char* and thus unmodifiable. If somebody // retrieves this C-String and tries to change any of the contents the // code could potentially crash as this is UNDEFINED Behavior. // The following does need to be free'd. // But given the type of s is char* this is more correct. s = strdup("Storing a string"); // This makes a copy of the string on the heap. // Because you allocated the memory it is modifiable by anybody // retrieving it but you also need to explicitly de-allocate it // with free() } 

你正在做的是使用C-Strings。 这些不应该与C ++ std :: string混淆。 C ++ std :: string自动初始化为空字符串。 分配的任何内存都已正确解除分配。 它可以很容易地作为可修改和不可修改的版本返回。 它也易于操纵( 缩小变化)。 如果你增长了一个C-String,你需要重新分配内存并将字符串复制到新的内存等(这非常耗时,容易出错)。

为了应对动态分配对象,我将学习智能指针。
有关智能指针的更多详细信息,请参阅此文章。
聪明的指针或谁拥有你宝贝

 std::auto_ptr obj(new MemoryLeak()); obj->store(); std::cout << obj->retrieve() << std::endl; // TWO // No need to delete When object goes out of scope it auto deletes the memory.