C++笔记(四)

拷贝构造函数调用时机

C++中拷贝构造函数调用时机通常有三种情况:

使用一个已经创建完毕的对象来初始化一个新对象

void test01(){

Person p1(20);

Person p2(p1);

}

值传递的方式给函数参数传值

void doWork(Person p)

{

}

void test02()

{

Person p;

doWork(p);//值传递的本质就是拷贝一个副本出来,会调用拷贝构造函数

}

以值方式返回局部对象

Person doWork2()

{

Person p1;

return p1;//以值的方式返回局部对象

}

void test03(){

Person p=doWork2();//调用拷贝构造函数

}

构造函数调用规则:

默认情况下,C++编译器至少给一个类添加三个函数

  1. 默认构造函数(无参,函数体为空)
  2. 默认析构函数(无参,函数体为空)
  3. 默认拷贝构造函数,对属性进行值拷贝

构造函数调用规则如下:

  1. 如果用户定义有参构造函数,C++不在提供默认无参构造,但是会提供默认拷贝构造
  2. 如果用户定义拷贝构造函数,C++不会再提供其他构造函数

深拷贝与浅拷贝:

浅拷贝只是拷贝一个指针,并没有新开辟一个地址,拷贝的指针和原来的指针指向同一块地址,如果原来的指针所指向的资源被释放了,那么再释放浅拷贝的指针资源就会出现错误。

深拷贝不仅拷贝值,还开辟出一块新的空间存放新的值,即使原先的对象被析构掉,释放内存了也不影响深拷贝得到的值

浅拷贝带来的问题就是堆区的内存重复释放(非法操作);

浅拷贝的问题用深拷贝解决:在堆区重新申请一块内存

拷贝构造函数:

Person(const Person &p)

{

m_age=p.m_age;

//m_height=p.m_height;(height属性是指针int * height,存储在堆区)编译器的默认构造函数实现的是这行代码

//深拷贝操作,在堆区重新申请一块内存

m_height=new int(*p.m_height);

}

总结:如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题

初始化列表:

作用:c++提供了初始化列表语法,用来初始化属性

语法:构造函数():属性1(值1),属性2(值2)...{}

举例:

//初始化列表初始化属性

Person(int a,int b,int c):m_A(a),m_B(b),m_C(c)

{

}

每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)

类中包含以下成员,必须放在初始化列表位置进行初始化:

引用成员变量,const成员变量,自定义类型成员(该类没有默认构造函数)

类对象作为类成员:

C++类中的成员可以是另一个类的对象,我们称该成员为对象成员

例如:

class A()

class B

{

A a;

}

B类中有对象A作为成员,A为对象成员

那么当创建B对象时,A与B的构造顺序是先A后B,析构的顺序是先B后A,

即当其他类对象作为本类成员,构造时候先构造类对象,再构造自身,析构的顺序与构造相反

静态成员:

静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员

静态成员分为:

静态成员变量

所有对象共享同一份数据

在编译阶段分配内存

类内声明,类外初始化

举例:

class Person

{

public

static int m_A;//类内声明

};

int Person::m_A = 100;//类外初始化

静态成员变量 不属于某个对象上 所有对象都能共享同一份数据

因此静态成员变量有两种访问方式(需要注意的是静态成员变量也是有访问权限的)

通过对象进行访问

Person p;

cout<

通过类名进行访问

cout<

静态成员函数

所有对象共享同一个函数

静态成员函数只能访问静态成员变量,因为这份数据是共享的,大家公用一份,静态成员函数不可以访问非静态成员变量,无法区分到底是哪个对象的属性

1.通过对象访问

Person p;

p.func();

2.通过类名访问

Person::func();

需要注意的是类外访问不到私有静态成员函数

你可能感兴趣的:(C++,c++,笔记,java)