浅拷贝与深拷贝
- 区别:浅拷贝只是单纯的值拷贝,没有任何副作用。
当把一个有指针成员的类做浅拷贝时,两个类的指针成员会指向同一块地址空间,释放时会释放两次。 - 解决:深拷贝的实现。定义拷贝构造函数。例如:Person(const
Person &ob)//ob即为要拷贝的目标。在拷贝构造函数中可对指针成员新开空间。
const的使用
在c中,会为const修饰的变量开辟空间。不能直接对变量进行修改,但可以对局部const的地址存储的值进行修改。注意全局const变量不可以,因为开辟全局变量放在文字常量区,只读。
c中const为外部链接,在不同文件定义同名const对象会报错,c++则不会。
const int a=10;
int *p=(int *)&a;
*p=20;
//再输出a则为20
在c++中,则不会为基础类型const变量开辟空间,而是将它放在符号表中(#define也是)。在取地址时才会为其开辟空间。但开完空间之后依然访问符号表。
const int a=10;
int *p=(int *)&a;
*p=20;
//c++中再输出a还是10
但c++中也有开辟空间的情况:
1、用变量给const对象赋值
int b=9;
const int a=b;
2、const修饰自定义类型(结构体、类)
Note:
尽量以const代替define,因为define在预编译阶段就被替换了,例如#define a 100,在运行时如果a出现问题,会报100出现错误,不好定位。
且,const有类型与作用域,define无。
const修饰成员函数
修饰的是this指针指向的内存区域,成员函数体内不可以修改本类中任何普通成员变量。
int Func(void) const; //const 修饰的是成员函数
const int Func(void); //const 修饰的是返回值
引用
给数组定义一个引用
方法一:
int arr[5]={1,2,3,4,5};
//引用
int (&myArr)[5]=arr;
方法二:
typedef int TYPE_ARR[5]
TYPE_ARR &myARR-arr;
引用作为函数参数
若普通变量作为参数,局部变量无法传出函数,以引用做参数,传进去进行操作的就是其本身。
void swap1(int a,int b)
void swap2(int &a,int &b)
int main()
{
int data1,data2;
swap1(data1,data2)//err 不能完成交换
swap2(data1,data2)//ok a b 就是 data1 data2的别名
}
引用作为函数返回值
int &getNum()
必须用引用去接受,但操作有风险,因为如果返回值是局部变量,接到的时候生命周期已经结束了。
note:如函数作为左值,那其返回值必须是引用。
引用的本质是一个常量指针。
常引用
c++中函数参数一般都传引用,这样可以减少开销,但是如果函数中对引用参数做操作可能出现错误,所有参数常用常引用
typedef struct{
int num;
string name;
}STU;
int STU(const STU tmp);
//常用于拷贝构造函数
给常量定义引用也要用const修饰
int &num=10; //error
const int &num=10; //right
inline内联函数
以空间换时间
限值:
1、不能存在任何循环
2、不能有过多的条件判断
3、不能对函数取址
new与delete
1、用void *定义的对象不要用delete删除,不知道内存大小,也不认为void *为对象。
2、new数组,用delete[]释放
3、new delete malloc free不能混用
静态成员
1、静态成员属于类,不属于对象。即不管类实例化多少对象,静态成员只有一个拷贝,为所有对象共享。
2、静态成员在编译阶段就开空间,所以静态成员在类内声明,类外定义。
因为编译阶段是不给类开空间的,实例化对象时才会开空间
static实现单例模式
单例模式:一个类只能被一个对象创建
实现:在单例类的内部实现只生成一个实例,同时他提供一个静态getInstance方法,让客户可以访问它的唯一实例。为了防止外部对它实例,将其构造函数与拷贝构造函数设为私有。
应用:打印机类。使用需排队,只创建一个对象,构造多个打印任务,次数累积
class Printer
{
public:
//2、提供一个方法,获得单例指针
static Printer *getInstance(void)
{
return signlePrinter;
}
//4、设置功能函数
void printText();
private:
//1、定义一个静态的 对象指针变量 保存唯一实例
static Printer *signlePrinter;
//3、防止该类实例化其他对象,将构造函数全部私有
Printe(){}
Printer(const Printer &ob){}
};
//静态成员变量类内声明,类外定义
Printer *Printer::signlePrinter=new Printer;
this指针
c++封装,对象的数据单独存储,但对象共享成员函数
为区分调用函数时的数据操作,引入this指针,区分当前对象
note:
1、this是隐含在对象成员函数内部的指针
2、成员函数通过this可以知道操作的是哪个对象的数据
3、静态成员函数内部没有this指针,静态成员函数不能操作非静态成员变量。(静态成员函数属于类,而不是对象。而this指针指向的是对象的地址)
友元函数
1、将全局函数声明为类的友元
在类内任意位置声明其为friend即可。一般都是传入引用,可以明确访问的是哪个对象。
重载运算符
note:分辨其为一元运算符还是二元运算符
a+b=c;
重载+,传入的参数为a,b的类型,返回值为类型c
cout<<n;
重载<< 传入cout与n,返回ostream类型。
方式:
1、全局函数作为友元重载运算符
2、成员函数重载运算符:
此时可以用this替代其中一个参数