类中的指针

Pointer in a class

本文关键字:指针      更新时间:2023-10-16

我有以下代码片段

class test{
    private:
        int *ptr;
    public:
        test(int *myptr){
            ptr = myptr;
        }
        ~test(){
            delete ptr;
        }
};
int main(){
    int* myptr = new int;
    *myptr = 10;
    test obj(myptr);
    delete myptr;
}

这个程序中是否发生了内存泄漏,如果我不在类中做一个新的 to 指针,是否会为该指针分配空间?

处理分配成员的经验法则:每个new/new[]都应该与一个delete/delete[]配对。如果您缺少delete,则存在内存泄漏(您分配了从未清理的内存)。如果delete多次 -ing(如在代码示例中所做的那样),则会遇到内存损坏问题。

你是如何多次delete的?在 main() 中,您分配一个指针:

int* myptr = new int;

您将该指针的副本提供给test对象,obj 。然后,在范围的末尾,我们有:

{
    // ...
    delete myptr;
    ~test(); // implicit, which also does delete myptr
}

这两个地方中只有一个应该负责delete指针。哪一个基于代码的语义。test拥有指针吗?在这种情况下,它应该delete它,但main()不应该。它只是观察指针吗?在这种情况下,它不应该delete它。在 C++11 中,我们有了新的智能指针来更好地表达这个想法。

我鼓励你浏览最终的C++书单,因为这样的概念对于理解C++非常重要,但也很难用简短的问答形式正确解释。

你应该

只在~test()delete中直接删除一次指针

*** Error in `./a.out': double free or corruption (fasttop): 0x08d13a10 ***

考虑使用 std::shared_ptr<int>std::unique_ptr<int> ,因为在现代C++中不鼓励直接内存管理,除非您有理由这样做。您可以在此处阅读有关智能指针的语义差异的信息,它们的参考资料在这里。

退出主函数时会崩溃,堆内存中分配的内存不能释放两次

在您的

实例中将发生的情况是指针将在main()中提供给delete,然后相同的指针值将再次提供给obj析构函数中的delete。这是未定义的行为,因此它可能有效,也可能无效,在任何情况下,它都不能保证有效,因此不应使用此类结构。

通常你会建立所有权规则,例如,构造函数是否"获得所有权"(因此负责释放资源)取决于你,但通常情况下,特别是在现代C++中,所有权语义可以通过使用 std::unique_ptrstd::shared_ptr 来明确实现。

最重要的是,无论您使用哪种方法来确定所有权,请确保您保持一致!避免复杂的所有权语义,因为这会使检测与内存相关的问题(或更一般地说,与资源相关的问题)变得更加困难。

其他人所说的相反:您不会删除C++中的指针,而是删除对象

有什么区别?

让我们稍微简化一下您的代码:

int *myptr = new int; // 1
int *ptr = myptr; // 2
delete myptr; // 3
delete ptr; // 4

newdelete的使用而言,这是相同的代码 - 我刚刚删除了该类,因为它与此处的重点无关。

此代码执行以下操作:

  1. new int分配一个int,并返回其地址。然后,该地址存储在 myptr 中。

  2. 地址将复制到ptrptrmyptr 都包含刚刚分配的int的地址。

  3. int已解除分配。

  4. int已解除分配...但它已经被解除分配了?哎呀!

    如果幸运的话,此时程序将崩溃。

delete myptr;与变量myptr无关,除了myptr保存要删除的事物的地址。

它甚至不必是一个变量 - 你可以做delete new int;(尽管它不是很有用)或delete someFunctionThatReturnsAnAddress();,或者int *p = 1 + new int[2]; delete [] (p - 1);

您的类只有分配整数的引用。考虑将其声明为 int const* ptr ,然后不能在类中删除它。应从析构函数中删除delete ptr

通常,分配某物的范围负责释放它。在您的情况下,主要例程是分配并且必须释放。

对于您的问题"此程序中是否发生内存泄漏",答案是否定的,但异常正在出现。

您的代码逻辑不好,您应该删除创建指针的位置。在此示例中,不应删除析构函数中的 ptr。