实例化奇怪

时间:2011-12-01 09:58:22

标签: c++

我遇到一个问题,即指针向量似乎没有按照我预期的多态方式运行。陌生人的事实是它适用于它所指向的每一个其他对象。

shotgunNodesrifleNodes都包含两个整数,它们代表一个级别中的适当位置,用于放置我正在生成的拾取器。

pickups是kpointers(父类)的向量,ShotgunPURiflePU是派生类。我将在下面发布标题和来源。

奇怪的问题是,如果我打破代码,一次一个循环,一切似乎都很顺利。第一个枪指针设置为指向步枪物体。精细。然后将下一个枪指针设置为指向下一个步枪对象,此时出于某种奇怪的原因,向量中的前一个指针应该指向第一个步枪被切断,现在只指向步枪的枪部分对象,所以我失去了它的所有派生功能。

在循环结束时,我有一个指向枪步枪霰弹枪的枪矢,它应该是步枪步枪霰弹枪。

int j = 0;

for (vec_i_sz i = 0; i < rifleNodes.size(); i++, j++)
{
    riflePickups.push_back(RiflePU(agents, mesh));
    riflePickups[i].Position(nodes[rifleNodes[i]].Position());

    pickups.push_back(&riflePickups[i]);//point the pickup pointer to the rifle pickup
    pickups[j]->Index(j);
    pickups[j]->NodeIndex(rifleNodes[i]);
}

for (vec_i_sz i = 0; i < shotgunNodes.size(); i++, j++)
{
    shotgunPickups.push_back(ShotgunPU(agents, mesh));
    shotgunPickups[i].Position(nodes[shotgunNodes[i]].Position());

    pickups.push_back(&shotgunPickups[i]);
    pickups[j]->Index(j);
    pickups[j]->NodeIndex(shotgunNodes[i]);
}

可能还值得注意的是,此代码(显然是翻译版本,但在相同的结构中)适用于程序的C#版本。所以我怀疑这是代码的结构。有什么我不知道指针的工作方式吗?

这是在使用它们的标题中声明向量的方式:

std::vector<Pickup*> pickups;
std::vector<RiflePU> riflePickups;
std::vector<ShotgunPU> shotgunPickups;

我刚刚注意到写了这个,它们在循环运行之前(在构造函数的主体中)实际上并没有在初始化列表中初始化,但是这不应该是正确的,因为它们是类类型吗?

如果它们在列表中初始化,它仍然会发生。

pickups(std::vector<Pickup*>()),
riflePickups(std::vector<RiflePU>()),
shotgunPickups(std::vector<ShotgunPU>())

2 个答案:

答案 0 :(得分:1)

当向向量添加项时,push_back可以在需要调整其底层缓冲区大小时使所有指向容器的指针无效。每次发生这种情况时,您已经存储在pick_ups中的指针都会变成垃圾。

1)您可以预先reserveriflePickups中的所有项目shotgunPickups内存。这将确保在添加许多项目时不会调整这些向量的大小,并且项目的地址将保持不变。

2)您可以在{/ 1}} 之后将指针存储在之后,您已在两个向量中创建了所有项目,而不是在这些向量尚未达到其最终大小时。

3)您可以使用pick_ups覆盖std::listriflePickups的向量。在列表中,只有在删除了所述项目时,指向项目的指针才会失效。


最终,你真的需要这个吗?也许你可以只在一个向量中存储(最好是智能的)指向动态分配对象的指针。

答案 1 :(得分:0)

&#34;访问者&#34;已经解释了会发生什么,并且正如他提示的那样,我认为你的基本问题是当你应该使用指向对象的指针时使用对象。请记住,C#(和Java)确实使用指向所有对象的指针,即使它在语法中不明显。所以这个C#代码:

Person daisy = new Person();
daisy.salary = 39000;
dosomethingwith(daisy);

也会编译为C ++,如果你只删除关键字 new ,执行它时会发生什么更接近这个C ++代码:

Person* daisy = new Person();
daisy->salary = 39000;
dosomethingwith(daisy);

Java和C#程序员通常会错误地转移到C ++,他们使用 new 创建所有对象,但也许情况恰恰相反。