Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does an object returned by value have the same address as the object inside the method?

Tags:

c++

c++11

#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
$ 
like image 437
willzeng Avatar asked May 14 '20 08:05

willzeng


People also ask

What is a returned object?

return obj; creates a new object copy or simply returns the current object itself.

Why Java is strictly pass by value?

Java always passes parameter variables by value. Object variables in Java always point to the real object in the memory heap. A mutable object's value can be changed when it is passed to a method. An immutable object's value cannot be changed, even if it is passed a new value.

When two objects communicate with each other some parameters might be passed?

When two or more objects communicate with each other that means that those objects are sending and receiving messages. This is often called method calling.

How to create object and assign value in JavaScript?

assign() which is used to copy the values and properties from one or more source objects to a target object. It invokes getters and setters since it uses both [[Get]] on the source and [[Set]] on the target. It returns the target object which has properties and values copied from the target object. Object.


3 Answers

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.

like image 167
Werner Henze Avatar answered Oct 23 '22 20:10

Werner Henze


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.

like image 32
R.. GitHub STOP HELPING ICE Avatar answered Oct 23 '22 20:10

R.. GitHub STOP HELPING ICE


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.

like image 8
Hikmat Farhat Avatar answered Oct 23 '22 20:10

Hikmat Farhat