Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.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++ 多重映射清除_C++_Multimap - Fatal编程技术网

C++ 多重映射清除

C++ 多重映射清除,c++,multimap,C++,Multimap,这是一个简单的事件系统,我使用多重映射制作;当我使用CEvents::Add(..)方法时,它应该插入并输入到多重映射中。问题是,当我触发这些事件时,多重映射看起来是空的。我肯定我没有调用delete方法[CEvents::Remove]。代码如下: //Code: .. CEvents Ev; Ev.Add("onButtonBReleased",OutputFST); .. // "CEvents.h" class CEvents { public: void

这是一个简单的事件系统,我使用多重映射制作;当我使用CEvents::Add(..)方法时,它应该插入并输入到多重映射中。问题是,当我触发这些事件时,多重映射看起来是空的。我肯定我没有调用delete方法[CEvents::Remove]。代码如下:

//Code:
..
CEvents Ev;
Ev.Add("onButtonBReleased",OutputFST);
..

// "CEvents.h"
class CEvents
{
public:

    void            Add                     ( string EventName, void(*fn)(void));   
    void            Remove                  ( string EventName, void(*fn)(void));
    void            Trigger                 ( string EventName );

//protected:

    bool            Found;

    std::multimap<string,void(*)(void)> EventsMap;
    std::multimap<string,void(*)(void)>::iterator EvMapIt;
};



//CEvents.cpp
void CEvents::Add (string EventName, void (*fn)(void))
{
if (!EventsMap.empty())
{
    Found = false;

    for (EvMapIt = EventsMap.begin(); EvMapIt != EventsMap.end(); EvMapIt++)
    {
        if ((EvMapIt->first == EventName) && (EvMapIt->second == fn))
        {
        CTools tools;
        tools.ErrorOut("Function already bound to same event... Not registering event");
                Found = true;
            } 
        }

        if (!Found)
        {
            EventsMap.insert(std::pair<string,void(*)(void)>(EventName,fn));
            std::cout<<"Added, with size "<<(int) EventsMap.size()<<std::endl; //Getting 1
        }
}
else
{
    EventsMap.insert (std::pair<string,void(*)(void)>(EventName,fn));
    std::cout<<"Added, with size "<<(int) EventsMap.size()<<std::endl; //Getting 1
}
}

