Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 神秘的std::list::size()不匹配_C++_List_C++11_Iterator - Fatal编程技术网

C++ 神秘的std::list::size()不匹配

C++ 神秘的std::list::size()不匹配,c++,list,c++11,iterator,C++,List,C++11,Iterator,我有一个“列表迭代器不可解引用”错误。我认为这通常是由于试图在列表中迭代太远造成的,但是我找不到原因。我严格遵守std::listAPI的函数,因此我不知道下面代码中到底是什么错误导致了这个错误 围绕着这个错误有一些谜团。这个问题的主要焦点是GameStateManager::HandleEvents(),在列表迭代期间。在结束时,我向列表中添加了五个元素,分别称为list::remove()(创建一个空列表),并添加了四个元素。但是,正如您在下面看到的,我在遍历列表之前先打印列表的大小。在调试

我有一个“列表迭代器不可解引用”错误。我认为这通常是由于试图在列表中迭代太远造成的,但是我找不到原因。我严格遵守
std::list
API的函数,因此我不知道下面代码中到底是什么错误导致了这个错误

围绕着这个错误有一些谜团。这个问题的主要焦点是
GameStateManager::HandleEvents()
,在
列表
迭代期间。在结束时,我向列表中添加了五个元素,分别称为
list::remove()
(创建一个空列表),并添加了四个元素。但是,正如您在下面看到的,我在遍历列表之前先打印列表的大小。在调试过程中,这显示了一些令人困惑的地方-由
list::size()
返回的大小与实际大小不同(通过Visual Studio调试器在list::size变量本身中查看)。这仅发生在错误之前-通常两个值相同。但是,就在错误发生之前,size()返回的值不等于列表的size成员值。在删除第一个元素之前,它始终包含上一个值。我忍不住觉得这种差异与“列表迭代器不可解引用”错误有关

此外,在触发错误代码之前,无法立即执行打印命令。此外,在
GameStateManager::HandleEvents()
中,在循环的致命
之前,不会触发任何自定义断点。也许这些异常情况是不同的问题,但我认为了解它们可能是有用的

GameStateManager.h

#pragma once
#include "Tools.h"
#include "TitleScreenState.h"
#include "Game.h"
#include "Timer.h"
#include <list>

class GameState;
class EventHandler;

class GameStateManager
{
public:
    GameStateManager(void);
    ~GameStateManager(void) { m_currentState->OnEnd(); }

    void Run(void);
    void Quit(void) { m_running = false; }

    // Event Handler Functions
    void AddHandler(EventHandler* handler) { m_eventHandlers.emplace_back(handler); }
    void RemoveHandler(EventHandler* handler) { m_eventHandlers.remove(handler); }

private:
    std::list<EventHandler*> m_eventHandlers; // All of the handlers who are passed the events
    bool m_running; // The universal boolean for whether or not the program is running
    int delta; // The time since the last frame
    Timer m_FPSTimer; // The timer that keeps track of the time since the last update
    GameStateID startStateID;

    GameState* m_currentState; // Pointer to the current game state

    // Poll and pass events to the current state
    void HandleEvents(void);
};
#pragma一次
#包括“Tools.h”
#包括“TitleScreenState.h”
#包括“Game.h”
#包括“Timer.h”
#包括
类配子态;
类EventHandler;
类GameStateManager
{
公众:
GameStateManager(无效);
~GameStateManager(void){m_currentState->OnEnd();}
无效运行(void);
void Quit(void){m_running=false;}
//事件处理函数
void AddHandler(EventHandler*handler){m_eventHandlers.emplace_back(handler);}
void removeholder(EventHandler*handler){m_eventHandlers.remove(handler);}
私人:
std::list m_eventHandlers;//传递事件的所有处理程序
bool m_running;//程序是否正在运行的通用布尔值
int delta;//自最后一帧起的时间
Timer m_FPSTimer;//跟踪自上次更新以来的时间的计时器
配子状态ID startStateID;
GameState*m_currentState;//指向当前游戏状态的指针
//轮询事件并将其传递到当前状态
无效手柄通风口(无效);
};
GameStateManager.cpp

