【问题标题】:C++ class map objectC++ 类映射对象
【发布时间】:2018-02-22 20:22:01
【问题描述】:

我正在我的 API 中生成一个随机的 sessionId。对于一个sessionId,我需要同时保存userId(给sessionId 所属的用户)和用户类型(例如,管理员、所有者等)。

这是我的哈希图:

std::map<std::string, SessionData*> sessionMap;

这是我的SessionData 课程:

class SessionData
{
public:
    SessionData(std::string pUserId, std::string pUserType)
    {
        userId = pUserId;
        userType = pUserType;
    }

    ~SessionData()
    {
    }

    std::string userId;
    std::string userType;
};

现在我找不到任何解决我的问题的方法。如何在地图中将sessionIduserIduserType 保存到一个?我有 char sessionId[80] 已经有 sessionId 由我的算法生成(算法对于这种情况并不重要)。我是 C++ 新手,但我认为是这样的:

sessionMap[sessionId].insert();

但我不知道如何插入userIduserType,因为我的地图是键 对象.. 键是sessionId,对象是我的类SessionData userIduserType

编辑 1:

我要映射的 typedef 结构:

typedef std::map<std::string, SessionData*> sessionMap_map_t;
sessionMap_map_t sessionMap;

地图中新的插入数据(与当前时间):

sessionMap.insert(std::make_pair(sessionId,new SessionData(userId,userType,currentTime)));

我的地图迭代(我需要每次迭代都可以访问 while 循环内的 currentTime

 sessionMap_map_t::iterator itSessionMap = sessionMap.begin();
    while(itSessionMap != sessionMap.end())
    {
        //TODO: Get currentTime

    }

【问题讨论】:

  • 与您的问题无关,但您的术语有点偏离。 std::map不是“哈希图”。它通常使用树来实现。 std::unordered_map一个“hashmap”。
  • 谢谢。我是 C++ 新手,所以我仍然不清楚一些术语。我已经更正了地图。

标签: c++


【解决方案1】:
SessionData *sessionData;
sessionMap.insert(std::make_pair(sessionId, sessionData));

使用迭代器遍历map:

for (auto itr = sessionMap.begin(); itr != sessionMap.end() ++itr) {
    std::string sessionId = itr->first();
    SessionData *sessionData = itr->second();

    // do something with userId and userType

    // to get current time
    std::string currentTime = sessionData->currentTime;
}

【讨论】:

  • 感谢您的评论和代码。不能像我发布的那样使用课程吗?在您的示例中,您之前没有为 userId 和 userType 分配任何值,但是您需要对吗?
  • @Pik93 是的,这只是显示语法。你应该在使用之前初始化sessionData
  • 是的,我现在明白了:)
  • 我还有其他问题(如果你能帮助我,你可以编辑你的答案)。如何迭代地图并找到一个sessionId并检查userId是否对应于sessionId?
  • @Pik93 你可以accept我的回答,如果它解决了你的问题。 :-)
【解决方案2】:

解决办法

#include <iostream>
#include <string>
#include <map>
using namespace std;
class SessionData
{

public:
    SessionData(std::string pUserId, std::string pUserType)
    {
        userId = pUserId;
        userType = pUserType;
    }

    ~SessionData()
    {
    }

    std::string userId;
    std::string userType;

};

int main()
{
  std::map<std::string, SessionData*> sessionMap;  
  **sessionMap.insert(std::make_pair("Test_Session_12345",new SessionData("1234","Test")));**
}