void CEvents::Trigger (string EventName)
{
std::cout<<"Triggering init"<<std::endl;
std::cout<<(int) EventsMap.size()<<std::endl; //Getting 0

for (EvMapIt = EventsMap.begin(); EvMapIt != EventsMap.end(); EvMapIt++)
    {
        std::cout<<"Triggering proc"<<std::endl;
        if (EvMapIt->first == EventName)
    EvMapIt->second();
}
}
//代码:
..
CEEV;
Ev.添加(“OnButtonDeleted”,OutputFST);
..
//“CEvents.h”
类事件
{
公众:
void Add(字符串EventName,void(*fn)(void));
void Remove(字符串EventName,void(*fn)(void));
无效触发器(字符串EventName);
//受保护:
布尔发现;
std::multimap EventsMap;
std::multimap::迭代器EvMapIt;
};
//CEvents.cpp
void CEvents::Add(字符串EventName,void(*fn)(void))
{
如果(!EventsMap.empty())
{
发现=错误;
对于(EvMapIt=EventsMap.begin();EvMapIt!=EventsMap.end();EvMapIt++)
{
如果((EvMapIt->first==EventName)&&(EvMapIt->second==fn))
{
CTools工具;
ErrorOut(“函数已绑定到同一事件…未注册事件”);
发现=真;
} 
}
如果(!找到)
{
插入(std::pair(EventName,fn));

std::cout这不是如何使用映射。可以使用映射,这可能比迭代集合中的所有元素更快。如果要确保键是唯一的,则可以使用普通映射,而不是多映射,多映射明确用于将重复键存储为唯一实体

编辑:根据您的注释更新键不应该是唯一的。然后,您应该使用和进行搜索,这比将所有键检查为
find
(从内存中)只返回
下限值要好。或者,您也可以只迭代一个键的结果(如注释中的标记所示)这将导致同样的结果


只要看一眼您的代码(由于缺少
擦除
清除
交换
调用),我猜您的问题在于您将元素添加到集合中时,而不是将其“清空”。

顺便说一句,为了加快速度,最好在找到项目时中断您的for:

for (EvMapIt = EventsMap.begin(); EvMapIt != EventsMap.end(); EvMapIt++)
{
    if ((EvMapIt->first == EventName) && (EvMapIt->second == fn))
    {
            CTools tools;
            tools.ErrorOut("Function already bound to same event... Not registering event");
            Found = true;
            break;
    } 

 }
编辑: “插入成员函数返回一个迭代器,该迭代器指向新元素插入多重映射的位置。”(msdn)


为了确保插入正确,请输入插入的返回值。

它不应该是代码审阅站点,但我无法控制自己

// "CEvents.h"
class CEvents
{
public:
    typedef void (*Callback)(void);

    // 1. Don't use `using namespace` in header files
    // 2. Pass by const reference to avoid a copy
    // 3. Function Pointers are easier to deal with when typedef'd
    void Add(std::string const& EventName, Callback fn);
    void Remove(std::string const& EventName, Callback fn);
    void Trigger(std::string const& EventName);

// Attributes should be `private` or `public`, `protected` is for functions.
// If you read otherwise, consider how this violates encapsulation.
//protected:

private: // cause nobody's touching my stuff lest they break it!

    // useless in this class, should be local variables in the routines
    // bool Found;
    // MapType::iterator EvMapIt;

    // typedef make life easier, spelling that out each time is just tiring.
    typedef std::multimap<std::string, Callback> MapType;
    MapType EventsMap;
};
/“CEvents.h”
类事件
{
公众:
typedef void(*回调)(void);
//1.不要在头文件中使用'using namespace'
//2.传递常量引用以避免复制
//3.使用typedef时,函数指针更容易处理
voidadd(std::stringconst&EventName,回调fn);
void Remove(std::string const&EventName,回调fn);
无效触发器(std::string const和EventName);
//属性应为'private'或'public','protected'用于函数。
/如果你不读,考虑一下这是如何违反封装的。
//受保护:
因为没人碰我的东西,免得他们弄坏了!
//在这个类中无用,应该是例程中的局部变量
//布尔发现;
//MapType::迭代器EvMapIt;
//typedef让生活变得更轻松,每次都把它拼出来是很累的。
typedef std::多映射映射类型;
地图类型事件地图;
};
好的,让我们来看看源文件

//CEvents.cpp

// Whole rewrite to use idiomatic interfaces
void CEvents::Add(std::string const& EventName, Callback fn)
{
    // Retrieve the range of callbacks registered for "EventName"
    std::pair<MapType::iterator, MapType::iterator> const range =
        EventsMap.equal_range(EventName);

    // Check that this callback is not already registered.
    for (MapType::iterator it = range.first, end = range.second;
         it != end; ++it)
    {
        if (it->second == fn) {
            // Are you sure `ErrorOut` should not be a free function
            // or at least a `static` function ?
            // It feels weird instantiating this class.
            CTools tools;
            tools.ErrorOut("Function already bound to same event..."
                           " Not registering event");
            // If it is in there, nothing to do, so let's stop.
            return;
        }
    }

    // If we are here, then we need to add it.
    // Let's give a hint for insertion, while we are at it.
    EventsMap.insert(range.second, std::make_pair(EventName, fn));

    // the (int) cast was C-like (bah...) and unnecessary anyway
    std::cout << "Added, with size " << EventsMap.size() << std::endl; 
}


void CEvents::Trigger (std::string const& EventName)
{
    std::cout << "Triggering init" << std::endl;
    std::cout <<  EventsMap.size() << std::endl; //Getting 0

    // Retrieve the range of callbacks registered for `EventName`
    std::pair<MapType::const_iterator, MapType::const_terator> const range =
        EventsMap.equal_range(EventName);

    // Call each callback in turn
    for (MapType::const_iterator it = range.first, end = range.second;
         it != end; ++it)
    {
        it->second();
    }
}
//CEvents.cpp
//全部重写以使用惯用接口
void CEvents::Add(std::string const&EventName,回调fn)
{
//检索为“EventName”注册的回调的范围
std::成对常数范围=
EventsMap.equal_范围(EventName);
//检查此回调是否尚未注册。
对于(MapType::iterator it=range.first,end=range.second);
它!=结束;++它)
{
如果(它->秒==fn){
//你确定'ErrorOut'不应该是自由函数吗
//或者至少是一个“静态”函数?
//实例化这个类感觉很奇怪。
CTools工具;
ErrorOut(“函数已绑定到同一事件…”
“未登记事件”);
//如果它在那里,没什么可做的,所以让我们停下来。
返回;
}
}
//如果我们在这里,那么我们需要添加它。
//在插入时,让我们给出一个提示。
EventsMap.insert(range.second,std::make_pair(EventName,fn));
//(int)的演员阵容是C型的(呸…),无论如何都是不必要的

std::coutOk,最后解决了它;供将来参考:

每次声明实例时,它都会重新定义多重映射。 解决方案是创建一个指向该类的全局指针


感谢所有回答的人!

键不应该是唯一的,我只是在检查键和值是否同时存在。除此之外,键可以存在多次。@MarwanDessouki,您可以迭代
equal\u range
返回的范围,而不是整个地图。@Markransem谢谢您的建议。猜一猜,您正在添加到映射的副本,而不是您用于查找的映射。@BenVoigt您能简单地告诉我如何解决它吗?:-)恐怕错误不在您显示的代码中。如果可以,请尝试使用,并在那里执行一个显示您看到的行为的最小示例,这样您就可以确保包含了查看b所需的代码ug:)@MatthieuM.True,现在测试它->调用类的实例是否会导致它重新定义变量,可能会重置?@MarwanDessouki:
#define string std::string
有点笨拙,您可以使用
using std::string;
将类型
string
带入当前范围。仍然只在源文件中这样做,不是页眉。谢谢,我会的