【问题标题】:Memory run time error: where do we delete this pointer内存运行时错误:我们在哪里删除这个指针
【发布时间】:2013-03-30 00:44:02
【问题描述】:

在下面的四种方法中,只有更好的是我们应该做的。我们希望在这里动态分配以避免错误的函数返回。但是,我们在哪里删除 f? 在调用 better() 的函数处删除?但在这种情况下,没有 f 了。

Foo *bad() {
  Foo f;
  return &f;
}

Foo &alsoBad() {
  Foo f;
  return f;
}

Foo mediocre() {
  Foo f;
  return f;
}

Foo * better() {
  Foo *f = new Foo;
  return f;
}

【问题讨论】:

  • 将其放入智能指针并返回以使“更好”的指针更好地工作。
  • mediocre 其实是最好的,只是说。见Modern C++ Style。另请参阅C++11 Style,其中 Bjarne Stroustrup 讨论了移动语义。
  • 您基本上是在问“我如何进行内存管理”,这是一个非常广泛且主观的话题。
  • @Zoidberg 是对的。甚至甲壳类动物也知道手动资源管理很疯狂。
  • @Blastfurnace 成就了我的一天。

标签: c++ pointers memory-leaks


【解决方案1】:

但在这种情况下,没有 f 了。

好吧,f 指针超出了范围,这是真的,但我们仍然返回指向 f 指向的同一对象的指针。

因此,我们仍然拥有该对象的句柄,并且我们仍然可以在返回的指针上调用 delete。实际上,您可以在使用new 创建对象后随时调用delete

你需要注意的是:

  • 您确实在某个时间点为使用new 分配的每个对象调用了delete(否则您会出现内存泄漏);
  • 不要为同一个对象多次调用delete,否则会出现未定义的行为;
  • 不要取消引用指向已销毁对象的指针(即“悬空指针”),否则会出现未定义的行为。

一般而言,现代 C++ 不鼓励通过 newdelete 进行手动内存管理,而应通过 智能指针 实现所有权策略。 或者...

下面的四种方法中,只有更好的是我们应该做的

不完全是。事实上,我会说我们绝对不应该这样做 better() - 尽管我们可以做一个修改后的 better() 版本以创建和返回智能指针而不是拥有原始指针。

不过,mediocre() 函数其实还不错,原因有二:

  1. 首先因为编译器很可能会忽略对复制构造函数的调用而执行(Named) Return Value optimization,从而导致没有运行时开销;
  2. 其次,由于 C++11 的移动语义,可以 为Foo 配备一个 move 构造函数,它可以按值返回 即使不执行省略,在大多数情况下也很有效。

此外,正如Zoidberg 在 cmets 中正确提到的那样,如果您真的不需要指针,则根本不应该使用它们。唯一所有权通常可以通过创建具有自动存储持续时间的对象(也称为“在堆栈上”)来实现,并且移动语义使这种做法有效。只能创建指针when you need reference semantics

【讨论】:

  • 我想在最后一句话中补充一点,在许多情况下,所有权可以在没有任何指针(或引用,就此而言)的情况下表达。
  • @Zoidberg:当然。会提到这一点。谢谢
  • 你确实在某个时候调用了delete 来调用new 分配的所有对象 我承认这有时并不像你想象的那么容易,尤其是如果您有不同的内存分配器。所以better 函数会有一个补充,betterCallMeWhenYouAreDone,它释放分配的对象,你必须调用它而不是delete
  • @ta.speot.is:是的,但我宁愿完全忘记 better(),因为在现代 C++ 中实际上是 quite_bad()。手动内存管理已被智能指针(也支持自定义删除器)取代,这些使我们免于遇到与您引用的我的答案部分相关的大部分麻烦。
猜你喜欢
  • 2020-06-09
  • 2016-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多