C++ 指针和内存泄漏

标签 c++ pointers memory-leaks

我想说明一件事:

class Something {};

void do_something(const Something *p_sth) {}

然后:

do_something(new Something());

应该会导致内存泄漏,因为当您调用 new 时,您也应该始终调用 delete,对吧?这是一个好的解决方案吗?

void do_something(const Something *p_sth)
{
    delete p_sth;
}

还是使用引用 & 更好?我还发现智能指针可以解决这个问题,所以不需要delete(这似乎是件好事,但我以前从未使用过)。我只想知道最好的解决方案是什么,以避免内存泄漏。谢谢

*谢谢大家的回答。它帮助我清理了一些东西。我也对我发布的代码感到抱歉,因为它可能太笼统了。

最佳答案

您关于假定指针所有权并删除对象的建议有问题。

这种行为在 C++ 中不是惯用的。程序员希望他们必须删除使用 new 分配的每个对象。如果您的函数的用户希望他们负责删除将其地址传递给函数的对象,那么您的解决方案就会分崩离析。此外,它会阻止将您的函数与调用结束后必须保持存在的对象一起使用:

Something* s = new s();
do_something(s);
s.foo() // oops, object was deleted, I can't use it anymore
delete s; // oops, double delete because I'm for some reason not responsible for deleting the object that I allocated

您的解决方案还可以防止在函数中使用自动和静态分配的对象。

Something s;
do_something(&s); //oops, do_something assumes that object is dynamically allocated

所有这些注意事项都必须记录给函数的用户。

在函数内部没有删除的原始指针没有这些问题。管理调用者的内存真的不应该是你的功能的责任。这样做会破坏单一责任原则。当您不想想要转让或共享所有权时,原始指针参数没有任何问题。如果您确实想暗示所有权发生变化,请使用专为此设计的智能指针。

智能指针不存在上述一些问题,但它们仍然会阻止使用自动和静态对象的功能。

在许多情况下,引用参数是理想的。它告诉调用者他们仍然对该对象负责。作为奖励,不需要 addressof 运算符允许稍微更好的语法。当然,调用者可能仍然会忘记管理他们的内存,但正如我所指出的,这不应该是你的责任。

引用有一个潜在的缺点。它们不能为空。如果您不需要 null,那么它实际上是一个优势。

哪种解决方案是理想的,取决于您的需要。以下并非适用于所有极端情况,但适用于大多数常见情况:

  • 如果要修改对象,则传递一个引用。
    • 除非你需要 null,在这种情况下使用指针
  • 如果你只是想读取对象,那么
    • 如果对象是可复制的、小的(大小小于或等于 word)、不包含指向动态对象的指针且不是多态的,则按值传递
    • 否则,或者如果您因为正在编写模板而不知道这些事情,请传递一个 const 引用
    • 除非你需要 null,在这种情况下使用指针
  • 如果你想转移所有权,那么使用unique_ptr
  • 如果您希望共享该所有权,请使用 shared_ptr

关于C++ 指针和内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32653090/

相关文章:

c++ - 是否有可能为 std::map 重载 << 运算符,其中包含对 std:string 和 std::vector<int>?

c# - 托管 .net 的 C++ 程序将对象从 C++ 公开到 C#

c - C语言中如何获取指向指针的指针?

c++ - 如何正确取消初始化 OpenSSL

c++ - 滚动大图像故障的 MSDN 示例

c++ - 带有 OpenMP 关键指令的 Rcpp 明显比编译的 C++ 代码慢

c++ - 检查未完全填充的数组中的字符是否为空

c++ - 为什么当我访问一个由三个整数组成的对象时,它会从基指针而不是堆栈指针中减去?

.net - "ContentPresenter.Content"内存泄漏

swift - 如何使用 dispatchQueue 创建引用循环?