赋值运算符函数
下面我们将编写代码,为一个CMyString类型添加赋值运算函数
1
2
3
4
5
6
7
8
9class CMystring{ public: CMyString(char* pData=nullptr); CMyString(const CMyString& str); ~CMyString(void); private: char* m_pData; };
写代码时有几点要注意:
1.返回值的类型:由于要完成连续赋值操作,函数的返回值必须声明为该类型的引用,并在函数结束前返回实例自身的引用(*this)
2.将传入的参数声明为常数引用
3.释放实例自身已有的内存,若忘记在分配新内存之前释放自身已有的空间,程序将出现内存泄漏
4.判断传入的参数和当前实例是否为同一实例,若果是就直接返回,不进行赋值
根据上述要求,我们可以写出代码
1
2
3
4
5
6
7
8
9
10
11CMyString& CMyString::operator=(const CMyString& str) { if(this==&str) return *this; delete[] m_pData; m_pData=nullptr; m_pData=new char[strlen(str.m_pData)+1]; strcpy(m_pData,str.m_pData); return *this; };
然而更高级的工程师不会止步于此,显然我们还有更多的东西需要去考虑。仔细观察上面的程序代码,我们会发现一项严重影响程序安全性的问题:当我们释放实例自身的内存后,我们申请新的内存空间,这时可能会因为内存不足而抛出异常,导致m_pData是一个空指针
我们有两种解决方法
1.先用new分配新内容,再delete释放已有的内容
2.创建一个临时实例,再交换临时实例和原来的实例
针对第二个方案,写下如下代码:
1
2
3
4
5
6
7
8
9
10
11
12CMyString& CMyString::Operator=(const CMyString& str) { if(this!=&str) { CMyString strTemp(str); char* pTemp=strTemp.m_pData; strTemp.m_pData=m_pData; m_pData=pTemp; } return *this; }
strTemp是一个局部变量,当其离开if时就出了变量的定义域,自动调用strTemp的析构函数,把strTemp.m_pData所指的内存——即实例之前的m_pData内存释放
设计一个类,我们只能生成该类的一个实例
当我们在程序中声明一个对象时,编译器调用构造函数,而调用通常来自外部,而不是class对象本身的调用
为了不让外部对象创建该类的实例,我们将该类的构造函数声明为private,这样就只能通过class内部创建对象实例,然而没有该类的实例,我们该如何访问class内部呢?
解决方案就是利用static公有成员,它独立于class对象而存在,而我们就可以利用这个公有成员函数访问该类内部
若我们再某static函数中创建了该class对象,并以引用或者指针形式将该对象返回(不能以该对象直接返回,主要是因为构造函数为私有函数,外部无法创建临时对象),这样我们就获得了该对象的使用权。
下面是单线程代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59class lazySingleton//懒汉模式,按需创建Singleton对象实例 { private: Singleton() { cout<<"Singleton()"<<endl; } static Singleton* instance; public: static Singleton* get_instance() { if(instance==NULL) { instance=new Singleton(); } return instance; } static Singleton* destroy() { delete instance; instance=NULL; } }; Singleton* Singleton::instance=NULL; int main() { Singleon* sl= Singleon::get_Singleon(); cout << sl<< endl; system("pause"); return 0; } class eagerSingleton//饿汉模式,在类加载时就完成了初始化 { private: Singleton() { cout<<"Singleton()"<<endl; } static Singleton* instance; public: static Singleton* get_instance() { return instance; } static Singleton* destroy() { delete instance; instance=NULL; } }; Singleton* Singleton::instance=new Singleton(); int main() { Singleon* sl= Singleon::get_Singleon(); cout << sl<< endl; system("pause"); return 0; }
最后
以上就是温柔大碗最近收集整理的关于C++练习Day4 剑指offer 赋值运算函数 创建单例类赋值运算符函数设计一个类,我们只能生成该类的一个实例的全部内容,更多相关C++练习Day4内容请搜索靠谱客的其他文章。
发表评论 取消回复