当前位置:  开发笔记 > 编程语言 > 正文

返回const引用是否更有效

如何解决《返回const引用是否更有效》经验,为你挑选了2个好方法。

例如

这些中最好的是:

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引用返回.



1> Nicola Bonel..:

函数永远不应该返回对本地对象/变量的引用,因为这些对象超出了作用域并在函数返回时被销毁.

不同的是,该函数可以将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引用返回.



2> Chris Jester..:

我想补充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的.:-)

推荐阅读
有风吹过best
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有