打赏

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 
}  

参考

posted @ 2022-03-18 10:51  idoe  阅读(23)  评论(0编辑  收藏  举报