Transferring a vector<shared_ptr<T>> by reference without bypassing shared semantics

Viewed 79

I have a class which contains a vector<shared_ptr<T>>:

using SharedItems = std::vector<std::shared_ptr<Item>>;

class LargeLift
{
public:
    SharedItems& getItems()
    {
        return _items;
    }

    void setSharedItems(SharedItems& items)
    {
        _items = items;
    }

private:
    SharedItems _items;
};

I then do the following:

LargeLift b;
{
    LargeLift a;
    // Gets populated

    SharedItems& items = a.getItems();
    b.setSharedItems(items);
}

// Variable a is now out of scope

SharedItems& items2 = b.getItems();

Is the last line valid, given a has gone out of scope?

3 Answers

The code passes a reference into setSharedItems, but SharedItems _items; is NOT a reference, so _items = items; copies items into _items. a._items is different from b._items, so b will be just fine after a fades away. Since b made copies of all of the shared_ptrs the reference counts have not hit zero and all of the pointers will still be good.

As written, your code is safe - nothing has gone out of scope.

In this example, a does go out of scope, but things are still safe:

LargeLift b;
{
    LargeLift a;
    // Gets populated

    SharedItems& items = a.getItems();

    //give b its own copy
    b.setSharedItems(items);
}

// safe, because b owns its own copy
SharedItems& items2 = b.getItems();

In this example, they are not safe:

SharedItems* p_items;

LargeLift b;
{
    LargeLift a;
    // Gets populated

    items = &a.getItems();
}

// unsafe, items is already dangling
b.setSharedItems(*p_items);

SharedItems& items2 = b.getItems();

Yes it is valid. You class holds the vector by value so in your setter

_item = item

Will copy the whole vector

Related