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?
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.