C++ return value optimization

对着背影说爱祢 提交于 2019-11-29 13:28:11
Daniel Frey

When you call a function, for a return type like std::vector<T> the compiler provides memory for the returned object. The called function is responsible for constructing the instance it returns in this memory slot.

The RVO/NRVO now allows the compiler to omit creating a local temporary object, copy-constructing the returned value in the memory slot from it, destructing the temporary object and finally returning to the caller. Instead, the called function simply constructs the local object in the return slot's memory directly and at the end of the function, it just returns.

From the caller's perspective, this is transparent: It provides memory for the returned value and when the function called returned, there is a valid instance. The caller may now use this object and is responsible for calling the destructor and freeing the memory later on.

This means that the RVO/NRVO only work for when you call a function to construct a new instance, not when you assign it. The following is an example of where RVO/NRVO could be applied:

std::vector<float> v = getstdvec();

but you original code uses a loop and in each iteration, the result from getstdvec() needs to be constructed and this temporary is assigned to v. There is no way that the RVO/NRVO could remove this.

You can pass it by reference...copy elision makes it so that v = getstdvect() allocates v (in your main) directly to the v (in your getstdvec()) and skips the copy usually associated with returning by value, but it will NOT skip the v(4) in your function. In order to do that, you need to take the vector in by reference:

#include <vector>
void getstdvec(std::vector<float>& v){
  v.resize(4);//will only realocate if v is wrong size
  v[0] = 1; v[1] = 2; v[2] = 3; v[3] = 4;
  return v;
}
int main() {
  std::vector<float> v(4);
  for (int i=0; i!=1000;++i)
    getstdvec(v);
}

You're doing copy-assignment in your loop, not copy-construction. The RVO optimization only applies to constructing variables from a return value, not assigning to them.

I can't quite make out the real problem you're trying to solve here. With more details it might be possible to provide a good answer that addresses your underlying problem.

As it stands, to return from your function in such a way you'll need to create a temporary vector to return each time the function is called.

The simplest answer is to pass the already created vector object into the function.

std::vector<float> getstdvec(std::vector<float> &myvec){

In that case you don't really have to return it so

void getstdvec(std::vector<float> &myvec){

in stead use the return value, you can use a reference:

void getstdvec(std::vector<float> &v)

Which can avoid the copy of temporary object

How can I return a vector (or any other object) from a function like this without having to allocate it every time?

In your way, you declare a local vector with size 4, so each time the function is called, it is going to allocate the memory. If you means that you always modify on the same vector, then you may consider pass the vector by reference instead.

For example:

void getstdvec(std::vector<float>& vec)
{                                //^^
    //do something with vec
}

inside main, you declare the vector and allocate space as what you did. You now do the following:

for (int i=0; i!=1000;++i)
{        //^^^minor: Don't use magic number in the code like this, 
         //define a const instead
    getstdvec(vec);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!