C++ 使用单例初始化程序

C++ 使用单例初始化程序,c++,design-patterns,singleton,C++,Design Patterns,Singleton,我读过多篇关于为什么单身不好的文章。 我知道它很少有像日志记录这样的用途,但是初始化和去初始化呢。 这样做有什么问题吗? 我有一个脚本引擎,需要在启动时绑定到库。 图书馆没有main,那么我应该使用什么呢? 正则函数或单例函数。 是否可以以某种方式复制此对象: class { public: static void initialize(); static void deinitialize(); } bootstrap; 如果没有,为什么人们要隐藏复制ctor、赋值运算符和c

我读过多篇关于为什么单身不好的文章。 我知道它很少有像日志记录这样的用途,但是初始化和去初始化呢。 这样做有什么问题吗? 我有一个脚本引擎,需要在启动时绑定到库。 图书馆没有main,那么我应该使用什么呢? 正则函数或单例函数。 是否可以以某种方式复制此对象:

class
{
public:
   static void initialize();
   static void deinitialize();

}  bootstrap;

如果没有,为什么人们要隐藏复制ctor、赋值运算符和ctor?

单例的目的是在您的系统中只有一个特定类的实例。 C'tor、D'tor和CC'tor是隐藏的,以便有一个单一的接入点来接收唯一的现有实例

通常情况下,实例是静态的,也可以在堆上分配,并且是私有的,还有一个静态方法,通常称为GetInstance,它返回对该实例的引用

在决定是否使用单例时,您应该问自己的问题是:我真的需要强制使用这个类的一个对象吗

还有一个继承问题——如果你打算从单身汉那里继承遗产,这会使事情变得复杂

另一个问题是网络上充斥着关于这个问题的文章

在某些情况下,最好是静态保存您的私有数据,而不是单独保存,这一切都取决于域

但是请注意,如果您是多线程的,静态变量可能会让您在XXX中感到痛苦

因此,在决定要使用的设计模式之前,您应该仔细分析您的问题

在您的例子中,我认为您不需要单例,因为您希望在开始时初始化库,但这与强制只拥有一个类实例无关。如果您只想确保只初始化一次静态标志static bool Initialized,那么您可以只保留一个静态标志static bool Initialized


只调用一次方法不足以产生一个单例。

单例的目的是在系统中只有一个特定类的实例。 C'tor、D'tor和CC'tor是隐藏的,以便有一个单一的接入点来接收唯一的现有实例

通常情况下,实例是静态的,也可以在堆上分配,并且是私有的,还有一个静态方法,通常称为GetInstance,它返回对该实例的引用

在决定是否使用单例时,您应该问自己的问题是:我真的需要强制使用这个类的一个对象吗

还有一个继承问题——如果你打算从单身汉那里继承遗产,这会使事情变得复杂

另一个问题是网络上充斥着关于这个问题的文章

在某些情况下,最好是静态保存您的私有数据,而不是单独保存,这一切都取决于域

但是请注意,如果您是多线程的,静态变量可能会让您在XXX中感到痛苦

因此,在决定要使用的设计模式之前,您应该仔细分析您的问题

在您的例子中,我认为您不需要单例,因为您希望在开始时初始化库,但这与强制只拥有一个类实例无关。如果您只想确保只初始化一次静态标志static bool Initialized,那么您可以只保留一个静态标志static bool Initialized


只调用一次方法不足以产生一个单例。

最好为库提供一个接口,以便多个模块或线程可以同时使用它们。如果在加载模块时确实需要运行一些代码,则使用Singleton来初始化必须初始化一次的部分。

最好为库提供一个接口,以便多个模块或线程可以同时使用它们。如果你真的需要在加载模块时运行一些代码,那么使用单件来初始化必须init的部分。C++中的

< p>库有一种更简单的方式来执行初始化和清理。这和你做其他事情的方式完全一样。拉伊

将需要初始化的所有内容包装在类中,并在构造函数中执行其初始化。瞧,问题解决了

单身人士的所有常见问题仍然适用:

您将需要不止一个实例,即使您没有计划。如果没有其他内容,那么在单元测试时您将需要它。每个测试都应该从头开始初始化库,以便它在干净的环境中运行。单例方法很难做到这一点。 一旦这些单身汉开始互相引用,你就完蛋了。因为实际的初始化顺序是不可见的,所以很快就会得到一堆循环引用,从而导致访问未初始化的单例、堆栈溢出、死锁或其他有趣的错误,如果您不沉迷于使所有内容都全局化,这些错误可能会在编译时被捕获。 多思 阅读强制所有线程共享一个类的同一个实例通常是一个坏主意,因为这会强制该类锁定并同步所有内容,这会降低性能,并可能导致死锁。 意大利面代码。每次使用单实例或全局实例时,都会隐藏代码的依赖项。函数所依赖的对象不再明确,因为并非所有对象都作为参数可见。而且,由于不需要将它们作为参数添加,因此很容易添加的依赖项远远超过需要的数量。这就是为什么一旦你有了单身汉,他们几乎不可能被移除。
< C++中的库有一个更简单的方式来执行初始化和清理。这和你做其他事情的方式完全一样。拉伊

