Singleton类无法找到ctor,但编译,运行并保留实例未初始化

问题描述 投票:4回答:1

我在MSVC ++ 17版本15.5.5中实现单例模式时遇到问题。我正在用旗帜/std:c++17编译。

我的实现包含以下帮助器类:

#pragma once
#include <cassert>

template<class T>
class Singleton : private T
{
public:
    virtual ~Singleton() = default;

    template<typename ... Targs>
    static T & initInstance(Targs && ... args)
    {
        assert(instance == nullptr);
        instance = new Singleton<T>(std::forward<Targs>(args)...); //The constructor of T might be inaccessible here so let our own ctor call it
        return *instance;
    }

    static T & getInstance()
    {
        assert(instance != nullptr);
        return *instance;
    }

private:
    template<typename ... Targs>
    explicit Singleton(Targs && ... args)
        : T{ std::forward<Targs>(args)... }
    {}

    static T * instance;
};

template<class T>
T * Singleton<T>::instance = nullptr;

这种实现的一个目的是使用某种形式的延迟初始化,但没有每次调用if时执行的冗余getInstance()语句。只有第一次才有用,因为实例需要初始化,但之后if只是开销。为此,我创建了函数initInstance(),在调用getInstance()之前必须调用它。我很清楚assert()只能在调试模式下工作,但这对我的项目来说很好。

该类旨在以下列方式使用:

#include "Singleton.h"
#include <iostream>
class Foo
{
public:
    virtual ~Foo() = default;

protected: //has no public ctor's
    Foo(int i) //has no default ctor
        : i{ i }
    {
        std::cout << "foo ctr " << i << "\n"; //Not printed if no ctor of Foo is found
    }

private:
    int i;
};

int main(int argc, char** argv)
{
    Singleton<Foo>::initInstance(5); //Selects and executes Foo(int i).
    //Singleton<Foo>::initInstance(); //Should not compile, yet it does. Calls no ctor of Foo at all.
    Foo & theOnlyFoo = Singleton<Foo>::getInstance(); //or just use the return value of initInstance(5) to initialize this reference

    //...
    return 0;
}

问题:

如果我在没有任何参数的情况下调用Singleton<Foo>::initInstance();,即使Foo没有默认构造函数,代码仍会编译并运行。我原本预计实例化Singleton<Foo>的构造函数会失败,因为它调用Foo的构造函数给出了参数,但在查找时它不应该找到合适的构造函数。然而代码以某种方式编译。

当我执行代码时,Singleton<Foo>的构造函数被调用,但Foo本身的构造函数不是。当我在instance初始化之后在断点处停止执行并检查其数据库i的值时,它是一个随机的巨大负值,表明没有执行任何代码来初始化Foo的实例。

只有在没有适当的Foo构造函数才能调用时才会发生这种情况。当有,一切正常,并调用Foo的选定构造函数。

c++ visual-c++ singleton
1个回答
0
投票

正如评论中所建议的,这可能是编译器错误。我提交了一份错误报告。

我还提交了我在评论中描述的内部编译器错误的错误报告。当我(错误地)将using T::T;放入Singleton<T>::InitInstance()然后调用Ts构造函数时,会发生内部编译器错误。

© www.soinside.com 2019 - 2024. All rights reserved.