1

例如,如果我创建一个类对象的“新”实例,然后“删除”该实例,是否会清除(如释放)该实例使用的所有内存?如果实例创建了其他对象的“新”实例怎么办?他们也会受到影响吗?

“删除”究竟是如何工作的?是否有任何关于如何删除的安全规则/提示?如果我真的想保留某些东西并在那种情况下删除其他所有东西怎么办?

编辑:关于“智能指针”,如果我需要在特定时刻删除它,我还能这样做吗?如果是这样,那和“新”有什么区别?(除非应用程序意外关闭时删除智能指针?)

4

7 回答 7

1

使用smart_pointers而不是原始指针。

“删除”究竟是如何工作的?

调用对象的析构函数,然后调用::operator delete函数,释放内存。

对于 2 首先你的问题:

由于关键字 delete 调用对象的析构函数 - 您应该在析构函数中手动释放内存(如果使用某些资源,则需要释放)。简单的例子

class A {};

class B
{
public:
    A() : a(new A()) {}
   ~A() { delete a; /* free a's memory */ }
private:
    A* a;
};
于 2013-04-11T13:27:24.533 回答
1

new规则 1.除非你有充分的理由,否则不要使用。

规则 2. 如果你确实使用new,那么你必须有一个对应的呼叫到delete某个地方。

至于做什么delete:它调用对象的析构函数(如果有的话),然后释放内存。如果“清除”是指“将使用的内存设置为零或其他值”,那么通常不会。但是,如果您的意思是“使其可用于其他事物”,那么是的,这正是delete它的作用。

于 2013-04-11T13:28:42.853 回答
0

可悲的是,除非借助智能指针技巧等,否则没有这种安全的方法可以完成此操作。您可以自由使用“新建”和“删除”,因此您负责内存管理。

于 2013-04-25T15:39:02.070 回答
0

常规删除实际上做了两件事:

  1. 调用指针指向的对象的析构函数。
  2. 释放对象本身的内存,即 sizeof(object)

在这两个步骤之间,将调用任何类成员的析构函数(以及任何基类析构函数)。

请注意,这一步,即类成员被删除,仅适用于成员对象。如果成员是指针,它不会自动对它们调用“删除”。因此,您的班级的析构函数需要处理好这一点。

智能指针实现了这一点。Aunique_ptr将始终删除它自己销毁的指针。Ashared_ptr将减少指针上的引用计数(在许多共享指针之间共享),并且只有在引用计数下降到 0 时才会删除指针。

因此,通常最好使用对象而不是指针,因为您不需要调用 delete。

在函数的范围内,这一点尤为重要,因为可能会在您到达清理阶段之前引发异常,这会使您提前退出函数。但是对于自动对象,即使以这种方式退出其范围也会调用其析构函数。(这就是为什么你必须强制执行析构函数不能抛出的策略,以防万一发生这种情况)。

在类的范围内,它不太重要,因为您可以将逻辑放入析构函数中。但是,如果您的类被复制或分配,您必须更加注意何时发生,以及如果您的构造函数抛出(因此不会调用析构函数)会发生什么。

于 2013-04-11T14:01:12.280 回答
0

不,delete不会以任何方式“清除”内存或对象。它确实调用了对象析构函数,您应该在其中释放对象分配的资源。

于 2013-04-11T13:27:37.120 回答
0

使用 创建对象时new,会为所有成员分配内存获取,并调用一个构造函数获取(取决于您指定的)。您可以使用它在那里创建引用,例如:

public Foo()
{
    m_bar = new Bar();  // Bar* m_bar;
}

但是,这不会影响对象的大小。指针 ( m_bar)总是需要 4 个字节(在 32 位架构上)的内存,因此对象的大小大约为 8 个字节(至少 - 4 个m_bar字节用于指向构造函数的指针,4 个字节用于指向构造函数的指针)1

完全相反的是析构函数,它在使用时被调用delete。您可以使用它来释放所有引用:

public ~Foo()
{
    if (m_bar)  // If the pointer is not NULL, thus pointing anywhere.
        delete m_bar;  // Calls destructor of "Bar" and free it's memory.
}

所以调用delete,调用析构函数并释放对象占用的内存,但不会自动释放内存引用的对象(如此m_bar处)使用。您必须小心,这些对象将在析构函数中被删除。如果您忘记调用 delete m_bar,它可能会以我们所说的内存泄漏而告终。

使用newanddelete适用于您需要尽可能多的性能的场景(例如实时场景),但通常您应该更喜欢使用智能指针

1请注意,您无法真正说明物体的实际大小。这取决于编译器如何翻译它。

于 2013-04-11T13:28:26.980 回答
0

是否有任何关于如何删除的安全规则/提示?

是的,著名的 RAII(资源分配是初始化)就是解决方案。它声明,一个类分配的所有内存都应该在构造函数中释放。C++ 保证即使抛出异常,也会调用析构函数,并且析构函数是释放的安全港。

如果实例创建了其他对象的“新”实例怎么办?

您也应该跟踪它们,您可以将它们保留为类的成员并在析构函数中删除它们,否则您可能需要复杂的过程来跟踪它们。

于 2013-04-11T13:30:54.177 回答