#include "GameStateManager.h"
#include "EventHandler.h"
#include "ToolKit.h"
#include "Game.h"
#include <time.h>

GameStateManager* g_manager = nullptr;

GameStateManager::GameStateManager(void) 
    : m_eventHandlers(), delta(0), m_running(true), startStateID(GSID_TITLE), 
      m_currentState(nullptr), m_titleScreen(nullptr), m_game(nullptr)
{
    // Initialise time
    srand(time(nullptr));
}


void GameStateManager::Run(void)
{
    Initialise();

    while (m_running)
    {
        // State's key press responses
        m_currentState->OnKeys(SDL_GetKeyboardState(nullptr));
        // Update State
        m_currentState->OnUpdate(delta);
        // Render State
        m_currentState->OnRender();

        HandleEvents();
    }

    delete this;
}


void GameStateManager::HandleEvents(void)
{
    // Respond to events
    SDL_Event event;
    while(SDL_PollEvent(&event))
    {
        if (event.type == SDL_QUIT) {
            m_running = false; // Quit
        }
        else 
        {
            int size = m_eventHandlers.size();
            printf("Whooo! Size: %d\n", size);

            for (EventHandler* handler : m_eventHandlers)
                handler->OnEvent(event);
        }
    }
}
#包括“GameStateManager.h”
#包括“EventHandler.h”
#包括“ToolKit.h”
#包括“Game.h”
#包括
GameStateManager*g_manager=nullptr;
GameStateManager::GameStateManager(无效)
:m_eventHandlers(),delta(0),m_running(true),startStateID(GSID_TITLE),
m_当前状态(nullptr)、m_标题屏幕(nullptr)、m_游戏(nullptr)
{
//初始化时间
srand(时间(nullptr));
}
void GameStateManager::运行(void)
{
初始化();
同时(m_运行)
{
//州政府的关键新闻回应
m_currentState->OnKeys(SDL_GetKeyboardState(nullptr));
//更新状态
m_currentState->OnUpdate(增量);
//呈现状态
m_currentState->OnRender();
把手通风孔();
}
删除此项;
}
void GameStateManager::HandleEvents(void)
{
//应对事件
SDL_事件;
while(SDL_事件和事件))
{
if(event.type==SDL\u QUIT){
m_running=false;//退出
}
其他的
{
int size=m_eventHandlers.size();
printf(“哇!大小:%d\n”,大小);
for(EventHandler*处理程序:m_eventHandlers)
handler->OnEvent(事件);
}
}
}

某个事件处理程序是否在其OneEvent()中注销自身?如果是这样,这将破坏您的迭代。我不能确定,但我可以预见的一个问题是,
handler->OnEvent(事件)调用调用一些其他处理程序的
GameStateManager::RemoveHandler
。也许
for
循环无法正确迭代列表?作为一个更好的解决方法,在循环之前将
std::list
复制到本地自动列表或向量,并枚举该容器,而不是
m_eventHandlers
。如果处理程序在枚举过程中撤销自身,它将在不影响您的枚举的情况下这样做。这只是一个指针列表,所以复制它应该很快。建议很公平,但没有一个处理程序应该取消引用自己。我将尝试本地复制方法,看看效果如何,只是为了确定。目前,这四个处理程序都是菜单项,例如恢复游戏、退出游戏等。但是,只有当事件发生时,才执行这些处理程序,即单击鼠标-在没有任何输入之前触发错误。尽管如此,还是值得一试。在此之前,任何其他建议都将不胜感激。可能是在for循环之前跟踪未执行打印和断点触发的原因。只需在大小数据成员更改上设置一个数据断点,您就会看到它何时意外更改。您的列表在迭代过程中被更改,或者可能是内存损坏问题。附带说明:您的代码不是线程安全的:至少运行的m_应该是原子的。