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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Singleton类无法找到ctor,但编译,运行并保留实例未初始化相关的知识,希望对你有一定的参考价值。

我在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 << "
"; //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的选定构造函数。

答案

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

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

以上是关于Singleton类无法找到ctor,但编译,运行并保留实例未初始化的主要内容,如果未能解决你的问题,请参考以下文章

Singleton 类 DataLoader - 在 AppDelegate 中从 Core Data 设置值,但无法访问其他类中的 DataLoader 变量

std::any 用于仅移动模板,其中 copy-ctor 内的 static_assert 等于编译错误,但为啥呢?

依赖项没有复制 ctor 或赋值运算符时的 C++ 初始化程序列表

effectiveJava强化Singleton属性

编译器如何从delete-default-ctor lambda生成一个闭包?

单例模式-Singleton