何时使用新关键字?

时间:2019-06-01 21:47:45

标签: c++ memory heap sfml

我正在使用SFML开发小型游戏,我创建了一个游戏类来存储各种类;例如播放器类。

我用“ new”关键字初始化了堆上的类,但是经过数小时试图弄清楚为什么我的播放器类在一定范围后变为空的原因。我决定不初始化堆上的游戏,这样做之后,一切都很好。

有人可以解释为什么会这样。顺便说一句,我不再在堆上创建游戏了,而是在显示我以前获取空引用时使用的代码。

int main()
{
    sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "Dungeon Run");

    //Asset test;
    //test.CreateAsset("GameAssets/Player.png");

    sf::Event event;
    renderWindow.setKeyRepeatEnabled(true);

    Game* game = new Game(renderWindow);
// Player initialized here.
    game->Initialize(); 
    while (renderWindow.isOpen()) 
    {
// Game->Player goes null in here.
        while (renderWindow.pollEvent(event))
        {

            if (event.type == sf::Event::EventType::Closed)
            {
                renderWindow.close();
            }
            //set window to random color to check if working
            if (event.type == sf::Event::EventType::KeyPressed) {
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) {
                }
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
                }
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {
                }
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {
                }
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) {
                    renderWindow.close();
                }
            }
            else if (event.type == sf::Event::EventType::MouseButtonPressed) {
                if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
                }
                else if (sf::Mouse::isButtonPressed(sf::Mouse::Right)) {
                }
            }

            renderWindow.clear();
            game->Draw(); // Here player was null when I tried to draw the sprite for the player.
            renderWindow.display();
        }
    }

delete game;
game = nullptr;
}

播放器类:

class Player
{
public:
    Player();
    Player(std::string name) 
        : name(name) 
    {
    }


    std::string name = "";
    double health = 100;
    double stamina = 100;
    int level = 1;
    Asset sprite;

    void attack();

    ~Player();
};


资产类别:

Asset::Asset() {

}

void Asset::CreateAsset(std::string path) {
    if (!texture.loadFromFile(path)) {
        std::cout << "Failed to load texture from file: " << path << std::endl;
    }

    sprite.setTexture(texture);
}

sf::Sprite& Asset::GetSprite() {
    return sprite;
}

Asset::~Asset() {

}

Game.h和Game.cpp:

class Game {
private:
    Player player;
    sf::RenderWindow* window;
public:
    Game(sf::RenderWindow& window);

    void Initialize();
    void Upadte();
    void Draw();

    ~Game();
};


Game::Game(sf::RenderWindow& window) {
    this->window = &window;
    player = Player("Player");
}

void Game::Initialize() {
    player.sprite.CreateAsset("GameAssets/player.png");
}

void Game::Upadte() {
}

void Game::Draw() {
    window->draw(player.sprite.GetSprite()); // Drawing his sprite
}

Game::~Game() {
}

1 个答案:

答案 0 :(得分:3)

在现代C ++中,您几乎不需要new关键字

如果要在堆上创建对象,请使用unique_ptrshared_ptr

您通过以下方式创建课程

std::unique_ptr<Game> game = std::make_unique<Game>(renderWindow);

这样,您就不需要delete了,因为unique_ptr会在超出范围时为您处理。

所以只需将上面的new行替换为delete

您可能需要包括以下内容才能使用std::unique_ptr

#include <memory>

至于“为什么”,您遇到了一个问题:负责的代码尚未发布,但我认为您还有另一个删除游戏或将其设置为nullptr的地方