计算机系统应用教程网站

网站首页 > 技术文章 正文

C++核心准则边译边学-I.3 避免单例

btikc 2024-09-24 08:08:10 技术文章 17 ℃ 0 评论

I.3: Avoid singletons(避免单例)

Reason(原因)

Singletons are basically complicated global objects in disguise.

单例基本上就是一个复杂的全局对象的伪装。

Example(示例)

class Singleton {
 // ... lots of stuff to ensure that only one Singleton object is created,
 // that it is initialized properly, etc.
};

There are many variants of the singleton idea. That's part of the problem.
存在许多单例想法的版本。这是问题的一个方面。

Note(注意)

If you don't want a global object to change, declare it const or constexpr.

如果你不希望全局对象发生改变,将其定义为常量或常量表达式。

译者注:常量表达式请参考https://mp.weixin.qq.com/s/Y_pEIVO8H6u-fpPczJU5Mw

Exception(例外)

You can use the simplest "singleton" (so simple that it is often not considered a singleton) to get initialization on first use, if any:

你可以使用最简单的“单例”(简单到经常不被认为是单例)以便在第一次使用时获取初始值。

X& myX()
{
 static X my_x {3};
 return my_x;
}

This is one of the most effective solutions to problems related to initialization order. In a multi-threaded environment, the initialization of the static object does not introduce a race condition (unless you carelessly access a shared object from within its constructor).

这是解决初始化顺序相关问题的最有效手段。在多线程环境中,静态对象的的初始化不会触发竞争条件(除非你不小心在某个共享对象的构造函数中访问了它)

译者注:这也是目前单例设计模式在现代C++中最新实现。

Note that the initialization of a local static does not imply a race condition. However, if the destruction of X involves an operation that needs to be synchronized we must use a less simple solution. For example:

注意局部的静态变量不包含竞争条件。然而,如果X的析构动作牵涉到需要被同步的操作,我们必须使用一个次简单的解决方案。例如:

X& myX()
{
 static auto p = new X {3};
 return *p; // potential leak
}

Now someone must delete that object in some suitably thread-safe way. That's error-prone, so we don't use that technique unless

现在某个角色必须以一种合适的线程安全的方式删除那个对象。由于容易引发错误,因此我们不会使用这个技术,除非

  • myX is in multi-threaded code,myX就在多线程代码中
  • that X object needs to be destroyed (e.g., because it releases a resource), andX对象需要被销毁(例如,因为它释放资源)
  • X's destructor's code needs to be synchronized.X的析构函数的代码需要被同步。

译者注:函数内部构建的静态对象在程序退出时会被自动析构,如果希望自己控制析构的时机就只能动态构建对象以避开自动析构。

If you, as many do, define a singleton as a class for which only one object is created, functions like myX are not singletons, and this useful technique is not an exception to the no-singleton rule.

如果你像很多人一样为只创建一个的对象定义单例类,像myX那样的函数没有使用单例,这个有用的技术也不是禁止单例规格的例外。

译者注:做个做法不是单例,也就不会违反禁止单例的规则。

Enforcement(实施建议)

Very hard in general.

通常会十分困难。

  • Look for classes with names that include singleton.

找到名称中包含singletong的类。

  • Look for classes for which only a single object is created (by counting objects or by examining constructors).

找到只创建一个对象的类(通过对对象计数或检查(监控)构造函数)

  • If a class X has a public static function that contains a function-local static of the class' type X and returns a pointer or reference to it, ban that.

如果类X有一个公开的静态函数,在其内部存在一个类型为X、作用域为该函数范围的局部静态变量并返回这个变量的指针或引用时,禁止它。


觉得本文有帮助?请分享给更多人。

更多更新文章,欢迎关注微信公众号【面向对象思考】

面向对象设计,面向对象编程,面向对象思考!

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表