Soroush Rabiei
Soroush Rabiei

Reputation: 10868

Is returning reference to an element in a growing vector bad practice?

I'm experiencing a strange memory bug (segfault). After some code review I found that I'm passing a pointer to self (this) to a member value inside a class, which itself is inside a vector and it's about to change its address. Then (possibly) vector grows and the pointer that just passed become invalid.

My understanding is std::vector is supposed to move its content in memory, since its guaranteed to be continues, right? I thought that I can overcome this by passing a const reference instead of pointer (passing *this). But I'm having same segfault. I can't see why references can become invalid just as pointers do! The situation can be summarized like this:

class Foo
{
public:
    Foo(): x(new Bar(*this)){}
    Foo(Foo&&);
    Foo& operator=(Foo&&)
private:
    // some heavy to move data
    Bar* x;
};

class Bar
{
public:
    Bar(const Foo& foo): instance(foo){}
private:
    const Foo& instance;
};

std::vector<Zoo> vec;
// Do some stuff on vec, then x->instance become invalid. Why?

Upvotes: 0

Views: 219

Answers (1)

Mat
Mat

Reputation: 206831

When a vector needs to reallocate its storage, the objects that lived at the "old" location are deleted after they've been copied (or moved into) the new storage. The move doesn't "teleport" an object to a new location, it's still creating a new object in the new location.

The reference you're holding references the "old" object that has been deleted by the vector reallocation operation. Using that reference will lead to undefined behavior. Same as the pointer case. You can't store an iterator either, those are invalidated too.

You'll need to find another way to keep track of that element. Exactly how you do that depends on what you're trying to do. Sometimes just keeping an index is enough.

Upvotes: 2

Related Questions