通过函数释放内存 - 这样做正确吗?

3

我刚开始有点困惑,当我通过函数尝试删除一个新分配的变量时,为什么打印出来的是相同的内存地址,我猜测没有泄漏内存或指针悬挂。

打印出来的是相同的内存地址。

#include <iostream>

using namespace std;

void deallocater(int *p)
{
    delete p;
    p = nullptr; // memory deleted and no dangling pointer right?
}

int main()
{
    int *x = new int(1);
    cout<<x;
    deallocater(x);

    cout<<endl<<x; // why is the same memory address being printed?

    return 0;
}

我假设这个函数已经成功运行

2个回答

7

调用函数

void deallocater(int* p)
{
    delete p;
    p = nullptr;
}

通过

deallocater(x);

x的值复制到p。因此,在deallocater()中,局部变量p被赋予nullptr。然而,调用程序的变量x不会被改变。

您可以通过使用引用参数来达到所需的目的:

void deallocater(int* &p)
{
    delete p;
    p = nullptr;
}

然而,为了避免悬挂指针和/或内存泄漏的风险,内存分配和释放不应该拆分成不同且无关的函数。相反,良好的C++代码几乎不包含 delete 语句和少量 new 语句(用于初始化智能指针),而是使用标准库结构(容器和智能指针)进行内存管理。


2
尽管你的答案与 Kingsley 的解决方案达到了相同的结果,但我更喜欢这个答案,因为它不需要改变函数体。 - jbinvnt
然而,调用程序的变量x并没有被改变。非常感谢您的有见地的反馈。 - visitor

2

当在deallocater()中释放内存后,代码无法更改指针p的内容,因此打印时仍然显示相同的值。 调用之后,p仍具有相同(指针)值,但它指向的内存已被释放。 这被称为“悬空引用”。

要更新指针,请使用双指针或指向指针的引用:

void deallocater(int **p)
{
    delete *p;
    *p = nullptr; // memory deleted and no dangling pointer right?
}

int main()
{
    int *x = new int(1);
    cout<<x;
    deallocater( &x );

    cout<<endl<<x; // why is the same memory address being printed?

    return 0;
}

1
对于非可选参数,请使用引用作为参数。 - Swordfish
非常有启发性,从未想到指针仍然悬空!至少内存已经被释放了哈哈,非常感谢。 - visitor
@Swordfish - 我不同意,你能引用比Google的C++编码标准(https://google.github.io/styleguide/cppguide.html)更好的参考资料吗?还是这只是个人风格选择? - Kingsley
该编程语言具有内置的按引用传递机制--直接使用它明显比通过指针模拟更可取。 - M.M
@Kingsley 你是在指输出参数吗? 它们并没有解释*为什么*。而且这个“风格指南”只是众多风格指南之一。 - Swordfish

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