深拷贝与浅拷贝
浅拷贝:简单的赋值拷贝操作
如果被拷贝对象有指针变量,拷贝的指针变量依旧逐字逐句,不会改变,即两个对象将会指向同一块堆区内存
如果在析构中存在释放堆区内存的代码,那么先操作的会释放,而后操作的由于该内存已经被释放,找不到,将是非法操作
即堆区内存的重复释放
深拷贝:在堆区重新申请空间,进行拷贝操作
自己实现拷贝构造函数,解决浅拷贝带来的问题
举例
person(const person &p)
{
m_age=p.m_age;//int 变量没有差别
//height=p.height;//指针变量,此为默认的浅拷贝模式
height= new int (*p.height);//深拷贝模式
}
如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题
初始化列表
C++提供了初始化列表语法,用来初始化属性,语法为构造函数带冒号
class person
{
public:
//传统
person(int a, int b, int c)
{
ma=a;
mb=b;
mc=c;
}
//初始化列表
person():ma(10),mb(20),mc(30)
{
}
灵活写法为:
person(int a, int b, int c):ma(a),mb(b),mc(c)
{
}
private:
int ma;
int mb;
int mc;
};
类对象作为类成员
C++类中的成员可以是另一个类的对象,称该成员为对象成员
构造的时候先构造另一个类对象,再构造自身,先析构自身,再对象
静态成员就是在成员变量和成员函数前加上static
分为
静态成员变量:
有两种访问方式:
对象:person p1;p1.func();
类名: person::func();
所有对象共享同一份数据
在编译阶段分配内存
必须类内声明,类外初始化
静态成员函数://类外访问不到私有的静态成员函数
所有对象共享同一个函数
静态成员函数只能访问静态成员变量
class person
{
public:
static void func()
{
a=100;
}
static int a;//类内声明
};
int person::a = 0;//类外初始化
C++对象模型和this指针
在C++中,类内的成员变量和成员函数分开存储
person p;
cout<<sizeof(p)<<endl;
空对象占用内存空间为1,因为编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置
每个空对象也应该有一个独一无二的内存地址
如果类中写入一个 int a;则占用四个字节,仅为int所占用的
如果加入一个静态成员变量,占用字节不变,因为它不属于类的对象上
如果写入一个成员函数void function(){},占用字节不变,因为是分开存储的
静态成员函数也一样
只有非静态成员变量才属于类的对象上
每个非静态成员函数只会诞生一份函数实例,多个同类型的对象共用这一块代码
区分哪个对象调用自己,使用this指针
this指针指向被调用的成员函数所属的对象
this指针是隐含在每一个非静态成员函数内的一种指针
this指针不需要定义,直接使用即可
this指针的用途,当形参和成员变量同名,可用this指针区分
class person
{
public:
person(int age)
{
age=age;
}
int age;
}//无法区分
class person
{
public:
person(int age)
{
this-> age=age;
}
int age;
}//可以区分
在类的非静态成员函数中返回对象本身,可使用return *this;this是指针,*this是对象本身
如类中有函数void func(){}
如果要实现连续的函数,如p.func.func.func.func;
那么func函数必须返回p这个对象本身
需要用引用的方式返回
改为
person& func()
{
return *this;
}
如果不是引用的方式返回,返回的是值,也就是新创建一个对象来储存这个值,真正的p只进行了第一次操作,
那些新创建的对象,没有索引是找不到的,
这与拷贝构造函数有关,不会看前面
空指针访问成员函数
C++中空指针也可以调用成员函数,但是也要注意有没有用到this指针
person * p=NULL;
p->a();
p->b();//B会崩溃
比如类中函数
void a(){cout<<"ddd"<<endl;}不会报错
但
int a;
void b(){cout<<a<<endl;}会崩溃
a会自动成为this->a;
如果用到this指针,需要加以判断保证代码的健壮性
if(this==NULL)return;
const修饰成员函数
成员函数后加const我们称其为常函数
常函数内不可以修改成员属性
成员属性声明时加关键字mutable后,在常函数中依然可以修改
class person
{
public:
void a() const
{//this的本质是指针常量,指针指向不可修改,const本质修饰的是this指针,让其成为什么都不能改的指针
b=100;//此处有一个隐含的this->b,加了const,这句就回报错
c=100;//这句就不会报错
}
int b;
mutable int c;
}
常对象:
声明对象前加const称该对象为常对象
常对象只能调用常函数
const person p;//常对象
p.b=100;//报错
p.c=100;//ok可以改
p.a();可以
p.func();不可以