【问题标题】:Can i save the pointers of some objects in a vector and than take that pointers to call an inline function我可以将某些对象的指针保存在向量中,然后用这些指针调用内联函数吗
【发布时间】:2019-07-22 04:05:27
【问题描述】:

假设我有一个 Player 类,它有一些成员函数。其中之一使用 this 关键字返回对象的指针。 Player* getPlayer() { return this;};

class Player
{
public:

    Player(int id, string name, int score = 0) : pId(id), pName(name), pScore(score) { };
    void rollDice();

    int getId() { return pId; }
    int getScore() { return pScore; }
    string getName() { return pName; }
    Player* getPlayer() { return this;};
private:
    int pId;
    std::string pName;
    int pScore;
    unsigned char playerDiceRolled;
    Dice mDice;
};

我还有一个名为 Game 的类,它使用一个函数将任何玩家的信息保存在不同的向量中。其中一个向量保存了对象向量 playerList 的指针;

class Game
{
public:


    void Winer();
    void addPlayer(Player A) ;
    void updateScore();
    vector<Player*> playerList;
    vector<int> idList;
    vector<string> nameList;
    vector<size_t> scoreList;

};

void Game::addPlayer(Player A)
{

    this->playerList.push_back(A.getPlayer());
    this->idList.push_back(A.getId());
    this->nameList.push_back(A.getName());
    this->scoreList.push_back(A.getScore());

}

我的问题是我可以从那个向量中取出指针并用它来调用那个类的函数并返回 wright 值。

我试过了,还是不行

我可以看到 Player 的其他值已正确保存,但是当我使用指针调用函数以获取值时,它返回 null。 例如

int main()
{
    Game Game1;
    Player A(0, "Player1");
    Player B(1, "Player2");
    Game1.addPlayer(A);

    Game1.addPlayer(B);

    cout << "Name is:" << Game1.nameList[1] << "\n";



    cout << "Name is:" << Game1.playerList[1]->getName() << "\n";






    return 0;

}

cout 为 Game1.nameList[1] 提供玩家的赖特名称,但为 NULL 值 Game1.playerList[1]->getName()

【问题讨论】:

  • addPlayer(Player A) 获取 Player 对象的副本。 A 的副本在方法 addPlayer 的末尾被破坏。使用this-&gt;playerList.push_back(A.getPlayer());,您可以将指针保存到向量中的临时对象。
  • 您可以使用 ref 运算符 &amp; 而不是 getPlayer。你可以直接将指针传递给对象。然后您可以使用一种称为智能指针的模式来确保您不会破坏正在使用的对象。看看unique_prshared_ptr
  • Player::getPlayer完全是多余的。如果你有一个指向Player 的指针,你已经有了getPlayer 的结果。如果你引用了 Player,那么已经有 &amp;std::addressof 做同样的事情

标签: c++


【解决方案1】:

那是因为你正在存储一个指向你的对象副本的指针:

void Game::addPlayer(Player A)

你需要使用一个引用并存储它:

void Game::addPlayer(Player& A)

否则你会得到一个未定义的行为。

【讨论】:

  • 是的,如果指向的对象(而不是副本)被更改。这就是指针的优势!
  • 如果我明白了,第一种情况的问题是,当我将对象传递给函数时,我正在创建一个副本来传递它,该副本具有与我想要的对象不同的指针,并且在函数 wright 的末尾被破坏了?
【解决方案2】:

addPlayer(Player A) 获取 Player 对象的副本。 A 的副本在方法 addPlayer 的末尾被破坏。使用this-&gt;playerList.push_back(A.getPlayer());,您可以将指针保存到向量中的临时对象。

您应该从总体上考虑您的代码设计。游戏具有玩家列表,因此游戏拥有这些玩家对象的共享或独占所有权。因此,您不应在此处使用原始指针。

如果您拥有独占所有权,您将使用:

std::vector<std::unique_ptr<Player>> playerList;

或者

std::vector<Player> playerList;

对于您将使用的共享所有权:

std::vector<std::shared_ptr<Player>> playerList;

所以设置可能如下所示:

int main()
{
    Game Game1;

    Game1.addPlayer(std::move(std::make_unique<Player>(0, "Player1"));
    Game1.addPlayer(std::move(std::make_unique<Player>(0, "Player2"));

    cout << "Name is:" << Game1.nameList[1] << "\n";
    cout << "Name is:" << Game1.playerList[1]->getName() << "\n";

    return 0;
}


class Game {
public:
    void Winer();
    void addPlayer(Player A);
    void updateScore();
    vector<std::unique_ptr<Player>> playerList;
    vector<int> idList;
    vector<string> nameList;
    vector<size_t> scoreList;
};

void Game::addPlayer(std::unique_ptr<Player> A)
{
    this->idList.push_back(A->getId());
    this->nameList.push_back(A->getName());
    this->scoreList.push_back(A->getScore());

    // adding A to the vector has to be the last action, because A is moved to the vector
    this->playerList.push_back(std::move(A));
}

原始指针现在一般来说是不好的,但是当你想表达所有权时不要使用它们。因此,如果您将 Player 对象传递给不应获得该对象所有权的函数,那么您会将其作为原始指针传递:

void print_player_info(Player * const p) {
    // only prints the player info so no ownership is taken
    // p is only use within print_player_info  
    cout << "Name is:" << p->getName() << "\n";
} 


int main()
{
    Game Game1;

    Game1.addPlayer(std::move(std::make_unique<Player>(0, "Player1"));
    Game1.addPlayer(std::move(std::make_unique<Player>(0, "Player2"));

    print_player_info(Game1.playerList[1]->get());

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    • 2021-06-03
    • 1970-01-01
    • 2020-09-18
    • 1970-01-01
    • 2014-01-25
    • 2018-08-08
    相关资源
    最近更新 更多