类的构造函数(二)

来源:互联网 发布:c语言辅导 编辑:程序博客网 时间:2024/05/21 17:27

一 . 浅拷贝和深拷贝

先看一段代码

class A{public:A(){_text = new char(100);}~A(){delete[] _text;}private:char * _text;};int main(){A a;A b(a);return 0;}
运行程序,会发现触发了一个断点,也就是程序崩溃了。为什么会出现这样的结果呢?
了解了拷贝构造函数的,就会知道这里的对象b的初始化会调用类的拷贝构造函数,但是我们这里没有自己的拷贝构造函数,那么系统会生成一个默认的拷贝构造函数。这个构造函数就是浅拷贝。
那么什么是浅拷贝呢?所谓的浅拷贝就是类对象的成员变量之间简单的赋值。简单的赋值,对于一般的变量来说的确没什么关系,但是对于指针就会出大的问题。为什么呢?指针是指向一个地址的标识,这个地址可以多个指针去指向,而我们简单的赋值,只是把一个指针指向的地址复制个了另一个。那么问题就来了,如果这个指针指向的地方被销毁了,但是另一个指针并不知道,然后在使用它之后,会悲剧的发现自己被人阴了,原来自己指向的内存释放了,自己什么都没有了。
这是相当危险的,潜伏在你的程序里面的一个重大的炸弹!

所以,我们需要深拷贝。可以理解为深度的拷贝,也就是两个对象完全独立的,拥有自己独立的地址,独立的内存空间。其中一个改变或者是被释放了,对另一个完全没有影响。
class A{public:A(){_text = new char(100);}A(const A& a){_text = new char[100];strcpy(_text, a._text);}~A(){delete[] _text;}private:char * _text;};int main(){A a;A b(a);return 0;}
这就是深拷贝。同时如果我们改变a的成员变量_text 是对b的成员变量没有任何影响的。
有一种偷懒的方法,就是把拷贝构造函数申明为私有的,这样在A b(a)的时候就会报错。但是,并不推荐这样写。

二. 移动构造函数(move构造函数)

这是涉及到c++11里面的,当然,也需要编辑器的支持。
首先应该了解c++11的右值引用,这里有一篇讲得很详细的文章:点击打开链接
下面是移动构造函数的写法:
class A{public:A(){_text = new char(100);}//拷贝构造函数A(const A& a){_text = new char[strlen(a._text) + 1];strcpy(_text, a._text);}//移动构造函数 A(A &&a){_text = a._text;a._text = nullptr;}//赋值构造函数A& operator=(const A&a){if (this != &a){delete[]_text;_text = new char[strlen(a._text) + 1];strcpy(_text, a._text);}return *this;}//移动赋值函数A& operator=(A &&a){if (this != &a){delete[] _text;_text = a._text;a._text = nullptr;}return *this;}~A(){delete[]_text;_text = nullptr;}private:char * _text;};int main(){A a;A c = move(a); //调用移动构造函数A d;d = move(a); //调用移动赋值函数return 0;}
仔细观察就会发现没有使用移动语义的函数都会去申请心的空间,虽然在调用结束之后会回收,但是使用移动语义之后明显节省了这一步,那么执行效率也会快很多。

关于c++11 的移动构造函数还不是很熟悉,难免会有错误的,请见谅。





0 0
原创粉丝点击