Search code examples
c++c++11stlsetrvo

Should I send std::set to function with refrence or not?


From another question I see this code :

template <typename T>
std::set<T> getUnion(const std::set<T>& a, const std::set<T>& b)
{
  std::set<T> result = a;
  result.insert(b.begin(), b.end());
  return result;
}

Can't we just use below code ? :

template <typename T>
std::set<T> getUnion(std::set<T> a, const std::set<T>& b)
{
  a.insert(b.begin(), b.end());
  return a;
}

Is there any difference ??

I can't understand the reason for using the first approach.

Is the second code inhibit RVO ?


Solution

  • The first version takes a std::set by reference which means you will not get a copy of the argument that is passed. The copy is actually happening in the initialization of result with a. The second takes its argument by value, which means that depending on the value-category of the argument the compiler will call the copy/move constructor. Particularly, if the argument is an lvalue, it is copied, and if an rvalue, moved.

    In the first example, the compiler will most likely will discard the copy operation from the return statement, an optimization known as return value optimization (RVO). The second version cannot do this as you are not returning a local variable. So you can see that the second version of the function has to incur at least one extra copy or move operation, while the first deals only with one.