Why does an object returned by value have the same address as the object inside the method?
C++C++11C++ Problem Overview
#include <stdio.h>
#include <array>
#include <vector>
std::vector<int> foo() {
int i;
std::vector<int> a(100);
printf("%p, %p, %p\n", &i, &a, &(a[0]));
return a;
}
int main() {
int i;
std::vector<int> b = foo();
printf("%p, %p, %p\n", &i, &b, &(b[0]));
}
Why do a
and b
have the same address for the above? Is this some kind of "cross-stack-frame" optimization? The result is the same even when I use the -O0
option.
The output:
$ vim main.cpp
$ cc -std=c++11 -lc++ main.cpp
$ ./a.out
0x7ffee28d28ac, 0x7ffee28d28f0, 0x7ff401402c00
0x7ffee28d290c, 0x7ffee28d28f0, 0x7ff401402c00
$
C++ Solutions
Solution 1 - C++
This is because of copy elision/named return value optimization (NRVO). foo
returns a named object a
. So the compiler is not creating a local object and returning a copy of it but creates the object at the place where the caller puts it. You can read more about it on https://en.cppreference.com/w/cpp/language/copy_elision. While RVO is mandatory since C++17, NRVO is not, but it looks like your compiler supports it even in case of -O0
.
Solution 2 - C++
Note that even without copy elision (mandatory or not), it's already possible for the addresses of the two objects to be the same because their lifetimes are non-overlapping.
Solution 3 - C++
as the others have explained this is because of copy elison. You can disable that with g++ by:
g++ -fno-elide-constructors main.cpp
where main.cpp
contains your code.
now a
and b
have different addresses but a[0]
and b[0]
will have the same
address because of the move semantics.