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++编译器至少给一个类添加三个函数
- 默认构造函数(无参,函数体为空)
- 默认析构函数(无参,函数体为空)
- 默认拷贝构造函数,对属性进行值拷贝
构造函数调用规则如下:
- 如果用户定义有参构造函数,C++不在提供默认无参构造,但是会提供默认拷贝构造
- 如果用户定义拷贝构造函数,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<<p.m_A<<endl;
通过类名进行访问
cout<<Person::m_A<<endl;
静态成员函数
所有对象共享同一个函数
静态成员函数只能访问静态成员变量,因为这份数据是共享的,大家公用一份,静态成员函数不可以访问非静态成员变量,无法区分到底是哪个对象的属性
1.通过对象访问
Person p;
p.func();
2.通过类名访问
Person::func();
需要注意的是类外访问不到私有静态成员函数
原文地址:https://blog.csdn.net/stephen_yoga/article/details/135836419
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!