Modern C++ Design 笔记 第六章 Implementing Singletons(1)
2008-12-09 11:42
351 查看
#include <iostream>
using namespace std;
/* Place holder for thread synchronization mutex */
class Mutex
{ /* placeholder for code to create, use, and free a mutex */
};
/* Place holder for thread synchronization lock */
class Lock
{ public:
Lock(Mutex& m) : mutex(m) { /* placeholder code to acquire the mutex */ }
~Lock() { /* placeholder code to release the mutex */ }
private:
Mutex & mutex;
};
class Singleton
{ public:
static Singleton* GetInstance();
int a;
private:
Singleton(int _a) : a(_a) { cout << "In Ctor" << endl; }
~Singleton() { cout << "In Dtor" << endl; }
static Mutex mutex;
// Not defined, to prevent copying
Singleton(const Singleton& );
Singleton& operator =(const Singleton& other);
};
Mutex Singleton::mutex;
Singleton* Singleton::GetInstance()
{
Lock lock(mutex);
cout << "Get Inst" << endl;
// Initialized during first access
static Singleton inst(1);
return &inst;
}
int main()
{
Singleton* singleton = Singleton::GetInstance();
cout << "The value of the singleton: " << singleton->a << endl;
return 0;
}
在wikipedia上看到Singleton pattern的描述时偶然看到了一个Singleton的实现,局部的静态变量我们看到很多了。但是这里的mutex让人感觉有点不必要。 感觉static Singleton inst(1);这个语句应该在loading的阶段就已经执行了,所以不存在所谓多线程的问题。但是实际上看了之后还是大吃一惊的。
// Initialized during first access
static Singleton inst(1);
00411F8C mov eax,dword ptr [$S1 (435234h)]
00411F91 and eax,1
00411F94 jne Singleton::GetInstance+0B4h (411FC4h)
00411F96 mov eax,dword ptr [$S1 (435234h)]
00411F9B or eax,1
00411F9E mov dword ptr [$S1 (435234h)],eax
00411FA3 mov byte ptr [ebp-4],1
00411FA7 push 1
00411FA9 mov ecx,offset inst (435230h)
00411FAE call Singleton::Singleton (411799h)
00411FB3 push offset `Singleton::GetInstance'::`2'::`dynamic atexit destructor for 'inst'' (42D370h)
00411FB8 call @ILT+480(_atexit) (4111E5h)
00411FBD add esp,4
00411FC0 mov byte ptr [ebp-4],0
return &inst;
00411FC4 mov dword ptr [ebp-0E0h],offset inst (435230h)
00411FCE mov dword ptr [ebp-4],0FFFFFFFFh
00411FD5 lea ecx,[ebp-14h]
00411FD8 call Lock::~Lock (41178Fh)
00411FDD mov eax,dword ptr [ebp-0E0h]
我们debug这个代码一下,在断点执行到static Singleton inst(1);的时候看到了这样的汇编语句。汇编语句中括号里面的数值是debug时候的地址。可以看到那个JNE,当条件满足的时候可以跳转到411FC4h,也就是 return &inst; 的位置,如果条件不满足就依次执行构造函数和atexit的设置。简单点的说就是,这里的inst是在程序第一次执行到这条语句的时候做初始化的。而不是main函数之前,loading阶段的。这个可能是很常见的问题还是让自己小小的吃惊了一把。既有此,想到了另一个形式变量, 如果我在这个函数里面加入一个static int temp = 1;会怎么样呢?这个是在什么时候分配呢?说干就干,这时候我们看到的汇编语句没有任何的变化。(只是显示这样一条C++的语句)。所以这一类的变量的初始化可以说和刚才的顺序是不同的。所以原书中对局部静态变量有了精彩的论述
int Fun(){ static int x = 100; return ++x;}In this case, x is initialized before any code in the program is executed, most likely at load time. For all that Fun can tell when first called, x has been 100 since time immemorial. In contrast, when the initializer is not a compile-time constant, or the static variable is an object with a constructor, the variable is initialized at runtime during the first pass through its definition.也就是说,局部静态变量如果是基本数据类型,而且赋值语句的右边是编译期常量的话,这个局部变量的初始化实在程序加载期间就完成的。但是如果是那些类的对象(有构造函数)的局部静态变量就是在第一次执行此语句的时候完成初始化的,当然这里还包括基本数据类型的赋值语句右侧是变量的情况。举个例子有这样的函数int Func(int x)
{
static int temp = x*x;
}
可以预见的是这样的temp的初始化是在一次这个函数被调用的时候发生的,不然的话也确实没有办法提前初始化他。有了以上的论述在发现,确实这样一个Mutex还是有存在的必要性的:)
using namespace std;
/* Place holder for thread synchronization mutex */
class Mutex
{ /* placeholder for code to create, use, and free a mutex */
};
/* Place holder for thread synchronization lock */
class Lock
{ public:
Lock(Mutex& m) : mutex(m) { /* placeholder code to acquire the mutex */ }
~Lock() { /* placeholder code to release the mutex */ }
private:
Mutex & mutex;
};
class Singleton
{ public:
static Singleton* GetInstance();
int a;
private:
Singleton(int _a) : a(_a) { cout << "In Ctor" << endl; }
~Singleton() { cout << "In Dtor" << endl; }
static Mutex mutex;
// Not defined, to prevent copying
Singleton(const Singleton& );
Singleton& operator =(const Singleton& other);
};
Mutex Singleton::mutex;
Singleton* Singleton::GetInstance()
{
Lock lock(mutex);
cout << "Get Inst" << endl;
// Initialized during first access
static Singleton inst(1);
return &inst;
}
int main()
{
Singleton* singleton = Singleton::GetInstance();
cout << "The value of the singleton: " << singleton->a << endl;
return 0;
}
在wikipedia上看到Singleton pattern的描述时偶然看到了一个Singleton的实现,局部的静态变量我们看到很多了。但是这里的mutex让人感觉有点不必要。 感觉static Singleton inst(1);这个语句应该在loading的阶段就已经执行了,所以不存在所谓多线程的问题。但是实际上看了之后还是大吃一惊的。
// Initialized during first access
static Singleton inst(1);
00411F8C mov eax,dword ptr [$S1 (435234h)]
00411F91 and eax,1
00411F94 jne Singleton::GetInstance+0B4h (411FC4h)
00411F96 mov eax,dword ptr [$S1 (435234h)]
00411F9B or eax,1
00411F9E mov dword ptr [$S1 (435234h)],eax
00411FA3 mov byte ptr [ebp-4],1
00411FA7 push 1
00411FA9 mov ecx,offset inst (435230h)
00411FAE call Singleton::Singleton (411799h)
00411FB3 push offset `Singleton::GetInstance'::`2'::`dynamic atexit destructor for 'inst'' (42D370h)
00411FB8 call @ILT+480(_atexit) (4111E5h)
00411FBD add esp,4
00411FC0 mov byte ptr [ebp-4],0
return &inst;
00411FC4 mov dword ptr [ebp-0E0h],offset inst (435230h)
00411FCE mov dword ptr [ebp-4],0FFFFFFFFh
00411FD5 lea ecx,[ebp-14h]
00411FD8 call Lock::~Lock (41178Fh)
00411FDD mov eax,dword ptr [ebp-0E0h]
我们debug这个代码一下,在断点执行到static Singleton inst(1);的时候看到了这样的汇编语句。汇编语句中括号里面的数值是debug时候的地址。可以看到那个JNE,当条件满足的时候可以跳转到411FC4h,也就是 return &inst; 的位置,如果条件不满足就依次执行构造函数和atexit的设置。简单点的说就是,这里的inst是在程序第一次执行到这条语句的时候做初始化的。而不是main函数之前,loading阶段的。这个可能是很常见的问题还是让自己小小的吃惊了一把。既有此,想到了另一个形式变量, 如果我在这个函数里面加入一个static int temp = 1;会怎么样呢?这个是在什么时候分配呢?说干就干,这时候我们看到的汇编语句没有任何的变化。(只是显示这样一条C++的语句)。所以这一类的变量的初始化可以说和刚才的顺序是不同的。所以原书中对局部静态变量有了精彩的论述
int Fun(){ static int x = 100; return ++x;}In this case, x is initialized before any code in the program is executed, most likely at load time. For all that Fun can tell when first called, x has been 100 since time immemorial. In contrast, when the initializer is not a compile-time constant, or the static variable is an object with a constructor, the variable is initialized at runtime during the first pass through its definition.也就是说,局部静态变量如果是基本数据类型,而且赋值语句的右边是编译期常量的话,这个局部变量的初始化实在程序加载期间就完成的。但是如果是那些类的对象(有构造函数)的局部静态变量就是在第一次执行此语句的时候完成初始化的,当然这里还包括基本数据类型的赋值语句右侧是变量的情况。举个例子有这样的函数int Func(int x)
{
static int temp = x*x;
}
可以预见的是这样的temp的初始化是在一次这个函数被调用的时候发生的,不然的话也确实没有办法提前初始化他。有了以上的论述在发现,确实这样一个Mutex还是有存在的必要性的:)
相关文章推荐
- Modern C++ Design 笔记 第六章 Implementing Singletons(2)
- Modern C++ Design 笔记 第十一章 MultiMethods(2)
- Modern C++ design 第六章
- Modern C++ Design 学习笔记-第3章
- Modern C++ Design学习笔记:Int2Type, Type2Type, TypeSelect
- modern c++ design Int2Type 笔记
- Modern C++ Design 笔记 第十章 Visitor
- Modern C++ Design 笔记 第十一章 MultiMethods(3)收藏
- Modern C++ Design 笔记 第四章 Small-Object Allocation
- Modern C++ Design 学习笔记之Policy Based Class Design
- [C++] Modern C++ Design(MCD)学习笔记 && 测试代码
- Modern C++ Design 笔记 第八章 Object Factories
- Effective Modern C++ 笔记 第六章 Lambda Expressions
- Modern C++ Design 笔记 第七章 Smart Pointers
- Modern C++ Design 笔记 第九章 Abstract Factory
- Modern C++ Design 笔记 第十一章 MultiMethods(1)
- modern c++ design Int2Type 笔记
- Modern C++ Design 笔记 第一章 Policy-Based Class Design
- Modern C++ Design 学习笔记之Policy Based Class Design
- modern c++ design 笔记(如何列印一个TYPELIST)