When I try to insert an object into my map, it throws the following exception:
Unhandled exception at 0x77a015de in Main.exe: 0xC0000005: Access violation reading location 0x00000004.
The “reading location 0x00000004” makes me think it’s some sort of null pointer exception. However, the map itself is a static map, initialized in the .cpp file. Why wouldn’t it have a location when trying to do the insert?
Here’s the class. It’s a player class that manages mapping IDs to players:
// Player.hpp
class Player {
public:
Player(){}; // I had to make this public, otherwise it wouldn't compile.
Player(Player &p);
Player & operator=(const Player &p);
bool operator==(const Player &p);
int getID() const;
int getTeam() const;
string getName() const;
Vec3 getColor() const;
static Player newPlayer(int team, string name, Vec3 color);
private:
Player(int id, int team, string name, Vec3 color);
int id,
team;
string name;
Vec3 color;
static std::map<int, Player> players;
};
and the cpp file:
#include "Player.hpp"
std::map<int, Player> Player :: players;
int Player :: currentPlayer=-1;
// Constructor
Player :: Player(Player &p) : id(p.getID()),
team(p.getTeam()),
name(p.getName()),
color(p.getColor()){}
Player & Player :: operator=(const Player &p){
if (this==&p){
return *this;
}
id=p.getID();
team=p.getTeam();
name=p.getName();
color=p.getColor();
return *this;
}
bool Player :: operator==(const Player &p){
return p.getID()==getID();
}
// Factory
Player Player :: newPlayer(int team,
string name,
Vec3 color){
int playerID=0;
if (players.size()>0){
int playerID=(*players.rbegin()).first+1; // get an ID higher than the largest already there.
}
Player p(playerID, team, name, color);
players.insert(std::make_pair(playerID, p)); // EXCEPTION THROWN HERE
return players[playerID];
}
// Internal Constructor
Player :: Player(int id,
int team,
string name,
Vec3 color) : id(id),
team(team),
name(name),
color(color){}
Can anyone help me understand what’s going on here?
EDIT:
The code that’s calling this method is in main.hpp, outside of any methods, in the global scope:
Player player1=Player::newPlayer(1, "p1", Vec3(0.2, 0.2, 0.8)),
player2=Player::newPlayer(2, "p2", Vec3(0.8, 0.2, 0.2));
To address the need for a public default constructor, try changing this:
into this:
(Explanation: The
[]-operator requires that your mapped type be default-constructible. Using it means that you’re ignoring the knowledge that the key that you’re looking up exists in the map. The operator wants to create a new default-constructed element if the key that you give it doesn’t exist.)Update: You also have to address the static initialization problem. Here’s one way how to do this:
Now just use
Player::players()to get a reference to the map.