【讨论】:

    【解决方案3】:

    您的方法并非完全错误。 让我们假设...

    std::string pUserId = "MyFirstUser";
    std::string pUserType = "testType";
    

    ...然后插入如下...

    // A short method to insert a new entry...
    sessionMap[pUserId] = new SessionData(pUserId, pUserType);
    // using operator[] is a more elegant alternative to calling insert(...value_type(...))
    

    ...现在它是 sessionMap 中的一个有效条目,将 pUserId 'unique' 映射到 SessionData 的实例。 但请注意,SessionData 实例是

    1. 通过弱指针引用。当心潜在的内存泄漏。删除条目或清除地图不会删除实例!

    2. 在其中一个实例中更改成员“userId”不会隐式更改到该实例的键映射。

    对于那些抱怨我在插入之前没有检查条目的人,请按照第二个示例检查...

    // A more "verifying" method to insert a second entry...
    pUserId = "MySecondUser";
    std::map<std::string, SessionData*>::const_iterator itEntry = sessionMap.find(pUserId);
    if (sessionMap.end() == itEntry)
    {   // Either "old"-style...
        // sessionMap.insert(std::map<std::string, SessionData*>::value_type(pUserId, new SessionData(pUserId, pUserType));
        // ...or again elegant style...
        sessionMap[pUserId] = new SessionData(pUserId, pUserType);
    }
    else
    {   // Example error handling in case of non-unique keys...
        throw string("error: Entry '") + pUserId + string("' is not unique");
    }
    

    更改已插入条目的键不会更改地图中元素的顺序。 即使您使用 std::set 或任何其他技巧也不会改变这一点,因为在条目成员发生更改的情况下不会重新调用派生二叉树的排序逻辑。

    如果您想找到您的 createTime 并在超过 30 分钟的情况下将其删除,我建议您遵循...

    // I assume you have/implement a class 'MyTimeClass' and a static function initializing it with the current time...
    MyTimeClass currenTime = MyTimeClass::currentTime();
    // Let's define an intermediate not-expiring-time...
    MyTimeClass oldestNotExpiringTime = currentTime - MyTimeClass(30min); // 30min is pseudo code and shall be replaced by the parameters defining the 30 minutes of expiration, however your MyTimeClass is defined
    // Now, let's iterate all entries in the map using the non-const iterator (to be able to modify the map by deleting entries)...
    for ( std::map<std::string, SessionData*>::iterator itEntry = sessionMap.begin(); sessionMap.end() != itEntry; /* don't ++itEntry to avoid conflicts with erase() */ )
    {   // I assume you have a member 'createTime' of type 'MyTimeClass'...
        MyTimeClass createTime = itEntry->second.createTime;
        // ...and I assume it implements an operator<() to compare times...
        if (createTime < oldestNotExpiringTime)
        {   // this means the createTime is older than the oldest accepted time -> delete it but first copy the iterator to be able to resume iteration after deletion...
            std::map<std::string, SessionData*>::iterator itToDelete = itEntry;
            // Iterate the loop-iterator before deleting the entry to avoid access violations (aka SEGFAULT)...
            ++itEntry;
            // Now delete the entry...
            sessionMap.erase(itToDelete);
        }
        else
        {   // No reason to delete -> iterate regularily...
            ++itEntry;
        }
    }
    

    在删除条目之前迭代到下一个位置非常重要,因为“旧”迭代器是一种指向条目的指针,也会被删除。迭代已删除的迭代器通常会导致访问违规(内存异常,SEGFAULT)。这就是为什么我在 if/else 中做出这个例外。

    【讨论】:

    • 感谢您的意见。我还有一个问题:
    • 现在想象一下我的 SessionData 有 3 个字段(userId、userType、createTime)我的 sessionIds 有验证(例如 30 分钟),并且我每秒运行一个函数。此函数需要迭代所有映射并检查所有 sessionIds 的所有 createTimes。如果某些 createTime 大于 30 分钟,我需要删除此 sessionId。我的疑问是:如何迭代所有地图,获取 createTime(检查我知道如何做的当前日期)并删除 sessionId。例如,如果我有 5 个 createTime 大于 30 分钟的 sessionId,我需要在迭代期间全部删除。请检查我的 EDIT 1 以查看我的代码
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 2015-09-27
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 2019-09-19
    • 1970-01-01
    相关资源
    最近更新 更多