【问题标题】:Initialization class member using initializer list results a memory leak使用初始化列表初始化类成员会导致内存泄漏
【发布时间】:2019-11-24 15:47:37
【问题描述】:

我有一个类,它包含一个属性 char * 变量名,它指向一个从 new char[] 分配的 char 数组,该数组包含一个 C 样式的文本字符串。我正在使用具有属性 char[] 变量 name_val 并且等于“emtpy”的重载构造函数。在成员初始化列表中,我已将私有类成员名称初始化为 nullptr,并且在构造函数内部,我已为其分配空间取决于在 name_val 的大小上,使用 strcpy 将其复制到 name。当我编译程序时,我收到警告说, [警告] 不推荐将字符串常量转换为 'char*' [-Wwrite-strings]。我还看到内存泄漏。所以我花了一点时间搞砸,一旦我将 char name_val 设置为 const char name_val[]="empty",在重载的构造函数中,一切都工作得很好。

这里是代码,请注意,在重载的构造函数中,属性 char[] 变量名 name_val 没有设置为 const!

有人可以解释一下,在这种情况下 const 的目的是什么?

#include<iostream>
#include<cstring>

using namespace std;

class Person{
    char *name;
public:
    Person(char name_val[]="empty"):
        name{nullptr}{
            name=new char[strlen(name_val)+1];
            strcpy(name,name_val);
        }
    ~Person(){
        delete [] name;name=nullptr;
    }

    char *get_Name()const{return name;}
};

int main(){

    Person p;
    cout<<p.get_Name()<<endl;
    return 0;
}

【问题讨论】:

  • "empty" 这样的字符串文字可以存储在只读内存中。如果你用一个非 const 指针指向它,你就会为 name_val[0] = 'X'; 这样的废话打开大门,而 Crom 只知道什么样的坏蓝精灵会试图写下它。
  • 你怎么知道你有内存泄漏?

标签: c++


【解决方案1】:

使用初始化列表初始化类成员会导致内存泄漏

我也看到了内存泄漏。

显示的程序中没有内存泄漏。不清楚为什么你会认为你看到了它。

有人可以解释一下,在这种情况下 const 的目的是什么?

对象是 const 意味着它的状态(除了类类型的可变成员)不能被修改。指向const的指针/引用意味着不能通过指针/引用修改指向/引用的对象。

指向非常量的指针可以隐式转换为指向 const 的指针,但转换回不是隐式的。

字符串字面量是常量。自 C++11 以来,不能将指向非 const (char*) 的指针分配为指向 const 对象。您看到的警告消息表明您使用的是 C++ 11 之前的 C++ 版本。当时从字符串文字到char* 的转换是格式良好的,但这种转换已被弃用。


附: Person 有一个严重的设计缺陷:该类是可复制的,但如果您有意或无意地复制,程序的行为将是不确定的。

附言默认成员初始化器是多余的,因为您从不使用它。

【讨论】:

    【解决方案2】:

    当你写作时:

    Person(char name_val[]="empty")
    

    相当于写:

    Person(char *name_val="empty")
    

    现在您可以看到您正在将字符串常量分配给非常量char *,因此会出现警告。解决方案(显然)是这样写:

    Person(const char *name_val="empty")
    

    然后编译器会很高兴。

    OTOH,当你写的时候:

    Person()
    {
        char name_val[]="empty"
        ...
    }
    

    然后您在堆栈上创建一个字符数组并将给定的字符串常量复制到其中,因此不需要const(尽管在这种情况下它仍然是一个好主意)。

    我不知道你为什么认为你有内存泄漏。我在你的代码中没有看到。

    【讨论】:

    • 我编译的时候,有时返回零值有时会崩溃,可能是我写代码的时候写错了,还是谢谢你,终于明白了
    猜你喜欢
    • 2021-09-16
    • 1970-01-01
    • 2020-05-10
    • 2015-04-17
    • 2019-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-12
    相关资源
    最近更新 更多