设计一个类,不能被拷贝
bash
#include <iostream>
using namespace std;
// 禁止拷贝的类(标准写法)
class NonCopyable
{
public:
// 1. 构造函数(正常写)
NonCopyable() = default;
// 2. 析构函数(正常写)
~NonCopyable() = default;
// ========== 核心:禁用拷贝 ==========
// 禁用拷贝构造函数
NonCopyable(const NonCopyable&) = delete;
// 禁用赋值运算符重载
NonCopyable& operator=(const NonCopyable&) = delete;
};
继承自他的所有类都不能被拷贝
bash
// 你的业务类,继承 NonCopyable → 自动禁止拷贝
class MyClass : public NonCopyable
{
// 你的代码...
};
- 子类要拷贝 → 必须先拷贝父类
- 父类拷贝构造被 =delete 了
- 子类自动无法生成拷贝函数
设计一个类,只能在堆上创建
bash
#include <iostream>
using namespace std;
class HeapOnly
{
public:
// 提供一个静态接口,专门用来在堆上创建对象
static HeapOnly* createInstance()
{
return new HeapOnly(); // 在堆上创建
}
HeapOnly(const HeapONly& ) = delete;
HeapOnly& operator=(const HeapONly& ) = delete;
// 提供销毁接口(必须手动delete)
void release()
{
delete this;
}
private:
// 🔴 核心:构造函数私有化!
// 外部无法直接调用 → 不能在栈上创建对象
HeapOnly()
{
cout << "对象在堆上创建啦!" << endl;
}
// 析构函数可以私有化
~HeapOnly()
{
cout << "对象在堆上销毁啦!" << endl;
}
};
设计一个类,只能在栈上创建
bash
#include <iostream>
using namespace std;
class StackOnly
{
public:
StackOnly() {
cout << "在栈上创建对象" << endl;
}
// 核心:禁用 堆上创建(new)
void* operator new(size_t) = delete;
void* operator new[](size_t) = delete; // 禁用数组new
};
设计一个类,只能创建一个对象(单例模式)
让一个类,这个类的对象,在当前进程中,有且只有一个.
饿汉模式:一开始(main之前)就创建对象
问题:
- 如果单例对象数据过多,构造初始化成本较高,会影响程序的启动速度.
- 多个单例类有初始化启动依赖关系,饿汉无法控制
例如:A和B两个单例,要求A先初始化,B后初始化,饿汉无法控制
bash
#include <iostream>
#include <vector>
#include <string>
using namespace std;
//饿汉:一开始就创建出对象
class Singleton
{
public:
static Singleton* GetInstance()
{
return &_sint;
}
void Print()
{
cout << _x << " " << _y << endl;
for (const auto& str : _vstr)
{
cout << str << " ";
}
cout << endl;
}
void Addstr(const string& str)
{
_vstr.push_back(str);
}
private:
Singleton(int x = 0, int y = 0, const vector<string> &vstr = {"xxxx", "yyyy"})
: _x(x), _y(y), _vstr(vstr)
{}
int _x;
int _y;
vector<string> _vstr;
//静态成员对象,不存在对象中,存在静态区,相当于全局的,定义在类中,受类域限制.
static Singleton _sint;
};
Singleton Singleton::_sint(1,1,{"aaa", "bbb", "ccc"}); //类外初始化
int main()
{
Singleton *s1 = Singleton::GetInstance();
s1->Print();
s1->Addstr("ddd");
Singleton *s2 = Singleton::GetInstance();
s2->Print();
return 0;
}
懒汉模式:调用时再初始化.
对比饿汉模式:程序一启动就直接把对象创建出来
懒汉模式:一开始只创建一个指针,等到使用的时候再把对象new出来
如下把GC回收机制也加入
bash
#include <iostream>
#include <vector>
#include <string>
using namespace std;
// 饿汉:一开始就创建出对象
namespace hunger
{
class Singleton
{
public:
static Singleton *GetInstance()
{
return &_sint;
}
void Print()
{
cout << _x << " " << _y << endl;
for (const auto &str : _vstr)
{
cout << str << " ";
}
cout << endl;
}
void Addstr(const string &str)
{
_vstr.push_back(str);
}
private:
Singleton(int x = 0, int y = 0, const vector<string> &vstr = {"xxxx", "yyyy"})
: _x(x), _y(y), _vstr(vstr)
{
}
int _x;
int _y;
vector<string> _vstr;
// 静态成员对象,不存在对象中,存在静态区,相当于全局的,定义在类中,受类域限制.
static Singleton _sint;
};
Singleton Singleton::_sint(1, 1, {"aaa", "bbb", "ccc"}); // 类外初始化
}
namespace lazy
{
class Singleton
{
public:
static Singleton *GetInstance()
{
// 第一次调用时,创建单例对象
// 线程安全问题,需要加锁
// lock_guard<mutex> lock(mtx);
// if (_psint == nullptr)
// {
// _psint = new Singleton(1, 1, {"aaa", "bbb", "ccc"});
// }
// return _psint;
static Singleton sint; // 局部静态变量,第一次调用时创建对象,线程安全
//局部的静态生命周期时全局的
return &sint;
}
static void DeInstance()
{
if (_psint)
{
delete _psint;
_psint = nullptr;
}
}
void Print()
{
cout << _x << " " << _y << endl;
for (const auto &str : _vstr)
{
cout << str << " ";
}
cout << endl;
}
void Addstr(const string &str)
{
_vstr.push_back(str);
}
private:
Singleton(int x = 0, int y = 0, const vector<string> &vstr = {"xxxx", "yyyy"})
: _x(x), _y(y), _vstr(vstr)
{
}
int _x;
int _y;
vector<string> _vstr;
// 静态成员对象,不存在对象中,存在静态区,相当于全局的,定义在类中,受类域限制.
static Singleton *_psint;
//内部类
class GC
{
public:
~GC()
{
Singleton::DeInstance();
}
};
static GC gc; // 全局对象,在main函数结束后,析构函数会被调用,释放单例对象
};
Singleton *Singleton::_psint = nullptr; // 类外初始化
static mutex mtx; // 锁
Singleton::GC Singleton::gc; // 类外初始化
}
int main()
{
// Singleton *s1 = Singleton::GetInstance();
// s1->Print();
// s1->Addstr("ddd");
// Singleton *s2 = Singleton::GetInstance();
// s2->Print();
lazy::Singleton *s3 = lazy::Singleton::GetInstance();
s3->Print();
s3->Addstr("ddd");
lazy::Singleton *s4 = lazy::Singleton::GetInstance();
s4->Print();
return 0;
}