3

当我尝试将一个对象插入我的地图时,它会引发以下异常:

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

2 回答 2

4

To address the need for a public default constructor, try changing this:

Player p(playerID, team, name, color);
players.insert(std::make_pair(playerID, p)); // EXCEPTION THROWN HERE
return players[playerID];

into this:

return players.insert(std::make_pair(playerID, Player(playerID, team, name, color))).first->second;

(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:

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

Now just use Player::players() to get a reference to the map.

于 2012-05-12T20:26:01.710 回答
2

Is the insertion also happening as part of the static initialisation of some other object?

If so you've hit a classic C++ gotcha: the order of static initialisation between different files is largely undefined, and rarely does what you want.

于 2012-05-12T20:26:58.007 回答