Singleton类无法找到ctor,但编译,运行并且未初始化实例(Singleton class can't find ctor but compiles, runs, and leave

编程入门 行业动态 更新时间:2024-10-27 20:34:10
Singleton类无法找到ctor,但编译,运行并且未初始化实例(Singleton class can't find ctor but compiles, runs, and leaves instance uninitialized)

我在MSVC ++ 17 15.5.5版本中实现单例模式时遇到了问题。 我正在用flag /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;

这种实现的一个目标是具有某种形式的延迟初始化,但没有每次调用getInstance()时都会执行的冗余if语句。 只有第一次是有用的,因为实例需要被初始化,但在那之后, if只是开销。 为此,我创建了函数initInstance() ,您必须在调用getInstance()之前调用函数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选中的构造函数被调用。

I am having trouble with my implementation of the singleton pattern in MSVC++ 17 version 15.5.5. I am compiling with the flag /std:c++17.

My implementation consists of the following helper class:

#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;

One aim of this implementation is to have some form of lazy initialization but without the redundant if statement that gets executed every time getInstance() is called. Only the very first time would be useful because the instance would need to be initialized but after that the if is just overhead. To do this, I created the function initInstance() that you will have to call before being able to call getInstance(). I am well aware that the assert()'s only work in debug mode but this is fine for my project.

The class is intended to be used in the following way:

#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; }

The problem:

If I call Singleton<Foo>::initInstance(); without any arguments, even though Foo has no default constructor, the code still compiles and runs. I would have expected that instantiating the constructor of Singleton<Foo> would fail because it calls Foo's constructor with the arguments given but upon lookup it shouldn't be able to find an appropriate constructor. Yet the code compiles somehow.

When I execute the code the constructor of Singleton<Foo> is called but the constructor of Foo itself isn't. When I stop execution at a breakpoint just after instance has been initialized and inspect the value of its datamember i it is some random huge negative value indicating that simply no code was executed to initialize the instance of Foo.

This only happens when there is no appropriate constructor of Foo to call. When there is, everything works fine and Foo's selected constructor is called.

最满意答案

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

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

As suggested in the comments this is probably a compiler bug. I submitted a bug report.

I also submitted a bug report for the internal compiler error that I encountered as I described in the comments. The internal compiler error happens when I (incorrectly) put using T::T; in Singleton<T>::InitInstance() and then call Ts constructor.

更多推荐

本文发布于:2023-07-07 15:30:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1065212.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:初始化   实例   且未   class   ctor

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!