全局矢量重置
Global Vector Getting Reset
更新:
正如neuront所建议的,我尝试输出矢量的地址,整个程序都是一样的。这意味着没有重复;矢量以某种方式得到";重置";在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:
我不知道为什么它不起作用,但我找到了一个有同样问题和解决方案的人。请参阅下面的答案。我将删除整个项目的内容(将问题缩小到原来的大小(,因为从链接中亚历克斯的问题来看,更大的项目似乎与问题无关。
如果我的错误微不足道,我会提前道歉。我是一个C++初学者,对范围和多文件项目的概念掌握相对较差,因此,尽管我花了很多时间玩代码并在互联网上搜索答案,但我可能错过了一些显而易见的东西。
为了使我的问题更容易回答,下面的代码被简化了。
我使用的是代码块、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类继承自CircularEntity,它只是有一个重新定义的构造函数(。main.ccp调用init,然后有一个循环:处理密钥,更新,然后渲染。文件";以上";MoveableCircular;包括树";(我不知道正确的术语(不应该与这个问题有任何关系,他们所做的唯一与这个问题真正相关的事情是"#包括";
输出为:
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 之前的整个代码
名称空间的东西(尽管我对名称空间的了解和理解是公认的薄弱,所以这仍然可能是问题的根源(。
我仍然不知道为什么我所做的是错误的,但这里有一个指向相同问题的链接,并为任何有类似问题的人提供了修复方法:
全局矢量在调用之间清空自身?
请参阅ZeRemz的解决方案。
在我的情况下,我使用/添加了以下代码:
在CircularEntity.h:中
std::vector<CircularEntity *> &getMasterEntityVector();
CircularEntity.ccp:
std::vector<CircularEntity *> &getMasterEntityVector()
{
static std::vector<CircularEntity *> s_vector;
return s_vector;
}
我仍然不知道为什么我的原始实现(或者为什么Alex在链接中的原始实现(是错误的,我从不喜欢不知道为什么,但至少我们有一个解决方案!
忘记任何命名空间之外的extern
变量,在CircularEntity
类(或其他类,如Entities
(中使用static
变量。
//CircularEntity.h:
class CircularEntity {
public:
static vector<CircularEntity*> entities;
}
//CircularEntity.cpp
vector<CircularEntity*> CircularEntities::entities;
...
CircularEntities::entities.push_back(whatever);
这样所有的东西都会被更加封装。
我已经读了几乎所有的代码,但仍然有一些问题:
- 在您的代码中,
MasterEntityVector
仅在CircularEntity
的构造函数中被引用。它在其他地方被引用过吗,尤其是它的pop_back
、erase
或任何被调用的非常量方法 CircularEntity
及其子类的对象是在哪里构造的- 你没有让
CircularEntity::~CircularEntity
过载,是吗
对于后两个问题,我在中发现了一个错误(?(
void setup() {
CircularEntity Planet2(0, 0, 100);
CircularEntity Planet3(0, 0, 100);
}
您在本地构造了2个CircularEntity
,因此它们将在initGL()
中调用setup()
之后被销毁。如果正确写入~CircularEntity
,则必须从MasterEntityVector
中删除this
,从而减小矢量的大小。(但我没有看到~CircularEntity
的声明(
此外,如果您怀疑是否还有全局向量的另一个实例,我认为您可以尝试输出全局向量的地址。
- 为什么在全局范围内使用"extern int a"似乎不行?
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 当vector是tje全局变量时,c++中vector的内存管理
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 如何创建一个空的全局类并在启动时实例化它
- 内联函数中具有内部链接的全局变量
- 为什么虚函数不能是静态的和全局的?
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 全局作用域中函数指针的赋值
- g++用户定义的动态链接库上的全局new和delete运算符
- 在命名空间中使用全局命名空间中的函数
- 全局变量 多读取器 一个写入器多线程安全?
- 类的全局对象和静态成员
- 如何声明一个可以在整个程序中使用的全局 2d 3d 4d .. 数组(堆版本)变量?
- 如果全局变量默认是外部变量,为什么要添加"extern"关键字?
- 不同作用域中的静态变量和全局变量
- 如何使用 llvm-10 库在C++定义 LLVM 全局值变量?
- 使用全局声明的向量时,C++双重释放错误/损坏
- 将线程中的数据存储到全局容器的最佳方法?
- 如何重写全局方法名称以在调用原始方法之前将我的代码推到前面