C++InterViewCode
@
前言
这里就存储一些代码型的面试题,防止出一些现场手写的问题。
正文
1. 单例模式
其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。单例模式分为懒汉式和饿汉式。
懒汉式是在指系统运行中,实例并不存在,只有当需要该实例时,才创建该实例。但注意,懒汉式并不是线程安全的,若要达到线程安全,则一个进行加锁。
懒汉式
#include <iostream>
#include <mutex>
#include <pthread.h>
using namespace std;
classs SignleInstance
{
public:
//获取单例对象
static SingleInstance *GetInstance();
//释放单例,进程退出时调用
static void deleteInstance();
//打印单例地址
void Print();
private:
//将其构造和析构函数都变成私有的,精致外部构造和析构
SingleInstance();
~SingleInstance();
//将拷贝构造和赋值构造成为私有函数,禁止外部拷贝和赋值
SingleInstance(const SingleInstance &signal);//拷贝构造
const SingleInstance &operator(const SingleInstance &signal);//const 防止对实参的意外修改
//使用引用的原因
// 因为实参是通过按值传递机制传递的。在可以传递对象cigar之前,编译器需要安排创建该对象的副本。因此,编译器为了处理复制构造函数的这条调用语句,需要调用复制构造函数来创建实参的副本。但是,由于是按值传递,第二次调用同样需要创建实参的副本,因此还得调用复制构造函数,就这样持续不休。最终得到的是对复制构造函数的无穷调用。(其实就是创建副本也是需要调用复制构造函数的)
//所以解决办法先是要将形参改为引用形参:
private:
//唯一实例对象指针
static SingleInstance *m_SingleInstance;
static mutex m_Mutex;
};
//初始化静态成员变量
SingleInstance *SingleInstance::m_SingleInstance = NULL;
mutex SingeInstance::m_Mutex;
SingleInstance* SingleInstance::GetInstance()
{
//使用双检锁的方式 ,判断对象为空再进行加锁
if(m_SingleInstance ==NULLL)
{
unique_lock<mutex> lock<m_Mutex>;
if(m_SingleInstance ==NULLL)
m_SingleInstance = new (std::nothrow) SingleInstance;//线程并发的话有可能创建多个实例,非线程安全
}
return m_SingleInstance;
}
void SingleInstance::deleteInstance()
{
unique_lock<mutex> lock<m_Mutex>
if(m_SingleInstance)
{
delete m_SingleInstance;
m_SingleInsance = NULL;//若没有置空,容易出现野指针。
}
}
void SingleInstance::Print()
{
std::cout<<"我的实例内存地址是"<<this<<std::endl;
}
SingleInstance::SingleInstance()
{
std::cout << "构造函数" << std::endl;
}
SingleInstance::~SingleInstance()
{
std::cout << "析构函数" << std::endl;
}
//普通懒汉式实现---线程不安全
void *PrintHello(void *threadid)
{
}
int main(void)
{
pthread_t threads[NUM_THREADS] = {0};
int indexes[NUM_THREADS] = {0}; // 用数组来保存i的值
int ret = 0;
int i = 0;
std::cout << "main() : 开始 ... " << std::endl;
for (i = 0; i < NUM_THREADS; i++)
{
std::cout << "main() : 创建线程:[" << i << "]" << std::endl;
indexes[i] = i; //先保存i的值
// 传入的时候必须强制转换为void* 类型,即无类型指针
ret = pthread_create(&threads[i], NULL, PrintHello, (void *)&(indexes[i]));
if (ret)
{
std::cout << "Error:无法创建线程," << ret << std::endl;
exit(-1);
}
}
// 手动释放单实例的资源
SingleInstance::deleteInstance();
std::cout << "main() : 结束! " << std::endl;
return 0;
}
饿汉式
//初始化静态成员变量
#if 0 懒汉模式
SingleInstance *SingleInstance::m_SingleInstance = NULL;
#endif
#if 0 饿汉模式
SingleInstance *SingleInstance::m_SingleInstance = new(nothrow) SingleInstance;
#endif
mutex SingeInstance::m_Mutex;
SingleInstance* SingleInstance::GetInstance()
{
#if 0 懒汉模式
//使用双检锁的方式 ,判断对象为空再进行加锁
if(m_SingleInstance ==NULLL)
{
unique_lock<mutex> lock<m_Mutex>;
if(m_SingleInstance ==NULLL)
m_SingleInstance = new (std::nothrow) SingleInstance;//线程并发的话有可能创建多个实例,非线程安全
}
#endif
#if 0 饿汉模式
return m_SingleInstance;//get方法,就直接返回即可。
#endif
}
参考
当你在凝视深渊时,深渊也在凝视你。