简体   繁体   中英

Shared Pointer to an object in a vector

I'm trying to figure out, what happens if you create a shared pointer, that points to an object that is held in a vector.

The Code looks like this:

class TestObject
{
public:
    int someTestData;
};

class Test
{
public:
    std::shared_ptr<TestObject> testPointer;

    std::shared_ptr<std::vector<TestObject>> getTestVector()
    {
        return testVector;
    }

private:
    std::shared_ptr<std::vector<TestObject>> testVector;
};

The Problem is, that I want to both support fast iteration over all TestObjects, but also provide shared pointers to single objects in the vector. But now I dont know what happens if the last shared ptr to an object in the vector gets deleted.

  • Does the object get removed from the vector?
  • Does this cause undefined behaviour?
  • How can I archieve the behaviour I want if this doesnt work?

EDIT:

To Clarify, what i need:

I need a MemoryManager Class, that has a method CreateTestObject, that creates a new TestObject, stores it in a vector or some other container that supports fast iteration and returns a some kind of shared_ptr to the newly created object so that the object that needs a new TestObject has a reference.

Now i also need the shared_ptr to the TestObject to be able to remove the TestObject from the container it is stored in, when the last shared_ptr goes out of scope, so that i'm not left with a vector full of unused TestObjects.

It's hard to know what happens on your end, since you didn't share the code which actually initializes testPointer . But what you're looking for is an aliased std::shared_ptr :

testPointer = {testVector, &(*testVector)[0]};

From then on, testPointer points to the first element of the vector, but shares the ownership of the vector itself with testVector , providing the correct semantics.

Do note that this doesn't prevent the vector from relocating its storage and making testPointer dangle if you cause it to reallocate.

For the record, trying to construct a std::shared_ptr owning the element itself, as follows:

testPointer.reset(&(*testVector)[0]); // Wrong!

... will necessarily trigger UB down the line, since std::vector has unique ownership of its elements already, and there's no way that you can make std::vector or std::shared_ptr relinquish ownership.

"I'm trying to figure out, what happens if you create a shared pointer, that points to an object that is held in a vector."

That is a very bad idea because the position of any element of a vector can change simply by adding or removing an element to the vector. What you implement is simply a duplication of ownership which brakes basic OOP concepts.

Does the object get removed from the vector?

A shared pointer is the "owner" of the object and the vector is also the owner. So it is conceptional broken!

Does this cause undefined behaviour?

It is still undefined, as you generate dangling pointes because vector can move its objects.

How can I achieve the behaviour I want if this doesnt work?

You have already fast access via operator[] and you have already "pointers" as iterators can be used as any other pointer.

You can do this using a custom deleter with your shared_ptr and using a container like boost::stable_vector :

testVector.emplace_back();
auto it = V.end()-1;
auto deleter = [&testVector, it] (int*) {testVector.erase(it);};
std::shared_ptr<TestObject> ptr(&testVector.back(), deleter);

When the last shared_ptr to an object goes out of scope, it will remove it from TestVector . Note however, that this does not work the other way round: If the object is removed from TestVector through any other means (eg by TestVector going out of scope), this will trigger undefined behavior, so it is your responsibility to make sure that this does not happen. Note also that this does not work with std::vector , as the iterators get invalidated when the vector is resized. You could however use std::list , although that will probably be slower than stable_vector .

This is not the cleanest solution (due to the very real possibility of triggering UB if you're not careful), but doing this proberly would be much more involved.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM