【问题标题】:Memory management of class object attributes in C++C++中类对象属性的内存管理
【发布时间】:2019-12-04 23:35:20
【问题描述】:

如果之前有人问过这个问题,我很抱歉。我搜索了互联网,但找不到任何明确的答案。

这是问题:

假设我有一个名为 Object 的公共类,它有 2 个属性。一个是int attr1,另一个是char * attr2。构造函数是(我有一个头文件):

Object::Object(int param1, char * param2) 
{
  attr1=param1; 
  attr2 = new char[strlen(param2)+1]; // I understand that by doing this the values are stored in the heap
  strcpy(attr2, param2); 
}

我知道在 Object 类的析构函数中我需要写delete [] attr2

在另一个文件 main.cpp 中,我以这种方式创建了一个新对象:

char * name = "Aname";
Object myObject = new Object(3, name);

据我了解,每当使用new 时,该值都会存储在堆中。因此,delete 是必要的,以避免内存泄漏。 这里我使用了new 操作符来创建一个对象。因此 myObject 是指向存储在堆中的 Object 的指针。当我不再需要它时,我需要这样做:delete myObject

所以这是我的问题:由于 myObject 指向的对象存储在堆中,这是否意味着它的所有属性都存储在堆中(包括attr1,它只是一个 int)? 如果是这样,为什么我也不必释放它(意味着在析构函数中使用运算符delete)?

感谢您的帮助!

注意:英语不是我的母语,如有错误请见谅。

【问题讨论】:

  • 不相关:我知道这样做会将值存储在堆中最好使用术语动态内存而不是堆。堆是动态内存的常见实现,但 C++ 实现可以改为使用仙尘作为动态内存,只要实现者可以使其工作。

标签: c++ memory heap-memory new-operator delete-operator


【解决方案1】:

您在第二个示例中显示的代码无法编译,因为

  • myObject 未声明为指针

  • 在 C++11 及更高版本中,非 const char* 指针不能指向字符串文字。

所以你需要这个:

Object::Object(int param1, const char * param2) 
{
  attr1 = param1; 
  attr2 = new char[strlen(param2)+1];
  strcpy(attr2, param2); 
}
const char * name = "Aname";
Object * myObject = new Object(3, name); // <-- note the * !

话虽如此,其余的 cmets 都是正确的。由于myObject 是用new 创建的,它的数据成员驻留在动态内存(即堆)中,你必须调用delete myObject 来销毁它并释放它的内存。完成使用它。而且由于您直接使用new[]attr2 分配内存,因此您需要手动调用delete[] attr2 来释放它。

但是,您不直接使用newattr1 分配内存,因此您不需要手动调用delete attr1attr1的内存由编译器管理,当myObject被销毁时会自动释放。

简而言之,当某个函数/运算符显式分配某物时,必须使用相应的函数/运算符显式释放它,例如:

  • 当使用 C++ newnew[] 运算符显式分配某些内容时,必须分别使用 deletedelete[] 运算符显式释放它。

  • 如果使用 C 运行时 (m|c|re)alloc() 函数显式分配某些内容,则必须使用 C 运行时 free() 函数显式释放它。

  • 如果使用 Win32 API (Local|Global)Alloc()(Local|Global)ReAlloc() 函数显式分配某些内容,则必须使用 Win32 API (Local|Global)Free() 函数显式解除分配。

【讨论】:

  • 是的!我忘记了 Object 之后的 *。谢谢您的回答。另一个问题:存储在指针myObject中的地址是不是我创建的对象的第一个属性的地址?
  • 旁注:char * name = "Aname"; 也是非法的。 "Aname" 是一个 String Literal,一个常量字符数组,如果没有允许赋值的非标准语言扩展,就不能将其赋值给非常量指针。出于遗留原因,这通常是允许的,因为在过去将字符串文字分配给 char * 过去很常见。尝试通过非const 指针修改常量字符串数据导致的错误也很常见。
  • 感谢您的回答和附注。它们对像我这样的初学者非常有帮助!为了澄清我之前的评论,我的意思是与指向数组的指针相比,例如,我知道存储该数组的第一个元素的地址。这对我的对象也有效吗?如果更改我声明属性的顺序,它会更改 myObject 指向的位置吗?
  • @CSstudZ 是的,对象的内存地址与其第一个数据成员的内存地址相同。但是,该数据成员可能不是您所期望的。例如,在具有虚方法的类中,对象指针指向对象的虚方法表,它是由编译器隐式创建的,它不指向您在类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 2019-05-11
  • 1970-01-01
  • 2012-06-13
  • 2017-05-19
相关资源
最近更新 更多