从零开始学C++之对象的使用(三):static 与单例模式、auto_ptr与单例模式、const 用法小结、mutable修饰符
2015-03-04 23:06
507 查看
转:/article/1350629.html
一、static 与单例模式
单例模式也就是简单的一种设计模式,它需要:
保证一个类只有一个实例,并提供一个全局访问点
禁止拷贝
C++ Code
上述程序虽然调用了两个GetInstance函数,但只调用一次构造函数,即创建一个对象。将赋值运算符和拷贝构造函数声明为私有,禁止拷贝。但程序存在一个问题就是对象生存期到时不会被析构。
为了解决对象不会被析构的问题,可以使用一个静态的嵌套类对象来解决:
C++ Code
利用静态嵌套对象的确定性析构会调用Garbo类的析构函数,在析构函数内delete 单例类的指针。
上面办法比较繁琐,也可以返回局部静态对象的引用来解决:
C++ Code
局部静态对象只会初始化一次,所以调用多次GetInstance函数得到的是同一个对象。由于函数内使用了静态对象,故不是线程安全的。实际上也可以使用auto_ptr 智能指针 来解决,程序如下,更详细的对auto_ptr 的讨论参见这里。
C++ Code
实际上,上述所有的单例模式例子都不是线程安全的,设想如果两个线程同时运行到语句if (instance
== null),而此时该实例的确没有创建,那么两个线程都会创建一个实例。如果不希望加锁实现线程安全,可以使用饿汉模式(即在main函数之前先生成一个实例):
或者通过加锁方式实现,请参考这里。
二、const成员函数、const 对象、mutable修饰符
(一)、const 成员函数
const成员函数不会修改对象的状态
const成员函数只能访问数据成员的值,而不能修改它
(二)、const 对象
如果把一个对象指定为const,就是告诉编译器不要修改它
const对象的定义:
const 类名 对象名(参数表);
const对象不能调用非const成员函数
用mutable修饰的数据成员即使在const对象或在const成员函数中都可以被修改。
C++ Code
三、const 用法总结
可以对const 的用法做个小总结:
参考:
C++ primer 第四版
Effective C++ 3rd
C++编程规范
一、static 与单例模式
单例模式也就是简单的一种设计模式,它需要:
保证一个类只有一个实例,并提供一个全局访问点
禁止拷贝
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | #include <iostream> using namespace std; class Singleton { public: static Singleton *GetInstance() { if (instance_ == NULL) { instance_ = new Singleton; } return instance_; } ~Singleton() { cout << "~Singleton ..." << endl; } private: Singleton(const Singleton &other); Singleton &operator=(const Singleton &other); Singleton() { cout << "Singleton ..." << endl; } static Singleton *instance_; }; Singleton *Singleton::instance_; int main(void) { //Singleton s1; //Singleton s2; Singleton *s1 = Singleton::GetInstance(); Singleton *s2 = Singleton::GetInstance(); //Singleton s3(*s1); // 调用拷贝构造函数 return 0; } |
为了解决对象不会被析构的问题,可以使用一个静态的嵌套类对象来解决:
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | #include <iostream> using namespace std; class Singleton { public: static Singleton *GetInstance() { if (instance_ == NULL) { instance_ = new Singleton; } return instance_; } ~Singleton() { cout << "~Singleton ..." << endl; } //static void Free() //{ // if (instance_ != NULL) // { // delete instance_; // } //} class Garbo { public: ~Garbo() { if (Singleton::instance_ != NULL) { delete instance_; } } }; private: Singleton(const Singleton &other); Singleton &operator=(const Singleton &other); Singleton() { cout << "Singleton ..." << endl; } static Singleton *instance_; static Garbo garbo_; // 利用对象的确定性析构 }; Singleton::Garbo Singleton::garbo_; Singleton *Singleton::instance_; int main(void) { //Singleton s1; //Singleton s2; Singleton *s1 = Singleton::GetInstance(); Singleton *s2 = Singleton::GetInstance(); //Singleton s3(*s1); // 调用拷贝构造函数 return 0; } |
上面办法比较繁琐,也可以返回局部静态对象的引用来解决:
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #include <iostream> using namespace std; class Singleton { public: static Singleton &GetInstance() { static Singleton instance; // 局部静态对象 return instance; } ~Singleton() { cout << "~Singleton ..." << endl; } private: Singleton(const Singleton &other); Singleton &operator=(const Singleton &other); Singleton() { cout << "Singleton ..." << endl; } }; int main(void) { Singleton &s1 = Singleton::GetInstance(); Singleton &s2 = Singleton::GetInstance(); return 0; } |
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #include <iostream> #include<memory> using namespace std; class Singleton { public: static Singleton *GetInstance() { if (instance_.get() == NULL) { instance_ = auto_ptr<Singleton>(new Singleton); } return instance_.get(); } ~Singleton() { cout << "~Singleton ..." << endl; } private: Singleton(const Singleton &other); Singleton &operator=(const Singleton &other); Singleton() { cout << "Singleton ..." << endl; } static auto_ptr<Singleton> instance_; }; auto_ptr<Singleton> Singleton::instance_; int main(void) { //Singleton s1; //Singleton s2; Singleton *s1 = Singleton::GetInstance(); Singleton *s2 = Singleton::GetInstance(); //Singleton s3(*s1); // 调用拷贝构造函数 return 0; } |
== null),而此时该实例的确没有创建,那么两个线程都会创建一个实例。如果不希望加锁实现线程安全,可以使用饿汉模式(即在main函数之前先生成一个实例):
或者通过加锁方式实现,请参考这里。
二、const成员函数、const 对象、mutable修饰符
(一)、const 成员函数
const成员函数不会修改对象的状态
const成员函数只能访问数据成员的值,而不能修改它
(二)、const 对象
如果把一个对象指定为const,就是告诉编译器不要修改它
const对象的定义:
const 类名 对象名(参数表);
const对象不能调用非const成员函数
用mutable修饰的数据成员即使在const对象或在const成员函数中都可以被修改。
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #include <iostream> using namespace std; class Test { public: Test(int x) : x_(x), outputTimes_(0) { } int GetX() const { cout << "const GetX ..." << endl; //x_ = 100; return x_; } int GetX() { cout << "GetX ..." << endl; return x_; } void Output() const { cout << "x=" << x_ << endl; outputTimes_++; } int GetOutputTimes() const { return outputTimes_; } private: int x_; mutable int outputTimes_; }; int main(void) { const Test t(10); t.GetX(); Test t2(20); t2.GetX(); t.Output(); t.Output(); cout << t.GetOutputTimes() << endl; return 0; } |
三、const 用法总结
可以对const 的用法做个小总结:
参考:
C++ primer 第四版
Effective C++ 3rd
C++编程规范
相关文章推荐
- 从零开始学C++之对象的使用(三):static 与单例模式、auto_ptr与单例模式、const 用法小结、mutable修饰符
- 从零开始学C++之对象的使用(三):static 与单例模式、auto_ptr与单例模式、const 用法小结、mutable修饰符
- static 与单例模式、auto_ptr与单例模式、const 用法小结、mutable修饰符
- 从零开始学C++之对象的使用(二):四种对象生存期和作用域、static 用法总结
- 十三、对象的使用(二)四种对象的作用域与生存期、static用法总结、static与单例模式
- auto_ptr、shared_ptr、weak_ptr、scoped_ptr用法小结
- 从零开始学C++之对象的使用(二):四种对象生存期和作用域、static 用法总结
- static,const,extern,auto的区别和用法
- 宏、const、static、extern、用法与使用场景
- 黑马程序员_Java基础_面向对象(Static的使用、对象初始化和调用成员过程、单例设计模式)
- 【c++笔记七】教你使用"const类型的对象、成员函数"和"static类型的成员函数、变量"
- auto_ptr、shared_ptr、weak_ptr、scoped_ptr用法小结
- auto_ptr、shared_ptr、weak_ptr、scoped_ptr用法小结
- 从零开始学C++之对象的使用(二):四种对象生存期和作用域、static 用法总结
- auto_ptr、shared_ptr、weak_ptr、scoped_ptr用法小结
- php面向对象全攻略 (十) final static const关键字的使用
- 对象类static用法小结
- auto_ptr、shared_ptr、weak_ptr、scoped_ptr用法小结
- C++中static_cast, dynamic_cast, const_cast用法/使用情况及区别解析
- auto_ptr、shared_ptr、weak_ptr、scoped_ptr用法小结