简体   繁体   English

指向向量中 object 的共享指针

[英]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.我试图弄清楚,如果您创建一个共享指针,该指针指向一个保存在向量中的 object,会发生什么。

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.问题是,我既想支持对所有 TestObjects 的快速迭代,又想提供指向向量中单个对象的共享指针。 But now I dont know what happens if the last shared ptr to an object in the vector gets deleted.但是现在我不知道如果向量中 object 的最后一个共享 ptr 被删除会发生什么。

  • Does the object get removed from the vector? object 是否从向量中删除?
  • 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.我需要一个 MemoryManager Class,它有一个 CreateTestObject 方法,它创建一个新的 TestObject,将它存储在一个向量或其他支持快速迭代的容器中,并将某种 shared_ptr 返回到新创建的 object 以便 ZA8CFDE6331BD59EB2AC96F968新的 TestObject 有一个参考。

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.现在,当最后一个 shared_ptr 超出 scope 时,我还需要 TestObject 的 shared_ptr 以便能够从它存储的容器中删除 TestObject,这样我就不会留下一个充满未使用 TestObjects 的向量。

It's hard to know what happens on your end, since you didn't share the code which actually initializes testPointer .很难知道最终会发生什么,因为您没有共享实际初始化testPointer的代码。 But what you're looking for is an aliased std::shared_ptr :但是您正在寻找的是别名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.从那时起, testPointer指向向量的第一个元素,但与testVector共享向量本身的所有权,从而提供正确的语义。

Do note that this doesn't prevent the vector from relocating its storage and making testPointer dangle if you cause it to reallocate.请注意,如果您导致向量重新分配,这不会阻止向量重新定位其存储并使testPointer悬空。

For the record, trying to construct a std::shared_ptr owning the element itself, as follows:作为记录,尝试构造一个拥有元素本身的std::shared_ptr ,如下所示:

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. ...必然会触发 UB,因为std::vector已经对其元素拥有唯一的所有权,并且您无法让std::vectorstd::shared_ptr放弃所有权。

"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." “我试图弄清楚,如果你创建一个共享指针,它指向一个保存在向量中的 object,会发生什么。”

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.这是一个非常糟糕的主意,因为向量的任何元素的 position 都可以通过向向量中添加或删除元素来改变。 What you implement is simply a duplication of ownership which brakes basic OOP concepts.您实施的只是所有权的重复,这会破坏基本的 OOP 概念。

Does the object get removed from the vector? object 是否从向量中删除?

A shared pointer is the "owner" of the object and the vector is also the owner.共享指针是 object 的“所有者”,向量也是所有者。 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.它仍然是未定义的,因为你会生成悬空点,因为 vector 可以移动它的对象。

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.您已经可以通过operator[]快速访问,并且您已经有了“指针”,因为迭代器可以用作任何其他指针。

You can do this using a custom deleter with your shared_ptr and using a container like boost::stable_vector :您可以使用带有shared_ptr的自定义删除器并使用诸如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 .当 object 的最后一个shared_ptr超出 scope 时,它将从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.但是请注意,这反过来不起作用:如果TestVector通过任何其他方式(例如通过TestVector超出范围)从 TestVector 中删除,这将触发未定义的行为,因此您有责任确保这不会发生。 Note also that this does not work with std::vector , as the iterators get invalidated when the vector is resized.另请注意,这不适用于std::vector ,因为在调整向量大小时迭代器会失效。 You could however use std::list , although that will probably be slower than stable_vector .但是,您可以使用std::list ,尽管这可能会比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.这不是最干净的解决方案(因为如果你不小心,很可能会触发 UB),但是这样做会更复杂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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