C ++返回对新对象的引用

时间:2013-10-16 02:47:51

标签: c++ pointers reference

我知道有类似的问题,但没有一个能给我一个明确的答案......

这两方面的最佳做法都可以吗?或者我应该返回一个指针? 如果不是,他们应该如何改变以遵循最佳实践。

我想从函数返回对新对象的引用。我的实现如下:

MyClass& doSomething() {
   return *(new MyClass());
}

MyClass a = doSomething();

这是否可以,因为正在使用new?

在堆上分配新的MyClass实例

或者我应该让它保持不变(我不确定何时这样做)?

const MyClass& doSomething() {
    return *(new MyClass());
}

如果这两个都错了,我应该只返回指向新对象的指针吗?

感谢。

1 个答案:

答案 0 :(得分:8)

虽然这并非完全无效,但这不是一个好主意。

MyClass& doSomething() {
   return *(new MyClass());
}

返回后,没有人拥有原始指针,所以没有人会delete它。*所以这是内存泄漏。

除非你有一个相应的new - 或者更好的智能指针构造函数,否则你几乎不应该编写delete


同时,原始代码中的这一行:

MyClass a = doSomething();

...无论如何都要制作一个价值的副本。假设这不是另一个必须修复的bug,为什么还要分配一个对象并返回一个复制和泄漏的引用呢?只需按值返回对象:

MyClass doSomething() {
   return MyClass();
}

现在您不必担心删除任何内容,因为您从未在堆上创建任何内容。


最佳做法通常可以用四个字母RAII来概括:资源获取是初始化。 (并且必然,破坏就是释放。)如果你有一些不可能或昂贵的东西要按值传递,那么按价值传递一些句柄。例如:

unique_ptr<MyClass> doSomething() {
    return unique_ptr<MyClass>(new myClass());
}

unique_ptr<MyClass> a = doSomething();

现在它只是一个被复制的指针。对象本身在doSomething内创建,并在a超出范围时被删除(或者,如果将 超出范围,则将其传递给另一个变量,等)。

另一方面,如果MyClass只是少量易于复制的值**,请复制它。


*删除它不是不可能;你总是可以指向参考和delete那个。你很可能不会这样做,而且看起来很尴尬。如果你想传递指针,传递指针。如果您不想传递指针,请在一个类中包装所有权并按值传递该类。

**“易于复制”我的意思是很容易将它们安全地复制,而你实际上是这样做的。例如,原始指针或文件句柄只是几个字节,默认的复制构造函数很乐意为你复制它们......但是你最终会对同一个堆对象或文件进行多次引用,并且无法跟踪谁负责删除或关闭它。