0

Why the result of returning lvalue from function is that that object std::vector<int> v in main() function has same memory address as returned object std::vector<int> vec in a get_vec() function, even though these objects exist in a different stack frame ?

Why there is not called move constructor ?

#include <iostream>
#include <vector>


std::vector<int> get_vec()
{
    std::vector<int> vec = { 1, 2, 3, 4, 5 }; 
    std::cout << "get_vec():\n" << &vec << '\n' << vec.data() << "\n\n";   
    return vec;
}

int main()
{
    std::vector<int> v = get_vec();
    std::cout << "main():\n" << &v << '\n' << v.data() << "\n\n";   
  
    return 0;
}
OUTPUT:
get_vec():
0x7a07ee93baa0
0x226b290

main():
0x7a07ee93baa0
0x226b290
filipcimo
  • 31
  • 1
  • 5
  • 2
    See nrvo explained in [dupe1](https://stackoverflow.com/a/72386932/12002570) and implicit move rule explained in [dupe2](https://stackoverflow.com/a/71934476/12002570) – Jason Jun 26 '22 at 11:04

2 Answers2

5

vec is either moved (automatically, because you're returning a local variable), or, if the compiler is smart enough, is the same object as v (this is called NRVO).

In both cases .data() is going to stay the same. When moved, the new vector takes ownership of the other vector's heap memory.

&vec,&v are going to be the same only if the compiler performs NRVO.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
1

You are initializing v with the result of get_vec and the return value undergoes copy elision.

Internally the C++ calling convention has a register for returning structs by passing in a pointer to storage. So the call gets transformed into:

void get_vec(std::vector<int> &out);

The function gets a reference to the v in main so the address is the same in both cases.

Goswin von Brederlow
  • 11,875
  • 2
  • 24
  • 42