全局矢量重置

时间:2013-05-26 22:55:32

标签: c++ global

更新

正如神经建议的那样,我尝试输出向量的地址,整个程序都是一样的。这意味着没有重复;在定义Planet和Player之后但在程序进入setup()和render()之前,向量以某种方式“重置”。可能导致这种情况的原因是什么?

更新2:

使用cout,我确定错误发生在main()之前。因此构造了全局的Player和Planet对象,并将指向它们的指针添加到MasterEntityVector中。然后,在main()启动之前(或者在main()启动时,但在执行它的任何部分之前),MasterEntityVector得到“重置”,之后一切都按预期运行。当MasterEntityVector是CircularEntity类的静态成员并且MasterEntityVector是OpenGLLoopLogic.ccp中的全局成员时,会发生此行为。什么可能导致这种行为?我想也许它与“静态初始化命令惨败”http://www.parashift.com/c++-faq-lite/static-init-order.html有关,但问题似乎略有不同(例如,我没有崩溃)。

更新3:

我不知道为什么它不起作用,但我找到了一个有同样问题和解决方案的人。请参阅下面的答案。我将删除整个项目的包含(将问题修改回原始大小),因为在链接中查看Alex的问题,较大的项目似乎与问题无关。


如果我的错误很简单,我会提前道歉。我是一名C ++初学者,对范围和多个文件项目的概念相对较差,因此虽然我花了很多时间玩代码并在网上搜索答案,但我可能错过了一些明显的东西。

以下代码已经过简化,目的是让我的问题更容易回答。

我正在使用Codeblocks,C ++,OpenGL(用于图形)和SDL(用于窗口)。

添加cout行进行故障排除,我将在下面输入。

问题是一个名为MasterEntityVector的全局向量,它应该包含指向模拟中所有“实体”的指针。它在CircularEntity.ccp中声明,在CircularEntity.h中有一个extern。应该在实体的构造函数中添加指针。在OpenGLLoopLogic.ccp中,指针在创建实体时添加到MasterEntityVector,但是当我们开始进入init / setup / render函数时,它似乎要么重置,要么得到它的第二个实例。如何阻止这种不良行为?

CircularEntity.h:

#ifndef CIRCULARENTITY_H
#define CIRCULARENTITY_H

#include "LUtil.h"

class CircularEntity {
    public:
        CircularEntity(double x, double y, int r);
        double xpos, ypos;
        int radius;
        void Draw(double camxpos, double camypos);

};

extern std::vector<CircularEntity *> MasterEntityVector;  //contains pointers to ALL entities

#endif // CIRCULARENTITY_H

CircularEntity.ccp:

#include "CircularEntity.h"

std::vector<CircularEntity *> MasterEntityVector;  //contains pointers to ALL entities

CircularEntity::CircularEntity(double x, double y, int r) {
    radius = r;
    xpos = x;
    ypos = y;
    std::cout << "test 1" << std::endl;
    std::cout << MasterEntityVector.size() << std::endl;
    MasterEntityVector.push_back(this);
    std::cout << "test 2" << std::endl;
    std::cout << MasterEntityVector.size() << std::endl;
}

...
//irrelevant code removed
...

OpenGLLoopLogic.h:

#ifndef OPENGLLOOPLOGIC_H
#define OPENGLLOOPLOGIC_H

#include "MoveableCircular.h"

//Screen constants
const int SCREEN_WIDTH = 1800;
const int SCREEN_HEIGHT = 1000;

bool initGL();

void setup();

void update();

void render();

void handleKeys( unsigned char key, int x, int y );

#endif // OPENGLLOOPLOGIC_H

OpenGLLoopLogic.ccp:

#include "OpenGLLoopLogic.h"

//The projection scale
GLfloat gProjectionScale = 1.f;
MoveableCircular Player(200, 200, 0, 0, .05, 10);
CircularEntity Planet(0, 0, 100);

bool initGL()
{
    ...
    //irrelevant code removed
    ...
    setup();

    return true;
}

void setup() {
    CircularEntity Planet2(0, 0, 100);
    CircularEntity Planet3(0, 0, 100);
}

