假设我有一个名为A的类:
Class A
{
...
}
以下两种实现对象的方法之间有什么区别:
void main(void)
{
A a; // 1
A *pa=new A(); // 2
}
正如我目前的理解(目前还不确定):
方法1在main()方法的堆栈帧上分配对象a,因此该对象无法删除,因为删除没有意义(不知道为什么,有人可以解释一下吗? )。
方法2在main()方法的堆栈帧上分配对象a在进程的堆上以及A * vairable pa ,因此可以删除对象删除后可以将pa指定为空。
我是对的吗?如果我的理解是正确的,有人可以告诉我为什么我不能在方法1中从堆栈中删除 a 对象吗?
非常感谢......
答案 0 :(得分:6)
对象a
具有自动存储持续时间,因此它将在定义范围的末尾自动删除。尝试手动删除它没有意义。只有具有动态存储持续时间的对象(例如*pa
已使用new
分配的对象)才需要手动删除。
答案 1 :(得分:4)
对于删除对象的部分,删除不仅调用对象的析构函数而且还释放其内存,这不会起作用,因为编译器会自动对堆栈进行内存管理,相反堆不是自动的并要求调用new和delete来管理对象的实时时间 通过调用new创建的任何对象都必须删除一次,忘记执行此操作会导致内存泄漏,因为对象内存永远不会被释放。
答案 2 :(得分:1)
方法1声明了一个变量并创建了一个对象。在方法2中,您创建了一个实例和指向它的指针。
编辑:在方法1中,对象将超出范围并将自动删除。在方法2中,指针将被自动删除,但不会被指向。那将是你的工作。
答案 3 :(得分:1)
分配做两件事:
1)为对象分配内存
2)在分配的内存上调用构造函数
删除有两件事:
1)在对象上调用析构函数
2)释放被破坏对象使用的内存
当您在堆栈上分配(A a;
)时,您告诉编译器“请为我创建一个对象,通过分配内存,然后调用该内存上的构造函数。当你在它的时候,当它超出范围时,你能处理调用析构函数并释放内存吗?谢谢!“一旦函数(main)结束,对象就会超出范围,调用析构函数,释放内存。
当您在堆上分配(A* pa = new A();
)时,您告诉编译器“请为我创建一个对象。我知道我在做什么,所以不要打扰调用析构函数或释放记忆。我会告诉你什么时候该做,其他时间“。函数(main)结束后,您分配的对象将保留在范围内,并且不会被销毁或释放。希望你有一个指向它的指针存储在你的程序中的其他地方(例如,你将pa复制到一个更大范围的其他变量)。您将不得不告诉编译器在将来的某个时刻破坏对象并释放内存。否则,会出现内存泄漏。
简单地说,“delete”命令仅适用于堆上分配的对象,因为这是C ++中的手动内存管理界面 - new / delete。它是堆分配器的命令,堆分配器对堆栈分配的对象一无所知。如果你试图在堆栈分配的对象上调用delete,你也可以在随机内存地址上调用它 - 就堆分配器而言,它们是相同的。非常类似于尝试访问数组边界外的对象:
int a[10];
std::cout << a[37] << "\n"; // a[37] points at... ? no one knows!
这并不意味着这样做:)
编辑:
附:在main
以外的函数中分配内存时,内存泄漏更为重要。当程序结束时,泄漏的内存将被释放,因此主内存泄漏可能不是什么大问题,具体取决于您的方案。但是,析构函数永远不会被泄露的对象调用。如果析构函数做了一些重要的事情,比如关闭数据库或文件,那么你手上可能会有一个更严重的错误。
答案 4 :(得分:1)
想象一下堆栈为void* stack = malloc(1.000.000);
现在,这个内存块由编译器和CPU在内部管理
它是一块共享的记忆。每个函数都可以使用它来存储临时对象。
这称为自动存储。您无法删除该内存的某些部分,因为其目的是为了
再次使用。如果明确删除内存,该内存将返回系统,
并且你不希望在共享内存中发生这种情况。
在某种程度上,自动对象也会被删除。当一个对象超出范围时,编译器会放置 不可见调用对象的析构函数,内存再次可用。
答案 5 :(得分:1)
你无法删除堆栈中的对象,因为它在内存中完全以这种方式实现 - 作为堆栈。在堆栈上创建对象时,它们会相互叠加。当对象离开作用域时,它们将从顶部以与创建它们相反的顺序被销毁(添加到堆栈顶部,并从堆栈顶部移除)。试图在堆栈中的某些内容上调用delete
会破坏该顺序。这个类比就像试图从一堆文件的中间拉出一些纸张。
编译器控制如何在堆栈上创建和删除对象。它可以做到这一点,因为它确切地知道堆栈上的每个对象有多大。由于堆栈大小是在编译时设置的,这意味着为堆栈上的内容分配内存非常快,比从堆中分配内存(由操作系统控制)快得多。
答案 6 :(得分:0)
堆栈内存的管理方式与堆内存不同。 没有必要从堆栈中删除对象:它们将被删除 在范围/功能结束时自动。