拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。
用C++11的话,可以使用特殊的语法来实现一个不能被拷贝的类。在C++11中,可以使用删除函数(deleted function)来禁用拷贝构造函数和拷贝赋值运算符。
下面是使用C++11实现一个不能被拷贝的类的示例代码:
class NonCopyable {
public:
NonCopyable() {}
~NonCopyable() {}
// 删除拷贝构造函数和拷贝赋值运算符
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator=(const NonCopyable&) = delete;
};
在这个示例中,通过在拷贝构造函数和拷贝赋值运算符的声明后面加上= delete来删除这些函数。这样一来,当其他地方尝试拷贝或赋值这个类的对象时,编译器会报错。
这种方法更加简洁,也更符合现代C++的风格。同时,使用删除函数可以提供更明确的错误信息,让开发者更容易理解问题所在。
实现方式:
下面是一个示例代码,展示了如何设计一个只能在堆上创建对象的类:
class HeapOnly {
public:
static HeapOnly* createInstance() {
return new HeapOnly();
}
void destroyInstance() {
delete this;
}
// 禁用拷贝构造函数和拷贝赋值运算符
HeapOnly(const HeapOnly&) = delete;
HeapOnly& operator=(const HeapOnly&) = delete;
private:
HeapOnly() {}
~HeapOnly() {}
};
在这个示例中,HeapOnly类的构造函数和析构函数都是私有的,这样其他地方就无法直接创建或销毁HeapOnly类的对象。而通过静态成员函数createInstance(),可以在堆上创建一个HeapOnly对象,并返回指向该对象的指针。同时,destroyInstance()函数用于在堆上销毁HeapOnly对象。
此外,还禁用了拷贝构造函数和拷贝赋值运算符,以确保对象不能被拷贝。
使用这种设计,其他地方只能通过调用HeapOnly::createInstance()来创建对象,并且必须手动调用destroyInstance()来销毁对象。这样可以确保对象只能在堆上创建和销毁,而不能在栈上创建对象。
这段代码定义了一个只能在栈上创建对象的类StackOnly。下面是对代码的解释:
class StackOnly {
public:
static StackOnly CreateObj()
{
return StackOnly();
}
void Print() const
{
cout << "StackOnly::Print()" << endl;
}
private:
StackOnly()
{}
StackOnly(const StackOnly&) = delete;
};
StackOnly类具有以下特点:
在main()函数中,我们可以看到如何使用这个类:
int main()
{
StackOnly so1 = StackOnly::CreateObj();
so1.Print();
return 0;
}
在main()函数中,我们通过调用StackOnly::CreateObj()来创建一个StackOnly对象,并将其赋值给so1。然后,我们调用so1.Print()来打印一条消息。
请注意,由于构造函数是私有的,因此无法直接在栈上创建对象,如代码中注释所示。这是通过将构造函数声明为私有来实现的。
这样设计的目的是确保只能通过特定的方式创建对象,以强制对对象的创建进行控制。
在C++中,饿汉模式(Eager Singleton)是一种单例设计模式的实现方式。单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。
饿汉模式的特点是在程序启动时就创建单例实例,并在整个程序的生命周期内保持不变。这意味着无论是否使用该实例,它都会被创建并占用内存。
class InfoSingleton
{
public:
static InfoSingleton& GetInstance()
{
return _sins;
}
void Insert(string name, int salary)
{
_info[name] = salary;
}
void Print()
{
for (auto kv : _info)
{
cout << kv.first << ":" << kv.second << endl;
}
cout << endl;
}
private:
InfoSingleton()
{}
InfoSingleton(const InfoSingleton& info) = delete;
InfoSingleton& operator=(const InfoSingleton& info) = delete;
map<string, int> _info;
// ...
private:
static InfoSingleton _sins;
};
InfoSingleton InfoSingleton::_sins;
int main()
{
InfoSingleton::GetInstance().Insert("张三", 10000);
InfoSingleton& infosl = InfoSingleton::GetInstance();
infosl.Insert("李四", 15000);
infosl.Insert("赵六", 12000);
infosl.Insert("王五", 8000);
infosl.Print();
// ...
return 0;
}
在这个例子中,InfoSingleton类是一个单例类。以下是饿汉模式的关键点:
通过调用InfoSingleton::GetInstance(),我们可以获取对单例实例的引用,并对其进行操作。在您的代码中,我们使用InfoSingleton::GetInstance()来插入和打印员工信息。
饿汉模式的优点是实现简单,线程安全(因为实例在程序启动时就已经创建),并且可以保证全局唯一性。然而,它的缺点是可能会浪费内存,因为实例在整个程序的生命周期内都存在,即使不使用它。
在C++中,懒汉模式(Lazy Singleton)是一种单例设计模式的实现方式。与饿汉模式不同,懒汉模式在第一次使用时才创建单例实例。
class InfoSingleton
{
public:
static InfoSingleton& GetInstance()
{
static InfoSingleton sinst;
return sinst;
}
void Insert(string name, int salary)
{
_info[name] = salary;
}
void Print()
{
for (auto kv : _info)
{
cout << kv.first << ":" << kv.second << endl;
}
cout << endl;
}
private:
InfoSingleton()
{
cout << "InfoSingleton()" << endl;
}
InfoSingleton(const InfoSingleton& info) = delete;
InfoSingleton& operator=(const InfoSingleton& info) = delete;
map<string, int> _info;
// ...
};
int main()
{
infosingleton::getinstance().insert("张三", 10000);
infosingleton& infosl = infosingleton::getinstance();
infosl.insert("李四", 15000);
infosl.insert("赵六", 12000);
infosl.insert("王五", 8000);
infosl.print();
infosingleton::getinstance().insert("张三", 13000);
infosingleton::getinstance().print();
infosl.print();
return 0;
}
在这个例子中,InfoSingleton类是一个单例类。以下是懒汉模式的关键点:
**懒汉模式的优点是实现简单,并且在第一次使用时才会创建实例,避免了可能的内存浪费。**然而,懒汉模式在多线程环境下可能存在线程安全问题。在C++11之前,静态局部变量的初始化是非线程安全的。但是在C++11之后,编译器保证了静态局部变量的线程安全性,因此可以在多线程环境下使用懒汉模式。
懒汉模式和饿汉模式在返回单例对象的函数上是相似的,都是返回一个静态的对象。但是它们的实现方式有所不同。
懒汉模式和饿汉模式是两种常见的单例模式实现方式,它们的区别主要体现在单例对象的创建时机和线程安全性上。
选择懒汉模式还是饿汉模式取决于具体的需求和场景。懒汉模式的优点是实现简单,且只在需要时才会创建对象,节省了内存资源。但是需要注意处理多线程环境下的线程安全问题。饿汉模式的优点是线程安全,不需要额外的线程同步机制,但在程序启动时就会创建对象,可能会造成一定的资源浪费。