当我尝试将对象插入地图时,会抛出以下异常:
Main.exe中0x77a015de处的未处理异常:0xC0000005:访问冲突读取位置0x00000004。
“读取位置0x00000004”让我觉得它是某种空指针异常。但是,映射本身是一个静态映射,在.cpp文件中初始化。为什么尝试插入时没有位置?
这是课程。它是一个玩家类,用于管理映射ID给玩家:
// 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;
};
和cpp文件:
#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){}
有谁能帮我理解这里发生了什么?
编辑: 在全局范围内,调用此方法的代码位于main.hpp之外的任何方法之外:
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));
答案 0 :(得分:4)
要解决对公共默认构造函数的需求,请尝试更改此:
Player p(playerID, team, name, color);
players.insert(std::make_pair(playerID, p)); // EXCEPTION THROWN HERE
return players[playerID];
进入这个:
return players.insert(std::make_pair(playerID, Player(playerID, team, name, color))).first->second;
(解释:[]
- 运算符要求您的映射类型是默认构造的。使用它意味着您忽略了您正在查找的键存在于地图中的知识。如果您提供的密钥不存在,则想要创建一个新的默认构造元素。)
更新:您还必须解决静态初始化问题。以下是如何执行此操作的一种方法:
// header:
class Player {
public:
static std::map<int, Player> & players();
// ...
};
// implementation:
std::map<int, Player> & Player::players()
{
static std::map<int, Player> impl;
return impl;
}
现在只需使用Player::players()
来获取对地图的引用。
答案 1 :(得分:2)
插入是否也作为其他对象的静态初始化的一部分发生?
如果是这样,你已经遇到了经典的C ++问题:不同文件之间静态初始化的顺序很大程度上是未定义的,很少能达到你想要的效果。