如果我在不使用诸如“Object s(someval)”之类的 new 关键字的情况下创建了一个对象,但是该对象构造函数使用了 new,那么当该对象超出范围时,是否会为它的新分配调用析构函数?我觉得好像是,但我不确定。
5 回答
让我们给物体起个名字,好吗?
struct A {
A() b(new B) {}
B* b;
C c;
};
A a;
这里调用了a
' 的析构函数。的析构函数也是如此A::c
(被析构时会自动调用a
)。
然而,*A::b
' 的析构函数没有被调用——实际上,指针对象A::b
本身被正确地释放了,但是因为它是一个原始类型(它是一个指针!)什么都没有发生。然而,指针 *A::b
需要通过调用手动销毁(并释放其内存)delete
。
当该对象超出范围时,是否会为它的新分配调用析构函数?
这取决于如何Object
定义。
如果返回的指针new
存储在某个数据成员中Object
,该数据成员delete
被Object
自身的析构函数调用,那么是new
的,当s
超出范围时,分配的对象也将被销毁。
否则,没有。在丢失对已分配对象的最后一个指针/引用之前,每个调用都new
必须与相应的调用匹配delete
,否则会发生内存泄漏。
由于这样做很容易失败,并且由于也很容易错误地取消引用悬空的指针(即指向生命周期已结束的对象),因此通常最好避免通过原始指针执行手动内存管理,new
和delete
(或它们的数组对应项)。
当您需要控制对象的生命周期时,总是更喜欢使用 RAII 包装器,例如std::shared_ptr<>
orstd::unique_ptr<>
除非您真的知道自己在做什么并且不能做其他事情。
不,delete
如果您将该动态分配的指针存储为数据成员,则必须在析构函数中显式使用它。这也引入了三规则(C++ 11 中的五规则),这很麻烦。这就是为什么在可能的情况下应该优先使用堆栈分配的对象。
当需要指针时,请使用 RAII 包装器,例如std::vector
动态分配的数组或智能指针,例如std::unique_ptr
or std::shared_ptr
,用于单个动态分配的对象。这些为您和您管理内存,这不是额外的工作。
不,它不会......您必须delete
在您分配的对象的析构函数中定义new
. 您使用在堆上创建一个对象new
,当您的对象被销毁时,您将丢失对创建内存泄漏的对象的引用。为避免这种情况,您可以使用智能指针,例如shared_ptr
.
不,您必须在析构函数中为该对象显式调用 delete