使用构造函数填充向量的 C++ 奇怪行为
C++ Odd behaviour with vector populated with constructor
我遇到了一些 "odd behaviour" 使用构造函数填充向量值的问题。
所以,我有这个块 class,每当调用构造函数时,它都会填充这个名为 blockList 的静态向量。
static std::vector<Block*> blockList;
Block::Block(float x, float y)
: RectangleShape(sf::Vector2f(WIDTH, HEIGHT)) {
blockList.push_back(this);
setFillColor(sf::Color(221, 221, 221, 255));
setPosition(x, y);
}
现在,当我在另一个 class 中填充值时,我调用了 "Game" ;在它的构造函数中像这样:
Game::Game(sf::RenderWindow& window) {
// other code here
Block firstBlock(10, 10);
// possible more blocks here
}
然后尝试绘制,它崩溃了。此外,此块的坐标打印为 (x: 9.8439e-12, y: 9.84394e-12)。现在我尝试做的是将它放入 draw 方法中(我知道这很糟糕,因为它不断被调用但用于调试目的):
void Game::drawObjects() {
// draw other shapes here
Block oneBlock(50.0f, 50.0f);
std::cout << std::string(10, '-') << std::endl;
for (Block* block : Block::getBlockList()) {
std::cout << block->getPosition().x << " - " << block->getPosition().y << std::endl;
window->draw(*block);
}
std::cout << std::string(10, '-') << std::endl;
}
对象的坐标和绘图完美无缺(即使向量被大量填充)。所以我想知道为什么会发生这种情况以及解决此问题的可能方法。我不喜欢这个主意,但也许我应该有标志来检测它们是否已经创建,然后在 draw 方法中创建它们?
So I'm wondering why this is happening
在Game::Game()
中,Block firstBlock(10, 10);
表示firstBlock
是一个局部对象,当超出Game::Game()
的作用域时会被销毁。那么blockList.push_back(this);
在blockList
中保存的指针就变成了悬挂指针,访问它就指向了UB。
and a possible way to work around this.
这里真的需要指针的向量吗?你可以
static std::vector<Block> blockList;
然后像这样使用它:
Block firstBlock(10, 10);
blockList.push_back(firstBlock);
作为宋元耀回答的补充。
你应该考虑一下你的应用程序中的内容。
我认为 Game
可以拥有所有的块,所以在游戏中有 vector<Block> blocks;
是 IMO OK。
或者如果有很多东西,并且你想保持 Game
短一点,你可以引入一些 World
包装器 class 拥有这些块,然后 Game
除其他事项外,还有单个 World world;
实例,其中包含 blocks
向量。
避免在源代码中使用裸指针,它们通常只是指出,您不确定谁应该拥有该对象的实例。拥有一切 "belonging somewhere" 将使所有内存释放只是超出范围的问题。例如,如果您的 main
具有 Game game;
本地实例,它将在退出 main
时被完全破坏(同时释放内部 world
实例以及所有 blocks
).
然后 C++ 感觉几乎就像拥有 GC,但是当 资源释放发生时,您不必担心 ,因为您通过退出特定范围来明确这一点.
我遇到了一些 "odd behaviour" 使用构造函数填充向量值的问题。
所以,我有这个块 class,每当调用构造函数时,它都会填充这个名为 blockList 的静态向量。
static std::vector<Block*> blockList;
Block::Block(float x, float y)
: RectangleShape(sf::Vector2f(WIDTH, HEIGHT)) {
blockList.push_back(this);
setFillColor(sf::Color(221, 221, 221, 255));
setPosition(x, y);
}
现在,当我在另一个 class 中填充值时,我调用了 "Game" ;在它的构造函数中像这样:
Game::Game(sf::RenderWindow& window) {
// other code here
Block firstBlock(10, 10);
// possible more blocks here
}
然后尝试绘制,它崩溃了。此外,此块的坐标打印为 (x: 9.8439e-12, y: 9.84394e-12)。现在我尝试做的是将它放入 draw 方法中(我知道这很糟糕,因为它不断被调用但用于调试目的):
void Game::drawObjects() {
// draw other shapes here
Block oneBlock(50.0f, 50.0f);
std::cout << std::string(10, '-') << std::endl;
for (Block* block : Block::getBlockList()) {
std::cout << block->getPosition().x << " - " << block->getPosition().y << std::endl;
window->draw(*block);
}
std::cout << std::string(10, '-') << std::endl;
}
对象的坐标和绘图完美无缺(即使向量被大量填充)。所以我想知道为什么会发生这种情况以及解决此问题的可能方法。我不喜欢这个主意,但也许我应该有标志来检测它们是否已经创建,然后在 draw 方法中创建它们?
So I'm wondering why this is happening
在Game::Game()
中,Block firstBlock(10, 10);
表示firstBlock
是一个局部对象,当超出Game::Game()
的作用域时会被销毁。那么blockList.push_back(this);
在blockList
中保存的指针就变成了悬挂指针,访问它就指向了UB。
and a possible way to work around this.
这里真的需要指针的向量吗?你可以
static std::vector<Block> blockList;
然后像这样使用它:
Block firstBlock(10, 10);
blockList.push_back(firstBlock);
作为宋元耀回答的补充。
你应该考虑一下你的应用程序中的内容。
我认为 Game
可以拥有所有的块,所以在游戏中有 vector<Block> blocks;
是 IMO OK。
或者如果有很多东西,并且你想保持 Game
短一点,你可以引入一些 World
包装器 class 拥有这些块,然后 Game
除其他事项外,还有单个 World world;
实例,其中包含 blocks
向量。
避免在源代码中使用裸指针,它们通常只是指出,您不确定谁应该拥有该对象的实例。拥有一切 "belonging somewhere" 将使所有内存释放只是超出范围的问题。例如,如果您的 main
具有 Game game;
本地实例,它将在退出 main
时被完全破坏(同时释放内部 world
实例以及所有 blocks
).
然后 C++ 感觉几乎就像拥有 GC,但是当 资源释放发生时,您不必担心 ,因为您通过退出特定范围来明确这一点.