void velocityupdate()
{
    Player.Gravity(0,0,100);
}

void positionupdate()
{
    Player.PositionUpdate();
}

void update()
{
        velocityupdate();
        positionupdate();
}

void render()
{
    ...
    //irrelevant code removed
    ...
    for (int n=0; n<MasterEntityVector.size(); n += 1) {
        (*MasterEntityVector[n]).Draw(Player.xpos, Player.ypos);
        std::cout << MasterEntityVector.size() << std::endl;
    }

    ...
    //irrelevant code removed
    ...
}

void handleKeys( unsigned char key, int x, int y )
{
    ...
    //irrelevant code removed
    ...
}

我省略了几个文件,所以你们都没有读过很多不相关的代码:

MoveableCircular源和标头与CircularEntity文件非常相似。 (cout的测试3和4而不是1和2,而MoveableCircular类继承自CirularEntity,它只有一个重新定义的构造函数)。 main.ccp调用init,然后有一个循环:handle keys,update,然后render。 “包含树”中的MoveableCirular.h上面的文件(我不知道正确的术语)不应该与问题有任何关系,他们唯一能做的就是与这个问题真正相关的是“#包括“

输出结果为:

test 1
0
test 2
1
test 3
1
test 4
2
test 1
2
test 2
3
test 1
0
test 2
1
test 1
1
test 2
2
2
2
2
.
.
.
[infinite 2's]

从输出中可以看出,随着Player和Planet对象的构建,一切都很顺利。 但是,当我们进入OpenGLLoopLogic函数(设置中的Planet2和Planet3,绘制代码渲染等等)时,它似乎“重置”或创建MasterEntityVector的第二个副本。造成这种不良行为的原因是什么?

我已经尝试过的事情:

在MasterEntityVector

之前的代码中添加“::”

命名空间的东西(尽管我对名称空间的了解和理解确实很弱,所以这仍然可能是问题的根源。)

3 个答案:

答案 0 :(得分:2)

我仍然不知道为什么我做错了,但是这里有一个相同问题的链接,并且对于遇到类似问题的人来说是一个修复:

Global vector emptying itself between calls?

请参阅ZeRemz的解决方案。

在我的情况下,我使用/添加了以下代码:

在CircularEntity.h中

std::vector<CircularEntity *> &getMasterEntityVector();
在CircularEntity.ccp中

std::vector<CircularEntity *> &getMasterEntityVector()
{
    static std::vector<CircularEntity *> s_vector;
    return s_vector;
}

我仍然不知道为什么我的原始实现(或为什么Alex在链接中的原始实现)是错误的,我从不喜欢不知道为什么,但是至少我们有一个解决方案!

答案 1 :(得分:0)

忘记任何命名空间中的extern变量,并在static类(或其他类,如CircularEntity)中使用Entities变量。

//CircularEntity.h:
class CircularEntity {
  public:
    static vector<CircularEntity*> entities;
}

//CircularEntity.cpp
vector<CircularEntity*> CircularEntities::entities;

...
CircularEntities::entities.push_back(whatever);

这样一切都将被更加封装。

答案 2 :(得分:0)

我几乎阅读了这些代码,但仍然有一些问题:

  • 在您的代码中MasterEntityVector仅在CircularEntity的构造函数中引用。是否已引用其他任何地方,尤其是其pop_backerase或任何非const方法?
  • CircularEntity及其子类的对象,它们是在哪里构建的?
  • 您没有超载CircularEntity::~CircularEntity,是吗?

对于后两个问题,我在

中发现了一个错误(?)
void setup() {
    CircularEntity Planet2(0, 0, 100);
    CircularEntity Planet3(0, 0, 100);
}

你在本地构建了2个CircularEntity,因此在setup()调用initGL()后它们会被破坏。 如果您正确撰写~CircularEntity,则必须从this删除MasterEntityVector,从而减​​少向量的大小。 (但我没有看到~CircularEntity

的声明

此外,如果您怀疑是否存在其他实例,我认为您可以尝试输出全局向量的地址。