[转] boost库的Singleton的实现以及static成员的初始化问题
http://www.cnblogs.com/kex1n/archive/2011/04/05/2006194.html
effectie c++的条款4中提到:
(global对象,定义在namespace内的对象,class内的static对象,函数内的static对象,file作用域内的 static对象)统称为static对象。其中函数内的static对象又叫local static object, 其他的叫non-local static object。
non-local static object的初始化顺序是没有定义的,local static object在函数第一次调用时构造初始化。
还有:non-local static object会在main函数之前被初始化。
#pragma once
#include <iostream>
using namespace std;
class Foo
{
public:
Foo()
{
cout<<"Foo create!"<<endl;
}
};
class Test
{
public:
Test() {}
Foo GetX() const{ return x_;}
private:
static Foo x_;
};
Foo Test::x_;
即使在main函数中未初始化Test对象,仍会看到Foo Create的提示,所以non-local static object在main函数之前初始化的。
普通的singleton模式:
#pragma once
template<typename T>
class Singleton_
{
public:
static T&Instance()
{
static T t_;
return t_;
}
private:
Singleton_() {}
};
多线程的时候此方法不给力,可以用加锁的办法,参见ACE实现的双重加锁优化的singleton实现。或要求使用者在main的早期或多线程环境之前把所有单件各调用一次instance()
由于non-local static object是在main之前初始化的,默认进入main函数之前只有主线程运行,则有如下写法
#pragma once
template<typename T>
class Singleton_
{
public:
static T&Instance()
{
return t_;
}
private:
Singleton_() {}
static T t_;
};
template <typename T> T Singleton_<T>::t_;
这样实现的问题是,无法预知对象的生成的顺序,如果多个单件对象有初始化次序要求会出现问题,比如一个单件构造函数中会调用另一个单件的instance(),而那个单件还没有构造。
下面看boost的singleton实现:
class Widget
{
public:
Widget()
{
cout<<"Widget Creat"<<endl;
}
};
template <typename T>
struct Singleton
{
private:
struct object_creator
{
object_creator()
{
Singleton<T>::instance();
}
inline void do_nothing()const
{}
};
static object_creator create_object;
Singleton () {}
public:
typedef T object_type;
static object_type& instance()
{
static object_type obj;
create_object.do_nothing();
return obj;
}
};
//声明一个全局变量template <typename T> Singleton<T>::create_object
typename Singleton<T>::object_creator Singleton<T>::create_object;
int main()
{
Widget& w = Singleton<Widget>::instance();
return 0;
}
没有使用锁机制,而是充分利用了C++的语言特性较好的解决了多线程情况下使用singleton的问题。
boost的singleton的实现基于以下假设:良好的设计在进入main函数之前应该是单线程的。
我们可以使用全局变量的方式来设计singleton,并且保证在使用该singleton之前其已经被正确的初始化。
在进入main之前,唯一的主线程开始构造Singleton<T>::create_object,在其构造函数之内调用
Singleton的instance函数,并在该函数内生成Singleton对象,至于函数donoting(),去掉之后照样可以通过编译,我想原
因可能是为了再次保证singleton的初始化完全成功。
[转] boost库的Singleton的实现以及static成员的初始化问题的更多相关文章
- (七)boost库之单例类
(七)boost库之单例类 一.boost.serialzation的单件实现 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一 ...
- 新手,Visual Studio 2015 配置Boost库,如何编译和选择,遇到无法打开文件“libboost_thread-vc140-mt-gd-1_63.lib“的解决办法
1,到官网下载最新的boost,www.boost.org 这里我下载的1-63版本. 2,安装,解压后运行bootstrap.bat文件.稍等一小会就OK. 3,编译boost库.注意一定要使用VS ...
- vs2013给项目统一配置boost库
1.打开项目,然后点击菜单中的 视图->其他窗口->属性管理器 2. 打开属性管理器,点击项目前的箭头,展开项目,找到debug或者release下面的Microsoft.Cpp.Win3 ...
- [C/C++] C/C++延伸学习系列之STL及Boost库概述
想要彻底搞懂C++是很难的,或许是不太现实的.但是不积硅步,无以至千里,所以抽时间来坚持学习一点,总结一点,多多锻炼几次,相信总有一天我们会变得"了解"C++. 1. C++标准库 ...
- dev c++ Boost库的安装
dev c++ 的boost库的安装步骤 然后点击“check for updates”按钮 最后点击“Download selected”按钮,下载完成后安装.... 给dev添加boost库文件, ...
- vs配置boost库
步骤: 1.在boost官网下载boost版本,以1.59.0为例. 2.解压,解压后可看到文件夹下有个bootstrap.bat文件. 注意: 如果有以下error: 'cl' 不是内部或外部命令, ...
- windows下安装boost库
工作中现在会接触boost,所以我计划两个月之内努力熟悉一下boost.今天在自己win10系统上尝试安装了boost库,下面把遇到的问题总结一下: 1. 下好1.61版本库,在boost目录下运行b ...
- ubuntu 下安装boost库
ubuntu下安装boost库,,在网上试了一些其他人推荐的libboost-dev 但是会缺少,编译程序会报错: /usr/bin/ld: cannot find -lboost_serializa ...
- linux下编译安装boost库
linux下编译安装boost库 linux下编译安装boost库 1.下载并解压boost 1.58 源代码 下载 解压 2.运行bootstrap.sh 3.使用b2进行构建 构建成功的提示 4. ...
随机推荐
- JQUERY1.9学习笔记 之属性选择器(一) 前缀选择器
描述:选择指定属性值的元素,或者是以字符串开始其后跟随“-”符号的. jQuery( "[attribute|='value']" ) 例:查找出所有语言属性为en的链接. < ...
- jQuery 元素移除empty() remove()与detach()的区别?
@1.empty() 删除匹配元素集合中所有的后代字节点元素: <p>hello<span>world</span></p> $("p&quo ...
- Binding在WPF中的使用
闲来无事,不想打DOTA,在这里小小研究下wpf中关于Binding的东西. 咯咯 在我们印象中,Binding的意思是“绑定”,这个“绑”大概取自于Bind这个单词吧,这么理解的话就是以音译英了,没 ...
- 使用C语言获取当前系统的时间
要想使用C语言来获取当前系统的时间,办法如下: 需要提前准备的工作: #include <stdio.h> #include <time.h> #include <std ...
- 三种常见字符编码简介:ASCII、Unicode和UTF-8
什么是字符编码? 计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是255( ...
- Node.js包(JXcore)
Node.js的代码是开放的,并准备好被复制像任何其他Javascript代码.但现在它不可能的了.JXcore 这是一个开源项目,引入了包装和源文件和其他资源加密成JX包一个独特的功能. 考虑大型项 ...
- OTP语音芯片和掩模语音芯片(mask)的区别
OTP(One Time Programable)是MCU的一种存储器类型,意思是一次性可编程:程序烧入IC后,将不可再次更改和:因此OTP语音芯片就是指一次性烧录的语音IC. 从OTP定义上来看,只 ...
- MySQL使用rand函数实现随机数
sql 的随机函数newID()和RAND() sql server的随机函数newID()和RAND() SELECT * FROM Northwind..Orders ORDER BY NEWID ...
- UVA-10735 - Euler Circuit(混合欧拉回路输出)
题意:给你一个图,有N个点,M条边,这M条边有的是单向的,有的是双向的. 问你能否找出一条欧拉回路,使得每条边都只经过一次! 分析: 下面转自别人的题解: 把该图的无向边随便定向,然后计算每个点的入度 ...
- 搜索(DLX): POJ 3074 3076 Sudoku
POJ 3074 : Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller ...