虽然这并不完全无效,但这不是一个好主意。
MyClass& doSomething() {
return *(new MyClass());
}
返回后,没有人拥有原始指针,所以没有人会delete
得到它。*所以这是内存泄漏。
new
除非你有一个相应的delete
——或者,更好的是,一个智能指针构造函数,否则你几乎不应该写 a 。
同时,原始代码中的这一行:
MyClass a = doSomething();
…无论如何都会复制该值。假设这不是另一个必须修复的错误,为什么还要麻烦堆分配对象并返回对复制和泄漏的引用?只需按值返回对象:
MyClass doSomething() {
return MyClass();
}
现在您不必担心删除任何内容,因为您从未在堆上创建任何内容。
最佳实践通常可以总结为四个字母 RAII:Resource Acquisition Is Initialization。(并且推论,破坏就是释放。)如果你有一些不可能或昂贵的东西,可以通过价值传递,然后通过价值传递一些句柄。例如:
unique_ptr<MyClass> doSomething() {
return unique_ptr<MyClass>(new myClass());
}
unique_ptr<MyClass> a = doSomething();
现在它只是一个被复制的指针。对象本身在 内部创建,并在超出范围doSomething
时删除(或者,如果您将其传递给另一个变量,则只要超出范围等)。a
另一方面,如果MyClass
只是少数易于复制的值**,只需复制它。
*删除它并非不可能;您始终可以获取指向引用的指针delete
。你不太可能这样做,而且看起来很尴尬。如果要传递指针,请传递指针。如果您不想传递指针,请将所有权包装在一个类中并按值传递该类。
** “易于复制”我的意思是很容易安全地复制它们,而且你确实这样做了。例如,原始指针或文件句柄只有几个字节,默认的复制构造函数会很乐意为您复制它们……但是最终您会得到对同一个堆对象或文件的多个引用,并且无法跟踪谁负责删除或关闭它。