例如
这些中最好的是:
std::string f() {}
要么
const std::string& f() {}
Nicola Bonel.. 35
函数永远不应该返回对本地对象/变量的引用,因为这些对象超出了作用域并在函数返回时被销毁.
不同的是,该函数可以将const或非const引用返回给其范围不受函数上下文限制的对象.典型的例子是自定义operator<<
:
std::ostream & operator<<(std::ostream &out, const object &obj) { out << obj.data(); return out; }
不幸的是,按价值返回有其性能缺陷.正如Chris所提到的,按值返回一个对象涉及一个临时对象的副本及其随后的破坏.副本发生我的复制构造函数或operator =.为了避免这些低效率,智能编译器可以应用RVO或NRVO优化,但有些情况下他们不能 - 多次返回.
即将推出的C++ 0x标准(部分在gnu gcc-4.3中可用)引入了可用于区分左值和右值引用的右值引用[&&].通过这种方式,可以实现移动构造函数,用于返回一个对象,部分避免了复制构造函数和临时构造函数的破坏.
移动构造函数基本上是Andrei几年前在Chris建议的文章http://www.ddj.com/database/184403855中所设想的.
一个移动构造函数具有以下特征:
// move constructor object(object && obj) {}
它应该取得传递对象内部的所有权,使后者处于默认状态.通过这样做,避免了内部的副本,并使临时的破坏变得容易.典型的功能工厂将具有以下形式:
object factory() { object obj; return std::move(obj); }
std :: move()从对象返回一个右值引用.最后但并非最不重要的是,移动构造函数允许非可复制对象的rvalue引用返回.
函数永远不应该返回对本地对象/变量的引用,因为这些对象超出了作用域并在函数返回时被销毁.
不同的是,该函数可以将const或非const引用返回给其范围不受函数上下文限制的对象.典型的例子是自定义operator<<
:
std::ostream & operator<<(std::ostream &out, const object &obj) { out << obj.data(); return out; }
不幸的是,按价值返回有其性能缺陷.正如Chris所提到的,按值返回一个对象涉及一个临时对象的副本及其随后的破坏.副本发生我的复制构造函数或operator =.为了避免这些低效率,智能编译器可以应用RVO或NRVO优化,但有些情况下他们不能 - 多次返回.
即将推出的C++ 0x标准(部分在gnu gcc-4.3中可用)引入了可用于区分左值和右值引用的右值引用[&&].通过这种方式,可以实现移动构造函数,用于返回一个对象,部分避免了复制构造函数和临时构造函数的破坏.
移动构造函数基本上是Andrei几年前在Chris建议的文章http://www.ddj.com/database/184403855中所设想的.
一个移动构造函数具有以下特征:
// move constructor object(object && obj) {}
它应该取得传递对象内部的所有权,使后者处于默认状态.通过这样做,避免了内部的副本,并使临时的破坏变得容易.典型的功能工厂将具有以下形式:
object factory() { object obj; return std::move(obj); }
std :: move()从对象返回一个右值引用.最后但并非最不重要的是,移动构造函数允许非可复制对象的rvalue引用返回.
我想补充Nicola的优秀答案.是的,您必须永远不要返回悬空引用(例如,引用局部变量),但是,在这些情况下,有三种有用的方法可以提高性能:
返回值优化(RVO):按值返回,但通过只有一个return
语句来消除复制,这会在现场创建返回值.以下是使用RVO的示例:如何标记C++字符串?
命名返回值优化(NRVO):按值返回,并在函数顶部首先声明返回值变量.所有return
语句都返回该变量.对于支持NRVO的编译器,该变量在返回值槽中分配,并且在返回时不会被复制.例如,
string foobar() { string result; // fill in "result" return result; }
使用a shared_ptr
等作为返回类型; 这需要在堆上创建对象,而不是堆栈.这可以防止悬空引用问题,同时仍然不需要复制整个对象,只需要智能指针.
顺便说一句,我不能相信有关RVO和NRVO的信息; 他们直接来自Scott Meyers的更有效的C++.由于我现在没有这本书,所以我的描述中的任何错误都是我的,而不是Scott的.:-)