防止物体被立即销毁

时间:2018-01-15 16:14:57

标签: c++ pointers singleton

我正在尝试创建一个类对象的单个实例,以便只需通过包含标头并调用getInstance()方法的相应形式,使该实例可以被任何其他需要它的类访问。我试图通过遵循显示here的Singleton示例来实现这一点,但由于某种原因,这个单个实例在创建后就会被销毁。

以下是标题文件Window.h

的副本
#pragma once

#include <string>
#include <SDL.h>

class Window {

public:
    static Window* getInstance();
    static Window* getInstance(const std::string &title, int width, int height);
private:
    Window(const std::string &title, int width, int height);
    ~Window();

    bool init();

    std::string _title;
    int _width = 800;
    int _height = 600;

    SDL_Window *_window = nullptr;

    static Window *_instance;
    // static Window _solidInstance;
};

以下是源文件Window.cpp,其中删除了一些不相关的部分以节省空间。

#include "Window.h"
#include <iostream>

Window* Window::instance = 0;
SDL_Renderer *Window::_renderer = nullptr;

Window::Window(const std::string &title, int width, int height) {
    // Code that isn't relevant to this issue
    std::cout << "Window constructor called\n";
}

Window::~Window() {
    // Code that isn't relevant to this issue
    std::cout << "Window destructor called\n";
}

Window* Window::getInstance() {
    return _instance;
}

Window* Window::getInstance(const std::string &title, int width, int height) {
    if (_instance == 0) {
        std::cout << "Just before construction\n";
        _instance = &Window(title, width, height);
        std::cout << "Just after construction\n";
        // _solidInstance = Window(title, width, height);
    }
    return _instance;
}

构建并运行此代码后,将按以下顺序将以下行打印到控制台:

Just before construction
Window constructor called
Window destructor called
Just after construction

这告诉我,在getInstance()甚至有机会返回之前,我创建的Window实例已经被销毁。我不确定如何防止这种情况发生。我已经尝试使用Window的常规实例而不是指向一个(请参阅引用soldInstance的注释掉的代码行)但这只会给我链接器错误。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:7)

您的问题出在此处:_instance = &Window(title, width, height); 您正在获取临时窗口的地址,该窗口在离开范围后会被销毁。

将其更改为:_instance = new Window(title, width, height);

但请务必在退出程序前删除该窗口!

在退出时自动删除窗口的更好的解决方案是:

Window* Window::getInstance(const std::string &title, int width, int height) {
    static Window window{title, width, height};
    return &window;
}

答案 1 :(得分:1)

_instance = &Window(title, width, height);

这会创建一个临时对象并获取其地址。表达式完成后,对象将被销毁,并且您将留下一个悬空指针。

要创建以更持久的方式存储的对象,请使用&#34; new&#34;要从堆中分配的运算符:

_instance = new Window(title, width, height);

小心这种单身方法。例如,你要求一个实例并提供可能使用或不使用的参数。如果尚未创建任何对象,则使用提供的参数创建窗口。但是,如果已经创建了窗口,则忽略提供的参数,您只需获得正常情况。这最终会给某人带来惊喜和愤怒。保证。
问题二,内存管理。在某些时候你应该删除这个指针。也许你可以通过将它存储在unique_ptr中来保存程序关闭,然后你可以用make_unique()分配它,但你应该考虑你做出的任何选择的后果。