使用指针对象的std::向量.当一个项目超出范围时,有没有办法从向量中删除它



我正在从旧学派C++向">现代"进行心理过渡。

我有一个类工厂,用于确保某个类foo的所有实例都维护在列表中。此列表用于按顺序处理所有foo

这是在一个使用常规旧指针(new/delete(的遗留系统中,但我想把它们变成shared_ptrs。

我还需要在foo的析构函数中调用"RemoveMeFromList()"吗?还是有一些我不知道的魔法?

在这种情况下,我建议您在工厂中保留一个弱指针向量(std::weak_ptr(:

std::vector<std::weak_ptr<foo>> foo_instances;

现在,有了这个向量,如果一个指针超出范围,它就会过期。因此,您可以在下次处理向量时删除过期的指针。换句话说,您不需要显式的"RemoveMeFromList"方法,但您可以在处理foo实例时删除过期指针。

我是否仍然需要在foo的析构函数中调用"RemoveMeFromList">

是。

还是有一些我不知道的魔法?

否。

您可以实现一个自定义容器,该容器存储指向共享所有权对象的弱指针,并在每次访问时检查指针是否仍然有效。我不知道这对你来说是否是一个好的设计(似乎很可疑(。

这是在一个使用常规旧指针(新指针/删除指针(的遗留系统中,但我想把它们变成shared_ptrs。

您并没有真正为我们提供很多内容,但我怀疑std::shared_ptr不是您所需要的。std::shared_ptr用于通过指针的所有副本"协作管理"所有权,并在没有副本时终止它。这样的杀戮不会通知你的"工厂"或中央存储库foos。但由于你实际上拥有它,并且你希望它跟踪实例,所以让成为拥有它们的人。最多,您可以让实体获得指向foo实例的指针/引用,而不是以某种方式处理引用计数的包装器。如果有必要,您的中央foo存储库将处理删除操作。它可以回收未使用的foos——重新初始化它们并分发它们,而不是真正分配任何新的东西。

再次,对于这个相当模糊和抽象的答案,我感到抱歉。

您可以按照eerorika的建议,通过这样做来实现带有shared_ptr和weak_ptr的解决方案。如果您不希望Factory是确定内容无效时的对象的所有者,则您可能更喜欢此解决方案而不是unique_ptr。

你的工厂类可能看起来像这样:

class Factory {
public:
std::shared_ptr<MyObject> create();
std::vector<std::weak_ptr<MyObject>>& getObjects();
private:
std::vector<std::weak_ptr<MyObject>> objects;
void cullInvalidObjects();
};

我们只需在工厂方法中从对象的shared_ptr创建一个weak_ptr:

std::shared_ptr<MyObject> Factory::create()
{
auto object = std::make_shared<MyObject>();
std::weak_ptr<MyObject> weakObject = object;
objects.push_back(weakObject);
return object;
};

工厂可以有一种内部方法来剔除不再有效的对象:

void Factory::cullInvalidObjects()
{
auto iter = objects.begin();
while (iter != objects.end())
{
if ((*iter).expired())
{
objects.erase(iter++);
}
}
}

然后,当让对象对其进行处理时,您可能需要在提供列表之前对其进行筛选:

std::vector<std::weak_ptr<MyObject>>& Factory::getObjects()
{
cullInvalidObjects()
return objects;
}

或者,你可以直接获取列表,然后检查处理它的函数的有效性,而不是进行筛选。如果你有大量无效项,这可能不是最好的解决方案。

void callSomeMethod(std::vector<std::weak_ptr<MyObject>>& objects)
{
for (auto wObj : objects)
{
auto sObj = wObj.lock();
if(p)
{
p->someMethod();
}
}
}

相关内容

最新更新