Pik93
Pik93

Reputation: 49

C++ class map object

I'm generating a random sessionId in my API. For one sessionId I need to save ate same time the userId (to the user to which the sessionId belongs) and the user type (for example, admin, owner etc).

This is my hashmap:

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

And this is my SessionData class:

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

    ~SessionData()
    {
    }

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

Now I don't find any solution for my problem. How to save in map to one sessionId the userId and userType? I have the char sessionId[80] that already have the sessionId generate by my algorithm (The algorithm is not important for the situation). I'm new in c++ but I think that is something like that:

sessionMap[sessionId].insert();

But I don't know how to insert the userId and userType, because my map is key <-> Object.. The key is sessionId and the object is my class SessionData that have the userId and userType.

EDIT 1:

My typedef struct to map:

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

The new insert data in map (with current time):

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

My map iteration (i need to have access for each iteration to currentTime inside while loop

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

    }

Upvotes: 0

Views: 209

Answers (3)

tildawn
tildawn

Reputation: 11

Your approach is not totally wrong. Let's assume...

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

...then insert it like as follows...

// 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(...))

...now it's a valid entry in your sessionMap, mapping pUserId 'unique' to an instance of SessionData. But be aware that SessionData instances are

  1. referenced via weak pointers. Beware of potential memory-leaks. Erasing entries or clearing the map doesn't delete the instances!

  2. changing the member 'userId' in one of the instances doesn't implicitly change key mapping to the instance.

For those who are complaining that I did not check the entry before inserting it check following 2nd example...

// 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");
}

Changing the key of an already inserted entry doesn't change the order of elements in the map. Even if you use std::set<> or any other trick will not change this as the sort-logic of the derived binary tree is not re-invoked in case of changes to the entry members.

In case you want to find your createTime and delete it in case of exceeding 30minutes I propose following...

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

It's very important that you iterate to the next position before deleting the entry because the "old" iterator is kind of a pointer to the entry and will be deleted as well. Iterating the deleted iterator results usually in an access violaton (memory exception, SEGFAULT). This is why I make this exception if/else.

Upvotes: 0

zhm
zhm

Reputation: 3651

SessionData *sessionData;
sessionMap.insert(std::make_pair(sessionId, sessionData));

Use iterater to traverse 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;
}

Upvotes: 1

PapaDiHatti
PapaDiHatti

Reputation: 1921

Here is the solution

#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")));**
}

Upvotes: 0

Related Questions