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


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 都安全吗?如果没有,为什么?

在第

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

第二种情况的问题在于,您的对象obj2指向一个它没有所有权的字符串,无论它是堆栈还是堆。这不是一件可怕的事情,我已经看到了它的合法用途,但必须小心翼翼地完成。这个特定示例可以正常工作,因为对象和字符串都存在于堆栈中,并且因为它非常简单。

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

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

这种特殊情况下,obj2 在 str 之前被销毁,所以没问题。如果您要返回 obj2 的副本,或者它本身被分配到堆上,那么这将是一个问题,因为它的寿命可能超过 str。

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

最新更新