我知道有类似的问题,但没有一个能给我一个明确的答案......
这两方面的最佳做法都可以吗?或者我应该返回一个指针? 如果不是,他们应该如何改变以遵循最佳实践。
我想从函数返回对新对象的引用。我的实现如下:
MyClass& doSomething() {
return *(new MyClass());
}
MyClass a = doSomething();
这是否可以,因为正在使用new?
在堆上分配新的MyClass实例或者我应该让它保持不变(我不确定何时这样做)?
const MyClass& doSomething() {
return *(new MyClass());
}
如果这两个都错了,我应该只返回指向新对象的指针吗?
感谢。
答案 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
那个。你很可能不会这样做,而且看起来很尴尬。如果你想传递指针,传递指针。如果您不想传递指针,请在一个类中包装所有权并按值传递该类。
**“易于复制”我的意思是很容易将它们安全地复制,而你实际上是这样做的。例如,原始指针或文件句柄只是几个字节,默认的复制构造函数很乐意为你复制它们......但是你最终会对同一个堆对象或文件进行多次引用,并且无法跟踪谁负责删除或关闭它。