内存运行时错误:我们在哪里删除此指针

时间:2013-03-30 00:44:02

标签: c++ pointers memory-leaks

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

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;
}

1 个答案:

答案 0 :(得分:5)

  

但在这种情况下再也没有了。

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

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

你需要注意的是:

  • 你确实在某个时刻为delete分配的每个对象调用new(否则你有内存泄漏);
  • 您不会为同一个对象多次调用delete,否则会出现未定义的行为;
  • 你没有取消引用一个指向已被破坏的对象的指针(即“悬空指针”),否则你会得到未定义的行为。

通常,在Modern C ++中不鼓励通过newdelete进行手动内存管理,而应通过智能指针来实现所有权策略。 或...

  

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

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

然而,函数mediocre()实际上非常好,这有两个原因:

  1. 首先,因为编译器很可能会忽略对复制构造函数的调用并执行(Named) Return Value optimization,因此不会产生运行时开销;
  2. 其次,因为感谢C ++ 11的移动语义,所以有可能 为Foo配备一个移动构造函数,使其按值返回 在大多数情况下即使没有进行任何省略也是有效的。
  3. 此外,正如Zoidberg在评论中正确提到的那样,如果你真的不需要它们,就不应该使用指针。独特的所有权通常可以通过创建具有自动存储持续时间的对象(也就是“在堆栈上”)来实现,并且移动语义使这种实践变得高效。应仅创建指针when you need reference semantics