如果没有从堆中为字符串文字分配内存,这是安全的吗?

时间:2014-10-08 05:05:06

标签: c++

class MyString
{
    char* str;
public:
    MyString(char* _str)
    {
        str = _str;
    }
};

int main()
{
   MyString obj1("hi");   // case 1
   char str[] = "hi";
   MyString obj2(str);  // case 2 
}

这里我没有在成员str的构造函数中从堆中分配内存。案例1和案例2都安全吗?如果没有,为什么?

2 个答案:

答案 0 :(得分:4)

在第一种情况下,它不安全,但不是因为内存的分配位置,而是因为"hi"的类型为const char*(可能是.text或.data知道) ,MyString的构造函数将其赋值给char*类型的变量。如果有人试图通过str修改字符串,则会发生未定义的行为。

第二种情况的问题是你的对象obj2指向一个没有所有权的字符串,如果它是堆栈或堆则无关紧要。这不是一件可怕的事情,我已经看到了合法用途,但必须小心谨慎。这个特殊的例子可以正常工作,因为对象和字符串都存在于堆栈中,因为它非常简单。

答案 1 :(得分:3)

第一种情况是可以的,因为“hi”是一个静态字符串 - 一个全局常量。它将至少与obj1一样长(即使obj1是全局的或者在堆上分配)。

第二种情况可能不正常,因为“hi被复制到堆栈中的str []。

在这种特殊情况下,obj2在str之前被销毁,所以很好。如果你要返回一个obj2的副本,或者它本身是在堆上分配的,那么这将是一个问题,因为它可能比str更长。

str(['h','i','\ 0'])的数据在堆栈上 - 与局部变量相同。 该内存仅在保留在范围内时才有效 - 在这种情况下,直到main()返回。 由于obj2也在堆栈上,它基本上与str具有相同的生命周期,因此在这个实例中没有问题。 但更一般地说,您可以使用不同的生命周期创建此对象的实例,可能类似于“MyString * s = new MyString(str); return s;”。现在,MyString对象将比str更长,并且将继续指向str曾经导致未定义行为的内存。 这是常常难以找到的错误的常见来源。