static与单例模式
单例模式保证一个类只有一个实例,并提供一个全局访问点,禁止拷贝
#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;
}
上述程序虽然调用了两个GetInstance函数,但只调用一次构造函数,即创建一个对象。将赋值运算符和拷贝构造函数声明为私有,禁止拷贝。但程序存在一个问题就是对象生存期到时不会被析构
。
不会被析构的原因在于,delete一个对象
,调用析构函数,释放内存。new出来的对象,若不手动的delete,对应的析构函数也不会被主动调用
。
智能指针
为了解决对象不会被析构的问题,可以使用智能指针。
#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;
}
嵌套类对象
还可以使用一个静态的嵌套类对象来解决:
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton *GetInstance()
{
if (instance_ == NULL)
{
instance_ = new Singleton;
}
return instance_;
}
~Singleton()
{
cout << "~Singleton ..." << endl;
}
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;
}
利用静态嵌套对象的确定性析构会调用Garbo类的析构函数,在析构函数内delete单例类的指针
。
局部静态对象
上面办法比较繁琐,也可以返回局部静态对象的引用来解决:
#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;
}
局部静态对象只会初始化一次
,所以调用多次GetInstance函数得到的是同一个对象。由于函数内使用了静态对象,故不是线程安全的
。
上述所有的单例模式例子都不是线程安全的,设想如果两个线程同时运行到语句if (instance == null),而此时该实例的确没有创建,那么两个线程都会创建一个实例
。如果不希望加锁实现线程安全,可以使用饿汉模式
,即在main函数之前先生成一个实例,或者通过加锁方式
实现
class Singleton
{
public:
static Singleton *GetInstance()
{
return instance_;
}
~Singleton()
{
cout << "~Singleton ..." << endl;
}
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_ = new Singleton;
饿汉模式
const成员函数/const对象/mutable修饰符
const成员函数
const成员函数不会修改对象的状态
,const成员函数只能访问数据成员的值,而不能修改它
const对象
如果把一个对象指定为const,就是告诉编译器不要修改它。
const对象的定义:const 类名 对象名(参数表);
const对象不能调用非const成员函数。
mutable修饰符
用mutable修饰的数据成员
即使在const对象或在const成员函数中都可以被修改
#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 GetX ...
GetX ...
x=10
x=10
2
const用法总结
const常量
const引用
const与指针
const成员与const成员函数
const对象