【问题标题】:Is an array of an object stored in stack or heap?对象数组是存储在堆栈还是堆中?
【发布时间】:2021-06-19 16:34:27
【问题描述】:

在以下代码中:

#include <iostream>
using namespace std ;

class TypeA {
 public:
  int a[10] ;
  TypeA () {
    int i ;
    for ( i = 0; i != 9; i++) {
      a[i] = double(i) ;
    }
  }
  void printVal() {
    int i ;
    for ( i = 0; i != 9; i++) {
      cout << a[i] << endl ; 
    }
  }
  ~TypeA() {
    //delete[] a;
    cout << "TypeA destructor called"<<endl;
  }

} ;


int main() {
  TypeA * ptrA = new TypeA() ;
  ptrA->printVal();
  delete ptrA ;

  return 0 ;
}

new TypeA() 在堆上实例化一个对象,并返回一个指针并保存在main() 中。我想知道a[]TypeA 是否存储在堆上?如果是这样,释放它的适当方法是什么?

【问题讨论】:

  • 你能解释一下是什么让你产生了这样的印象吗(不是,顺便说一句)?
  • 您不需要释放它 - C++ 将所有内容放入 Class 的内存中......因此分配一个新的 TypeA 为 int[10] 数组在内存空间中的其余部分提供了空间班级。删除 Class 时,会自动释放用于 int[10] 数组的内存。根本没有内存泄漏...

标签: c++ memory-management memory-leaks heap-memory


【解决方案1】:

通常,除非您的类包含指针,否则整个对象都包含在一个分配中。因此,您无需执行任何特殊操作即可清除它。

您可以在之前调用new[] 的事物上调用delete[],并且它必须完全与您获得的指针相同。由于从未直接实例化 a 属性,因此在其上调用 delete 是未定义的行为。

new 在概念上的工作方式并不那么奇特,它只是分配sizeof(X) 字节并调用该对象上的构造函数。 new[] 不同之处仅在于它分配sizeof(X) * N 字节并调用构造函数N 次。

【讨论】:

  • new[] 还存储分配了多少对象。
【解决方案2】:

试试这个代码:

#include <iostream>
#include <type_traits>
#include <cassert>
struct A{
    A() {
        std::cout<<"Called A() for "<<std::hex<<this<<'\n';
    }
};

struct B {
    A arr[10];
    B() {
        std::cout<<"Called B() for "<<std::hex<<this<<'\n';
    }
};

int main() {
    B* ptr = new B;
    static_assert(std::is_standard_layout<B>::value); //Sanity check for this example's case
    std::cout<<"Got ptr = "<<std::hex<<ptr<<std::dec<<" + sizeof(B)  = "<<sizeof(B)<<'\n';
    delete ptr;
    return 0;
}

输出是:

Called A() for 0x10d4eb0
Called A() for 0x10d4eb1
Called A() for 0x10d4eb2
Called A() for 0x10d4eb3
Called A() for 0x10d4eb4
Called A() for 0x10d4eb5
Called A() for 0x10d4eb6
Called A() for 0x10d4eb7
Called A() for 0x10d4eb8
Called A() for 0x10d4eb9
Called B() for 0x10d4eb0
Got ptr = 0x10d4eb0 + sizeof(B)  = 10

如果您看到代码和相应的输出,您可以关联B 类型的对象ptr0x10d4eb0 的堆上分配,它的大小为10(对应于10 个字节,1对象 A) 的每个字节。所以从0x10d4eb00x10d4eb9 的内存地址都在堆上。而如果你看到A的对象的地址,它们都属于这个地址范围。因此,A 的对象确实位于堆内存区域中。

现在谈到如何处理arr,需要调用delete/delete[],视情况而定,仅在使用new/new[]分配的对象上。由于arr 不是这种情况,因此无需调用delete[]

【讨论】:

    猜你喜欢
    • 2015-05-03
    • 2016-12-27
    • 1970-01-01
    • 1970-01-01
    • 2010-10-13
    • 2011-08-25
    • 2020-01-10
    • 2016-03-06
    相关资源
    最近更新 更多