1

我对 C++ 并不陌生,但我通常主要使用 C# 和其他托管语言工作,所以我不太精通共享指针等。

我基本上有一个 shared_ptrs 到自定义类对象的 3 维映射(用于 3d 目的)。

这些 shared_ptrs 存在于地图中,并在整个项目中被引用,到目前为止一切都很好。对于一个特定的功能,我将其中一些 shared_ptrs 存储在一个向量中,以便稍后在代码中进行迭代,但这似乎是事情发生故障的地方。

假设我有 100 个这些对象,它们的指针存储在 3d 地图中,其中 3 个被添加到向量中,因为它们具有特殊的功能属性。当我遍历向量时,我在这 3 个对象上调用函数。这一切正常,直到 for 循环(用于迭代)在向量的元素 [1] 上第二次运行,此时元素 [0] 充满了损坏的数据(但元素 [1] 需要访问元素 [0 ] 来执行其中一项功能),这就是我得到错误的地方。

正如我所说,我对 shared_ptrs 不是很精通,但我认为数据不会被破坏,因为实际对象是在创建 3 维地图时创建的——而且,向量还没有消失范围,因为我只在 for 循环的第二次运行(有 3 个对象和 3 次迭代)。

我知道我一定是做错了什么,但我不知道如何进一步调试 - 基本上当我单步执行代码并进入 for 循环的第二次运行时,如果我查看元素 [0] 中的 shared_ptr向量(使用VS)它都被破坏了。

这是代码的循环,因此您可以看到。向量是在此代码所在类的构造函数中创建的,而地图(创建 shared_ptrs 和对象的位置)在应用程序的主类中。此外,getAdjacent 将 objA 和 objB 作为指针,因此用 objA 的相邻对象的数据“填充”objB:

for(vector<shared_ptr<ObjectClass>>::iterator iterator = objects.begin(); iterator != objects.end(); iterator++)
{
    shared_ptr<ObjectClass> objA = (shared_ptr<ObjectClass>) iterator->get();

    shared_ptr<ObjectClass> objB;

    m_3DMap->getAdjacent(objA, objB);

    objA->move(objB);
}

会不会和我的演员阵容有关iterator->get()?我看不到任何其他方法可以做到这一点,因为如果我没有那个演员,VS 说它不能从 ObjectClass* 转换为 shared_ptr,这对我来说也很困惑,因为我认为我有一个 shared_ptrs 的向量? ..

感谢您的宝贵时间,如果有人可以提供帮助,那就太好了。

4

2 回答 2

0

对于初学者,您应该很少在 shared_ptr 上调用 get() 。并且使用该指针来初始化另一个 shared_ptr 你永远不能这样做。

您构造智能指针的原始指针被传递给所有权。所有权必须是排他性的。您使用它的方式,两个 shared_ptrs 将拥有同一个对象,从而导致过早删除,然后在某些时候进行双重删除,两者都将您置于 UB 领域。

这比您的原始版本要好一些,但是如果没有看到代码,getAdjacent 也会以某种方式被破坏。

for(auto i = objects.begin(); i != objects.end(); ++i)
{
   const auto&  objA = *i;
   shared_ptr<ObjectClass> objB;
   m_3DMap->getAdjacent(objA, objB);
   objA->move(objB);
}

getAdjacent 的签名应该类似于

void getAdjacent(shared_ptr<ObjectClass> const& objA, shared_ptr<ObjectClass>& objB);

有战斗的机会。

于 2013-06-28T16:06:02.677 回答
0

好的,我发现了我遇到的问题。

部分原因是 Balog Pal 所说的将 shared_ptrs 放在一个向量中,即使它们位于一个映射中,所以我改变了这一点,以便向量保存指向 shared_ptrs 的指针。虽然这可能仍然是不好的做法,但它解决了这个问题 - 特别是因为向量是本地的并且在函数退出后失去了范围。

最初的向量方法是在函数中某处对我的地图迭代器取消引用时实现的,因此我决定将所有地图操作留在迭代之外(因此将“特殊”对象存储在向量中以供稍后迭代)。

我现在更改了实现以消除这种低效率,因为我的操作函数现在返回一个新的映射迭代器,从而解决了这个问题。

如果错误消息更有帮助,那就太好了,因为我花了一些时间才意识到迭代器变得无效,因为我有一个 insert() 埋在“特殊”对象上调用的函数之一中.

虽然这个答案并没有真正回答我提出的确切问题,但它回答了整个问题以及为什么我以我在问题中的方式设计函数。

感谢 Balog 的帮助和 itwasntpete 的回答和评论。

于 2013-07-01T16:20:57.130 回答