C++面向对象编程(二)之 深拷贝和浅拷贝

来源:互联网 发布:手机版导航源码 编辑:程序博客网 时间:2024/04/30 01:29

拷贝构造函数的深浅拷贝详解


  1. 默认拷贝构造函数可以完成对象的数据成员值简单的复制。
  2. 对象的数据资源是有指针指示的堆时,默认拷贝构造函数仅作指针值复制。


而浅拷贝,在某些情况下,例如,当类的数据成员中有指针类型时,就会带来数据安全方面的隐患,

我们就需要定义一个特定的拷贝构造函数,该拷贝构造函数不仅可以实现原对象和新对象之间数据成员

的拷贝,而且可以为新的对象分配单独的内存资源,这就是 深拷贝构造函数。


自定义拷贝构造函数,进行深拷贝,即,各对象有各自的内存空间。


#include <iostream>using namespace std;class String{public:String(const char *str = NULL){if(str == NULL){m_data = new char[1]; //虽然传过来是空字符串,但也要存放'\0';*m_data = '\0';// 把m_data指向的内存空间 置为空('\0')}else {length = strlen(str);m_data = new char[length+1]; //字符串有个"\0",所以长度要加1strcpy(m_data,str);//把str指向的内存空间内容 拷贝 到m_data指向内存空间}cout << "我是构造函数" << endl;}//自定义拷贝构造函数,String(const String& other){length = strlen(other.m_data);m_data = new char[length+1];strcpy(m_data,other.m_data);cout << "我是拷贝构造函数" << endl;}String& operator=(const String &other){//先判断传进的参数和当前实例(*this)是不是同一个实例if (this == &other){return *this;}delete []m_data;//释放原有的内存资源,防止内存泄露length = strlen(other.m_data);m_data = new char[length+1];strcpy(m_data,other.m_data);return *this;}~String(){if (m_data != NULL){delete []m_data;//这里,析构对象tr2和tr1时候,共释放了两次,因此程序崩溃m_data = NULL; //把指针置为NULLlength = 0;    }cout << "我是析构函数" << endl;}private:char* m_data;int length;};void objmain(){String tr1("abcdef");String tr2 = tr1; //此时会调用默认拷贝构造函数,但是C++编译器提供的是浅拷贝,因此在释放内存时候,释放了两次,所以程序崩溃String tr3("ABCDEF");tr3 = tr1;//C++编译器提供的等号操作也属浅拷贝//tr3.operator=(tr1); 相当于这样调用}int main(){objmain();system("pause");return 0;}


看看 内存剖析图



构造函数的初始化列表


C++中提供初始化列表对成员变量进行初始化

语法规则:

Constructor::Contructor() : m1(v1), m2(v1,v2), m3(v3)

{

    // some other assignment operation

}


注意:成员变量的初始化顺序只与声明的顺序相关,与在初始化列表中的顺序无关


具体调用顺序,先执行 类对象 的构造函数,如果 类对象有多个,按照声明顺序执行,

而不是按照初始化列表的顺序。 析构函数与构造函数执行顺序相反。



New delete  和 malloc free 的联系和区别


相同点:都是在堆上进行动态的内存操作。


不同点: new 和delete 是运算符,不是函数,因此执行效率高。

      而malloc 和free 是函数,并且用malloc函数需要指定内存分配的字节数,且不能

初始化对象。

new会自动调用对象的构造函数,delete会自动调用对象的析构函数。


用new分配数组空间时,不能指定初值。如果由于内存不足等原因而无法正常分配空间。

则new会返回一个空指针(NULL),用户可以根据该指针的值判断分配空间是否成功。


C++中的静态成员变量和静态成员函数

static关键字的作用:

  1. 函数体内的static变量的作用范围为该函数体该变量的内存只被分配一次
  2. 在模块内的static的全局变量可以被模块内的所有函数调用,但不能被模块外其他函数访问。
  3. 类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝。
  4. 在模块内的static函数只可被该模块内的其他函数调用。
  5. 类中的static成员函数属于整个类所拥有,这个函数不接受this指针,因而只能访问类的static成员变量。



C++面向对象模型:

语言中直接支持面向对象程序设计的部分,主要涉及如构造函数,析构函数,虚函数,继承

(单继承,多继承,虚继承,多态)等等。

对于各种支持的底层实现机制。

概况的说,在C++类中有两种成员变量:静态成员变量,和非静态成员变量;三种成员函数:

静态成员函数,非静态成员函数,虚函数。 如图:


C++类对象中的成员变量和成员函数时分开存储的。

成员变量:


普通成员变量:存储在对象中,与Struct变量有相同的内存布局和字节对齐方式

静态成员变量:存储于全局数据区。


成员函数:存储在代码段中。




由上图可以看出:

C++中类的普通成员函数都隐式包含一个指向当前对象的this指针。

而静态成员函数不包含指向具体对象的this指针。





0 0
原创粉丝点击