将需要初始化的所有内容包装在类中,并在构造函数中执行其初始化。瞧,问题解决了

单身人士的所有常见问题仍然适用:

您将需要不止一个实例,即使您没有计划。如果没有其他内容,那么在单元测试时您将需要它。每个测试都应该从头开始初始化库,以便它在干净的环境中运行。单例方法很难做到这一点。 一旦这些单身汉开始互相引用,你就完蛋了。因为实际的初始化顺序是不可见的,所以很快就会得到一堆循环引用,从而导致访问未初始化的单例、堆栈溢出、死锁或其他有趣的错误,如果您不沉迷于使所有内容都全局化,这些错误可能会在编译时被捕获。 多线程。强制所有线程共享一个类的同一个实例通常是一个坏主意,因为这会强制该类锁定并同步所有内容,这会降低性能,并可能导致死锁。 意大利面代码。每次使用单实例或全局实例时,都会隐藏代码的依赖项。函数所依赖的对象不再明确,因为并非所有对象都作为参数可见。而且,由于不需要将它们作为参数添加,因此很容易添加的依赖项远远超过需要的数量。这就是为什么一旦你有了单身汉,他们几乎不可能被移除。
计算设计中的单例数,并将此数字称为's'

计算设计中的线程数,并将此数字称为“t”

现在,将t提高到s次方;这大概是调试结果代码时可能丢失的头发数


我个人曾经遇到过这样的代码:有50多个单例,10个不同的线程,所有线程都在竞相访问。getInstance first

计算设计中的单例数,并将此数称为's'

计算设计中的线程数,并将此数字称为“t”

现在,将t提高到s次方;这大概是调试结果代码时可能丢失的头发数


我个人遇到过50多个单例代码,10个不同的线程都在争先恐后地运行。getInstance first

你有没有问过这样的问题,比如如何定义一组范围有限的几乎全局的变量,并强制在实际使用这些数据集之前始终执行初始化函数?不需要变量。仅执行将库绑定到脚本引擎的函数。是的,可以复制对象,但如果这样做,则不会发生任何事情。人们隐藏复制运算符和赋值运算符,以防止被复制。什么意思,不需要变量?您希望执行绑定,并且该绑定必须作为状态存储在函数可以操作的位置。是否有可能需要两个脚本语言实例,例如,一个是功能齐全的interp,可以访问文件系统,第二个是用于运行不受信任的代码,功能减少。你能用单例来做这个吗?@jalf:变量存储在脚本引擎中。我根本不处理他们。我只需要调用将类绑定到脚本的函数。你能告诉我怎么复印吗@TokenMacGuy:两者的答案都是否定的。你有没有问过这样的问题,比如我如何定义一组范围有限的几乎全局的变量,并在实际使用这些数据集之前强制执行初始化函数?不需要变量。仅执行将库绑定到脚本引擎的函数。是的,可以复制对象,但如果这样做,则不会发生任何事情。人们隐藏复制运算符和赋值运算符,以防止被复制。什么意思,不需要变量?您希望执行绑定,并且该绑定必须作为状态存储在函数可以操作的地方。您是否可能希望有两个脚本语言实例,例如一个是具有访问文件系统的全功能interp,另一个是用于运行不真实的脚本语言
ted代码并减少了功能。你能用单例来做这个吗?@jalf:变量存储在脚本引擎中。我根本不处理他们。我只需要调用将类绑定到脚本的函数。你能告诉我怎么复印吗@TokenMacGuy:两种方法的答案都是否定的。您提供的代码不是单例代码,因为它不足以将两个方法声明为静态。您必须在静态方法中创建实例,并将其隐藏为私有,当然,还必须让此静态方法返回此实例。您还需要将C'tor、CC'tor和D'tor设置为私有,以防止用户创建多个实例或删除实例。请检查:有关详细信息,您提供的代码不是单例代码,因为它不足以将两个方法声明为静态。您必须在静态方法中创建实例,并将其隐藏为私有,当然,还必须让此静态方法返回此实例。您还需要将C'tor、CC'tor和D'tor设置为私有,以防止用户创建多个实例或删除实例。请检查:详情好主意。我不确定我能做到。原因是我需要一次加载所有资源,即使我不使用它们。那么?让用户创建一个代表整个库的主对象。该对象在构造时加载所有资源,无论它们是否被使用。所有库函数都在该对象上运行,当该对象超出范围时,整个库将被卸载。好主意。我不确定我能做到。原因是我需要一次加载所有资源,即使我不使用它们。那么?让用户创建一个代表整个库的主对象。该对象在构造时加载所有资源,无论它们是否被使用。所有库函数都在该对象上运行,当该对象超出范围时,将卸载整个库。