这一条和前面的条款19、RVO、NRVO是连在一起的。
核心思想:既然编译器能通过RVO/NRVO消除返回值复制,那么你写代码时应该尽量让编译器有机会进行这种优化。
为什么会有这一条
先看一个类:
c++
class Widget
{
};
函数:
c++
Widget create()
{
Widget w;
...
return w;
}
现代编译器通常会做NRVO,变成只直接在调用者内存构造。结果就是0次复制、0次移动,次那个能最好。
但是有些人会无意中写出:
C++
Widget create()
{
Widget w;
...
return Widget(w);
}
看起来一样,实际上编译器看到的是return Widget(w);即构造一个临时对象,这会让NRVO更难发生。
第一个原则 返回局部对象本身
推荐
c++
Widget create()
{
Widget w;
return w;
}
不要:
c++
Widget create()
{
Widget w;
return Widget(w);
}
因为前者更容易NRVO,后者可能产生额外对象。
第二个原则 不要返回局部对象的引用
很多人为了避免复制:
c++
Widget& create()
{
Widget w;
return w;
}
这属于返回局部变量引用,函数结束后局部变量就会销毁,最终导致得到悬空引用,从而导致未定义行为。
第三个原则 不要返回指针
例如:
c++
Widget* create()
{
Widget* p = new Widget;
return p;
}
虽然避免复制,但是引入内存管理问题,调用者必须delete p;否则会发生内存泄漏。
第四个原则 一个对象只构造一次
看这个例子:
c++
Widget create()
{
Widget w;
...
return w;
}
理想情况构造1次,但是如果这样写:
c++
Widget create()
{
Widget w;
...
return SomeCondition()
? Widget(w)
: Widget();
}
出现多个返回对象,那么编译器做NRVO的难度提高。