C ++使用构造函数填充的向量的奇怪行为

时间:2016-07-19 03:07:50

标签: c++ vector runtime-error stdvector

我经历了一些奇怪的行为"使用构造函数填充矢量值。

所以,我有这个块类,只要调用构造函数,就会填充这个名为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);
}

现在,当我在另一个类中填充值时,我调用了#34; Game&#34; ;在它的构造函数中如下:

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;
}

对象的坐标和绘图完美地工作(即使矢量被大量填充)。所以我想知道为什么会这样,并且可以解决这个问题。我不喜欢这个想法,但也许我应该有标记来检测它们是否已经创建,然后在绘制方法中创建它们?

2 个答案:

答案 0 :(得分:7)

  

所以我想知道为什么会发生这种情况

Game::Game()中,Block firstBlock(10, 10);表示firstBlock是一个本地对象,当它超出Game::Game()的范围时将被销毁。然后blockList.push_back(this);blockList保存的指针变为悬空指针,访问它会导致UB。

  

以及解决此问题的可能方法。

你真的需要一个指针的向量吗?你可以

static std::vector<Block> blockList;

然后使用它:

Block firstBlock(10, 10);
blockList.push_back(firstBlock);

答案 1 :(得分:1)

作为宋元尧回答的附录。

您应该考虑一下您应用中的内容所拥有的内容。

我认为Game可以拥有所有的块,因此在游戏中拥有vector<Block> blocks;就可以了IMO。

或者如果有很多东西,并且你想让Game更短一点,你可以引入一些拥有这些块的World包装类,然后Game包含其他内容World world;实例,其中包含blocks向量。

避免源中的裸指针,他们经常只是指出,你不确定谁应该拥有该对象的实例。让一切“属于某个地方”将使所有的记忆释放出超出范围的问题。例如,如果您的main具有Game game;本地实例,则在退出main时它将完全被破坏(同时使用所有{{1}的向量释放内部world实例})。

然后C ++感觉就像拥有GC一样,但是当资源释放发生时你不需要害怕,因为你通过退出特定范围来明确表示。