返回函数中的大对象 [英] Returning Large Objects in Functions

查看:113
本文介绍了返回函数中的大对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比较以下两段代码,第一段使用对大对象的引用,第二段使用大对象作为返回值。对大对象的强调指的是对象的重复副本,不必要地是浪费的周期。

Compare the following two pieces of code, the first using a reference to a large object, and the second has the large object as the return value. The emphasis on a "large object" refers to the fact that repeated copies of the object, unnecessarily, is wasted cycles.

使用对大对象的引用: p>

Using a reference to a large object:

void getObjData( LargeObj& a )
{
  a.reset() ;
  a.fillWithData() ;
}

int main()
{
  LargeObj a ;
  getObjData( a ) ;
}

使用大对象作为返回值:

Using the large object as a return value:

LargeObj getObjData()
{
  LargeObj a ;
  a.fillWithData() ;
  return a ;
}

int main()
{
  LargeObj a = getObjData() ;
}

第一个代码段不需要复制大对象。

The first snippet of code does not require copying the large object.

在第二个片段中,对象在函数内部创建,因此通常在返回对象时需要一个副本。然而,在这种情况下,在 main()中正在声明该对象。编译器首先创建一个默认构造的对象,然后复制由 getObjData()返回的对象,还是会像第一个代码片段一样有效?

In the second snippet, the object is created inside the function, and so in general, a copy is needed when returning the object. In this case, however, in main() the object is being declared. Will the compiler first create a default-constructed object, then copy the object returned by getObjData(), or will it be as efficient as the first snippet?

我认为第二个片段更容易阅读,但恐怕效率较低。

I think the second snippet is easier to read but I am afraid it is less efficient.

strong>通常,我想到的情况 LargeObj 是通用的容器类,为了参数,在其中包含数千个对象。例如,

Typically, I am thinking of cases LargeObj to be generic container classes that, for the sake of argument, contains thousands of objects inside of them. For example,

typedef std::vector<HugeObj> LargeObj ;

所以直接修改/添加方法到 LargeObj

so directly modifying/adding methods to LargeObj isn't a directly accessible solution.

推荐答案

第二种方法更加惯用和表达。很明显,当读取代码的函数没有前提条件的参数(它没有参数),并且它实际上会在里面创建一个对象。第一种方法对于临时读者来说不是那么清楚。调用意味着对象将被改变(通过引用传递),但是如果在传递的对象上有任何前提条件,则不那么清楚。

The second approach is more idiomatic, and expressive. It is clear when reading the code that the function has no preconditions on the argument (it does not have an argument) and that it will actually create an object inside. The first approach is not so clear for the casual reader. The call implies that the object will be changed (pass by reference) but it is not so clear if there are any preconditions on the passed object.

关于副本。您发布的代码不使用赋值运算符,而是复制构造。 C ++定义了在所有主要编译器中实现的返回值优化。如果您不确定是否可以在编译器中运行以下代码段:

About the copies. The code you posted is not using the assignment operator, but rather copy construction. The C++ defines the return value optimization that is implemented in all major compilers. If you are not sure you can run the following snippet in your compiler:

#include <iostream>
class X
{
public:
    X() { std::cout << "X::X()" << std::endl; }
    X( X const & ) { std::cout << "X::X( X const & )" << std::endl; }
    X& operator=( X const & ) { std::cout << "X::operator=(X const &)" << std::endl; }
};
X f() {
    X tmp;
    return tmp;
}
int main() {
    X x = f();
}

使用g ++,您将得到一行 X :: X )。编译器在堆栈中为 x 对象保留空间,然后调用在 x 上构造 tmp

With g++ you will get a single line X::X(). The compiler reserves the space in the stack for the x object, then calls the function that constructs the tmp over x (in fact tmp is x. The operations inside f() are applied directly on x, being equivalent to your first code snippet (pass by reference).

如果你没有使用复制构造函数(如果你写的是:x x; x = f ; )然后它会创建 x tmp 并应用赋值运算符,产生三行输出: X :: X / em> / X :: X() / X :: operator = ,所以在情况下效率会低一些。

If you were not using the copy constructor (had you written: X x; x = f();) then it would create both x and tmp and apply the assignment operator, yielding a three line output: X::X() / X::X() / X::operator=. So it could be a little less efficient in cases.

这篇关于返回函数中的大对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