C++:删除对象还是删除成员?

标签 c++ class heap-memory dynamic-memory-allocation

想问一下功能上的区别;也许要求一个示例场景,我应该从下面的主要方法中的选项之一中进行选择:

#include <iostream>

using namespace std;

class A{
    private:
        int x, y;
    public:
        A(int, int);
    };

class B{
    private:
        int *x, *y;
    public:
        B(int, int);
        ~B();
    };

A:: A(int x, int y){
    this->x = x; this->y = y;
    }

B:: B(int x, int y){
    this->x = new int(x);
    this->y = new int(y); 
    }

B:: ~B(){
    delete this->x;
    delete this->y;
    }

int main(){
    int x = 0, y = 0;
    A* objA = new A(x, y);  // line 1
    B objB1(x, y);          // line 2
    B* objB2 = new B(x, y); // line 3

    delete objA;
    delete objB2;
    return 0;
    }

我知道主方法 B objB1(x, y) 中的第二个声明明显不同于其他 2 个,但是有人可以解释标记为 1 的行中构造函数之间的功能差异和 3?这两个声明中是否有任何不良做法?

谢谢

NAX

更新

首先,我感谢大家给出的所有答案,我真的得到了一些很好的见解。我已经编辑了上面的代码,因为一些答案指出我没有删除我使用的对象,这是公平的,但这不是我的问题的目的。我只是想深入了解创建类的不同方法之间的功能差异。感谢所有针对这一点的人。我仍在通读答案。

最佳答案

"The functional difference..."

在第 1 行,您通过使用 new 关键字在 上分配了一个类型 A 的对象。在堆上,为 objA 指向的对象分配空间,这意味着在堆上连续创建 2 个 int,符合您的 ivar 定义。

在第 2 行,您在堆栈 上创建了一个 B 类的新对象。当它超出范围时,它将自动调用其析构函数。但是,当 B 被分配时,它将分配两个 int 指针(不是 int)的空间,这将依次分配在 heap 上,正如您在 B 中指定的那样构造函数。当 objB1 超出范围时,指针将被析构函数成功删除

在第 3 行,您在 上创建了一个 B 类的新对象。因此,在堆上为两个 int 指针(不是 int)分配空间,然后这些 int 又通过使用 在堆上的其他地方分配 new 关键字。当您delete objB2 时,析构函数被调用,因此两个“其他地方的整数”被释放,然后您在 objB2 的原始对象也被释放从堆中释放。

根据 WhozCraig 的评论,类 A 绝对是您在示例中显示的两个类定义中的首选。


编辑(评论回复):

WhozCraig 的链接基本上强烈反对使用原始指针。事实上,是的,我同意,第 2 行纯粹基于内存管理是首选,因为 B 在技术上管理自己的内存(尽管它仍然使用原始指针)。

但是,我通常不喜欢(过度)在类内部使用 new,因为 new 比等效堆栈(或 >non-new) 分配。因此,我更喜欢 new 整个类,而不是单个组件,因为它只需要一个 new 调用,而且所有的 ivar 都分配在堆中。 (更好的是,placement new,但这远远超出了这个问题的范围)。

总结起来:

第 2 行(类 B)在内存管理的基础上是首选,但比那更好的是:

A objAOnStack(x, y); // Avoids heap altogether

第 1 行是最好的,前提是你将它包装在一个智能指针中,例如 std::shared_ptrstd::unique_ptr 或类似的东西。

如果没有智能指针包装器,实际上不应该考虑第 3 行(无论如何,回避嵌套的 new 通常会提高性能)。

关于C++:删除对象还是删除成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15331568/

相关文章:

java - 异常 java.lang.OutOfMemoryError : Java heap space occurs in recursion

c++ - fstream 输入负数失败

c++ - 如何解析带有原始转义序列的字符串?

c++删除两个指针引用的对象

c++ - 比较数组相似性的最佳比较算法是什么?

ios - 如何使 UIViewControllerSubclass 成为 UITableViewController 的子类

ruby - 在 Ruby 中,使用 "def initialize ( value = ' ') 初始化类实例有什么好处?

php - 设置 wp_title 以更改插件的标题标签?

android - BitMapFactory.decodeStream 尝试在小图像上分配超过 20 MB

memory-management - C/Pascal 的堆管理器,可自动用零字节填充已释放的内存