c++ - 为什么在 C++ 中的字符串变量的 cout 中显示奇怪的字符?

标签 c++ string

我有以下代码:

Card.h:

#include <string>

using namespace std;

class Card
{
public:
    Card(string name);
    ~Card() {}; 

    string GetName();

private:
    string Name;

};

卡片.cpp:

#include "Card.h"

using namespace std;

Card::Card(string name) {Name=name;};
string Card::GetName() {return Name;}

Deck.h:

#include "Card.h"
#include <vector>

class Deck {
    public:
        Card& DrawCard();
        void AddCardToDeck(Card& c);

        Deck();
        ~Deck();

    private:
        std::vector <Card> cardsindeck;
};

Deck.cpp:

#include "Deck.h"
#include <vector>
#include <iostream>

using namespace std;

Card& Deck::DrawCard() {
    //cout << cardsindeck.back().GetName()<<" was drawn "<<endl;
    Card &c = cardsindeck.back();
    cout << c.GetName()<<" was drawn "<<endl;
    cardsindeck.pop_back();
    cout << c.GetName()<<" popped from deck "<<endl;
    return c;
}

Deck::Deck()
{

}

Deck::~Deck()
{
}

void Deck::AddCardToDeck(Card& c) {
    cardsindeck.push_back(c);
}

Player.h:

#include "Deck.h"
#include <vector>

using namespace std;

class Player {
    public:
        void Beginning();
        Player(Deck _deck);
        ~Player() {};

    private:
        vector <Card> cardsindeck;
        Deck deck;

};

Player.cpp:

#include "Player.h"

using namespace std;

Player::Player(Deck _deck)
{
    this->deck = _deck;
}

void Player::Beginning()
{
    Card& c = deck.DrawCard();

}

main.cpp:

#include "Player.h"
#include <iostream>
#include <string>

using namespace std;

int main()
{

    Deck aDeck;
    vector <Card> aHand;

    Card c=Card("THIS THIS GREAT PLAYER");
    Card& c1 =c;
    aDeck.AddCardToDeck(c1);

    Player P = Player(aDeck);
    P.Beginning();

    return 0;
} 

我得到的输出是:

THIS THIS GREAT PLAYER was drawn 
�\IS GREAT PLAYER popped from deck 

为什么第二行用那些奇怪的字符代替了“THIS THIS”?

最佳答案

你在这个函数中有未定义的行为:

Card& Deck::DrawCard() {
    // ...
    Card &c = cardsindeck.back();
    // ...
    cardsindeck.pop_back();
    cout << c.GetName()<<" popped from deck "<<endl;

    return c;
}

首先,您使用名为c 的引用为cardsindeck 的最后一个元素设置别名。这很好,访问它的成员函数也很好。然后,您使用 cardsindeck.pop_back(); 从容器中移除元素。来自 std::vector::pop_back 上的文档, 我们看到

No iterators or references except for back() and end() are invalidated.

这就是问题所在。您有对 back() 的引用,并且该引用已失效。它必须是 - 您正在从容器中删除 c 引用的 vector 中的元素。然后访问其成员,例如by GetName() 是 UB,那么。

您可以通过复制 cardsindeck.back() 的返回值轻松解决此问题,如下所示:

Card c = cardsindeck.back();
//  ^^ No reference. The last element is copied

cardsindeck.pop_back(); // Doens't affect the copied instance above

return c;

注意这里需要把成员函数的签名改成

Card Deck::DrawCard()

返回值不再是引用。

关于c++ - 为什么在 C++ 中的字符串变量的 cout 中显示奇怪的字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55038596/

相关文章:

c++父类(super class)为子类定义静态成员变量

c++ - 在 TFS 测试阶段运行 C++ 单元测试

c++ - 如何在 Win32 控制台应用程序中将 argv[ ] 设置为不区分大小写?

c++ - 如何在 Windows 中用 c/c++ 将 double 类型写入文件?

c++ - 队列实现错误 C++

java - 为什么java的 String split ("\\s") 数组中有一个空字符串?

android - 如何在 Android 中设置 String[] 的 TextView ?

java - Hashmap 未收到预期值

javascript - 使用 Javascript 填充 HTML 选择

javascript - 捕获字符之间的字符串并替换