插入地图时抛出异常

时间:2012-05-12 20:20:12

标签: c++ exception map

当我尝试将对象插入地图时,会抛出以下异常:

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));

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 ++问题:不同文件之间静态初始化的顺序很大程度上是未定义的,很少能达到你想要的效果。