简体   繁体   中英

when we return a c++ container like vector,list. What happens?

vector<int> function(...)
{
      .......
      .......
      vector<int> C = some value;
      return C
}
int main()
{
      X = function(...)
}

what would the value of x be, will it be the address of C like when we return an array or would the returned value be the complete vector C copied into X. in what cases should you dynamically allocate a container? Would there be any differnce in the final X if pass the vector by reference or by value?

Normally whenever you return something from a function it is copied. And when this something has a copy constructor then it will be fired. For example arrays: they are just pointers (with trivial copy constructor) to some block of memory. So what actually is copied is only the pointer itself. But vectors are quite complicated classes. And they have copy constructors which actually copy entire content. This does not scale well.

But here's the thing: you almost never allocate vectors dynamically. In many cases (for example in your pseudo-code) the content is not copied due to (Named) Return Value Optimization or other copy elision optimization . It is literally the same vector.

If in some case copy elision does not fire (or you are not sure) it is still better to pass the vector by ref to the function rather then dynamically allocate it on the heap. Allocating memory in a function and then returning it to the caller is an anti-pattern (even though sometimes necessary). This causes the big problem: who is responsible for freeing the memory? You need to know the source code of the function (or at least the docs) to know that.

Another option (when copy elision does not apply) is to use std::move to avoid copies.

On the other hand passing vector by value will create a copy of that vector. Most certainly you want to pass it by ref or const ref.

Also I encourage you to check all those things yourself. Try printing raw pointers &C and &X to see if it is the same object.

By a pure semantic standpoint, despite of its type name, C is a plain local variable (that most likely contains three pointers: to the begin, end and capacity of the dynamic buffer containing the data).

That variable is moved in a temporary object given to the return statement that is in turn moved into the X variable to replace its content.

RVO optimization can skip the first move, by making the C variable itself to live inside the stack frame of the outer function (main - in your case).

Since you did not declare any type for X, I must assume it is already existent std::vector<int> , so the = is actually an assignment.

Since std::vector implement move semantics:

  1. The actual inner pointers in X and C are swapped (so that X holds C content and C holds the old X content
  2. C is destroyed
    1. C destructor will destroy the retained "old X content"

Standard library containers are themselves dynamic content managers. Allocate them, dynamically and pass them around as pointers is the biggest nonsense a C++ programmer can do. At least from 2011 onward.

If "function" does not access X in any way, further optimization can even remove the assignment at all, by making C an alias of X, so that The content of X is replaced by the one of C at the time of its construction. the return and the = are simply removed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM