我需要在析构函数中删除基本数据类型吗?C++

10

如果我有一个类看起来像这样:

class SomeClass {
    public:
        SomeClass(int size) {
                     arr = new int[size];
                     someInt = size / 10;
                    };
        ~SomeClass() {
                      delete [] arr;
                      //do I need to somehow delete the int value 'someInt'?
                     };
    private:
        int *arr; //pointer to dynamically allocated array
        int someInt;
}

为避免内存泄漏,析构函数需要包含什么内容?

我知道需要删除动态分配的数组,但是否需要处理 int 值或其他基本数据类型?

谢谢, Jonathan


4
不需要,而且你应该使用std::vector而不是手动分配空间。 - Jerry Coffin
@Jerry,这与我的学校作业有关,我需要使用动态分配的数组作为其中的一部分。我还需要正确地拆解类中的所有内容。 - Jonathan
1
请记住三或五的规则。在您的示例代码中没有遵循该规则。 - chris
@chris,由于我不熟悉这个规则的名称 - 我查了一下。我只是简单地把它组合在一起作为一个简短的例子。在我的实际类中,我有一个默认(null)构造函数和一个复制构造函数。我还没有学习过移动构造函数。如果你想私信给我一个解释,我很乐意阅读。=) - Jonathan
如果您使用的是C++11,那么您只需要关心移动形式,但它们是用于旧对象不应再使用时的。例如,std::vector的移动构造函数和移动赋值运算符将仅复制指针而不是元素,并将另一个对象的指针设置为nullptr。它适用于即将被销毁的临时对象,因此不必多次复制。在C++03中,您只需要关心析构函数、拷贝构造函数和拷贝赋值运算符。 - chris
显示剩余2条评论
6个回答

24

不需要。

但不仅适用于基本类型。对于任何没有使用new分配的东西,都不需要调用delete。即使是指针也是如此。

delete与成员变量类型(某种程度上)无关。重要的是是否在构造函数(或类方法的其他地方)中使用new进行了分配。

经验法则是

Have as many delete as new
Have as many delete[] as new[].

当然,有时候你需要删除一些你没有分配但正在指向的东西,如果它不再需要(被其他人分配但只有你在使用)。

当然,有时候你需要不要删除一些你已经分配的东西,因为其他人正在指向它(由你分配但其他人正在使用)。


1
仅仅因为一个类没有分配某些东西,这并不意味着当这个类被销毁时,它没有“拥有”应该被删除的东西。 - user420442
@James 是的,确实如此。但那不是他想问的。我只是试图明确它的基础知识。我会编辑它。 - stardust
1
@Jonathan 在这种情况下,你只需要删除数组。没有别的了。其他情况我认为你需要时会注意到它们的。请看我的编辑。 - stardust
1
@Jonathan 是的,没错。何时何地删除某个东西完全取决于你程序的设计。对于基本分配的内存,由你决定谁拥有什么,以及谁负责清理任何给定的资源。通常情况下,分配某个东西的类也是负责删除它的类。当然总会有例外,但这完全在你的掌控之中。 - user420442
1
谢谢,伙计们。在这篇文章和dascandy的帖子之间,现在对我来说很有意义了。=) - Jonathan
显示剩余2条评论

5
不,你不需要手动删除自动变量。只需deletenew的内容即可。
此外,您可以通过使用智能指针并采用RAII技术避免删除数组的需要。这样,您就不必手动定义析构函数了;自动生成的析构函数将完成所需的工作。
class SomeClass {
    public:
        SomeClass(int size)
          : arr {new int[size]}
          , someInt = size/10;
        {};

    private:
        std::unique_ptr<int[]> arr; //pointer to dynamically allocated array
        int someInt;
}

使用更专门的类型,例如std::vector,而不是通用智能指针会更好:

class SomeClass {
    public:
        SomeClass(int size)
          : arr (size)
          , someInt = size/10;
        {};

    private:
        std::vector<int> arr;
        int someInt;
}

我同意两种情况,并且肯定使用向量会简化我正在尝试做的事情 - 但这是关于一个班级作业,你们两个的解决方案都被禁止了。我需要明确地拆解数组,而且我不能使用向量。= P - Jonathan
@Jonathan 如果您不允许使用std设施,可以尝试创建自己的简单实现。手动管理资源而没有这样的帮助程序很难做到完全正确。您甚至可能会更有收获。 - bames53
我认为这个任务的主要目的之一是理解析构函数和适当的内存分配和管理(至少在小范围内)。我不需要在此案例之外再次使用它,但我确实需要证明我理解它。否则,相信我,我会更愿意使用向量。=) - Jonathan
没错,我的意思是通过开发辅助组件你可以掌握这些技能。除非你的程序只需要处理一项任务,否则编写一个辅助组件并多次使用它要比多次复制该组件的逻辑更容易。如果你的程序只管理一个指针,则无所谓。 - bames53
我只需要在这个程序中管理一个指针。将来,如果我需要管理更多,我就可以使用向量。 - Jonathan

4
不,你不需要。你只需要删除使用new分配的内容。

3

你永远不会删除或新建任何属于你的对象的内容。这句话立即说明了为什么你不对int做任何特定的操作,但是你对指针做了一些操作。

int本身是你的类的一部分,指针也是你的类的一部分。事实上,你的类中列出的所有事物本身都是你的类的一部分。需要注意的是,指针是你的类的一部分,但是被指向的对象并不是。指针本身将被销毁(如果相关,则调用其析构函数),但被指向的对象不会。


谢谢您澄清这一点。我现在更明白需要显式销毁指向的对象的原因了。我可以给您答案,但我认为用户的答案更贴切地回答了我的问题。不过还是给您一个赞吧。=) - Jonathan

2

编号 someInt 是按值存储的,并使用 自动存储期。一旦其所属对象被销毁,someInt 和所有其他具有自动存储期的成员变量也将被销毁。您仍然需要管理具有动态存储期(new/delete)的对象,这是您已经完成的。


1

您只需要删除您new的内容或者delete[]您new[]的内容。您可能想要了解auto_ptr


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接