4

If I return a vector from a function, the object to which it is assigned will have the same address (without returning it as a reference) as the one declared in the function. For example:

vector<int> f() {
    vector<int> foo(5);
    cout << &foo << endl;

    return foo;
}

int main() {

    vector<int> bar = f();
    cout << &bar << endl; // == &foo

    return 0;
}

Then I assumed that this is happening because of the copy constructor and the & operator may be overloaded in a way such that it prints the address of a specific member of the vector class which was copied from foo to bar. But, if I change the scenario and move f() inside a class, the behaviour would be as I initially expected: &foo != &bar:

class A {
    vector<int> foo;
public:
    vector<int> f() {
        foo.push_back(10);
        cout << &foo << endl;

        return foo;
    }
};

int main() {
    A a;
    vector<int> bar = a.f();
    cout << &bar << endl; // != &foo

    return 0;
}

Can you explain what happens?

Robert
  • 43
  • 4
  • 1
    You're seeing one method of [copy-elision](https://en.cppreference.com/w/cpp/language/copy_elision), and the link I just gave you will explain it. – WhozCraig Nov 02 '19 at 14:58
  • 1
    More specifically, NRVO. – HolyBlackCat Nov 02 '19 at 14:59
  • 1
    Case 1 is an optimization that a compiler is free to perform: The returned object is created in the space already reserved for the eventual caller object. This saves up to two copy constructions which may be expensive, in case of a vector involve a dynamic allocation. In case 2 that is not possible: The caller's object and the class member must be distinct. – Peter - Reinstate Monica Nov 02 '19 at 14:59
  • @Peter-ReinstateMonica Without NRVO the vector would be moved, not copied. – HolyBlackCat Nov 02 '19 at 15:00
  • @HolyBlackCat True. So no allocation. – Peter - Reinstate Monica Nov 02 '19 at 15:05
  • One thing you can do is use your own class as return value and make the default-, copy and move constructors and the destructor print something. – Peter - Reinstate Monica Nov 02 '19 at 15:07
  • 1
    Possible duplicate of [What are copy elision and return value optimization?](https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization) – JaMiT Nov 02 '19 at 16:03

1 Answers1

2

What does the address of a vector represent?

Computer memory can be thought of an array of bytes. Memory address is an index to that figurative array. This is the same for all objects, including vectors.

If I return a vector from a function, the object to which it is assigned will have the same address (without returning it as a reference) as the one declared in the function.

This is not guaranteed by the standard. But it is indeed possible. It will happen whenever Named Return Value Optimisation is used to elide the copy/move of the return value.

Then I assumed that this is happening because of the ... & operator may be overloaded in a way such that ...

The addressof operator of vector is not overloaded.

Can you explain what happens?

You return a copy of a member rather than a local automatic variable. NRVO cannot be used in this case.

Disregarding subobjects, more than one object cannot overlap the same memory at any given time. If two objects exist simultaneously, then they each must have a distinct address. On the other hand, once the memory of one object is released, it can be reused by another object.

In the first example, the lifetime of the local variable ends, so there is no problem for its memory to overlap with the memory of the variable that is initialised from the return value.

In the second example, the lifetime of a and thus also its member overlaps with the lifetime of bar, and therefore they cannot overlap in memory.

eerorika
  • 232,697
  • 12
  • 197
  • 326