Why RVO doesn't happen here?
c++, return-value-optimization
Solution
As already said, there are two things that prevent RVO. The function doesn't return `v`, but instead a tuple that is constructed form `v` and `a`. Also in main function `v` is assigned and not constructed from the return value.
To get what you want you could use the tuples directly without additional vector objects:
#include <iostream>
#include <vector>
#include <tuple>
std::tuple<std::vector<int>, double> func() {
std::tuple<std::vector<int>, double> t;
get<0>(t).reserve(100);
for (int k=0;k!=100;k+=1)
get<0>(t).push_back(k);
get<1>(t) = 5.0;
std::cout << "Address of v in func\t" << &get<0>(t) << std::endl;
std::cout << "Address of v.data in func\t" << get<0>(t).data() << std::endl;
return t;
}
int main()
{
std::tuple<std::vector<int>, double> t = func();
std::cout << "Address of v in main\t" << &get<0>(t) << std::endl;
std::cout << "Address of v.data in func\t" << get<0>(t).data() << std::endl;
std::cout << get<0>(t)[9] << std::endl;
return 0;
}
Output:
Address of v in func 0x28fe80
Address of v.data in func 0x962c08
Address of v in main 0x28fe80
Address of v.data in func 0x962c08
9
Alternative optimization is to use move semantics when constructing the tuple:
return make_tuple(std::move(v), a);
In this case at least copying the vector's internal buffer is avoided:
Address of v in func 0x28fdd4
Address of v.data in func 0xa72c08
Address of v in main 0x28fe64
Address of v.data in func 0xa72c08
9
Problem
I have read Dave Abrahams article on RVO and a few other Q/As on SO (14043609, 9293726 and 10818278) but I still have a question. When I compile and run the following code, I get this output: ``` Address of v in func 0x7fffac6df620 Address of v.data in func 0x2081010 Address of v in main 0x7fffac6df690 Address of v.data in func 0x20811b0 9 ``` To me it seems that a copy is made. How do I pass large objects out of functions? Please note that I want to return one or more objects without writing an explicit structure for it. I used GCC 4.6.3 with -O2. Edit: The first two answers showed me that I expected too much from the compiler. I added a main2 that behaves in the same way, e.g. the printed addresses are different. I would like to emphasize that the motivation is efficient return of large objects. ``` #include <iostream> #include <vector> #include <tuple> std::tuple<std::vector<int>, double> func() { std::vector<int> v; v.reserve(100); for (int k=0;k!=100;k+=1) v.push_back(k); double a = 5.0; std::cout << "Address of v in func\t" << &v << std::endl; std::cout << "Address of v.data in func\t" << v.data() << std::endl; return make_tuple(v, a); } int main() { std::vector<int> v; double a; std::tie(v, a) = func(); std::cout << "Address of v in main\t" << &v << std::endl; std::cout << "Address of v.data in func\t" << v.data() << std::endl; std::cout << v[9] << std::endl; return 0; } int main2() { auto tp = func(); std::vector<int> & v = std::get<0>(tp); double & a = std::get<1>(tp); std::cout << "Address of v in main\t" << &v << std::endl; std::cout << "Address of v.data in func\t" << v.data() << std::endl; std::cout << v[9] << std::endl; return 0; } ```