1、 拷贝构造函数:拷贝构造函数是一种特殊的构造函数,函数名与类名一致,必须的参数时本类型的一个引用变量。
三种会调用拷贝构造函数的情况;
(1)对象作为函数的参数传递的时候会建立一个临时的对象拷贝;
(2)对象以值传递的方式从函数返回;
(3)用一个对象去初始化另一个类型相同的对象。
浅拷贝:对象赋值的时候,只对对象中的数据成员进行简单的赋值;
深拷贝:在对象赋值的时候,对于动态成员重新分配内存。
2、 Volatile关键字:volatile表示易变的,关键字会告诉编译器不对该数据进行优化,系统访问该数据的时候总是会从内存中重新读取数据。
3、 动态内存:
(1) 计算机中程序运行相关的存储区:静态内存(static对象,类static成员和函数以外的变量)、栈内存(函数内部的非static成员)、堆内存(动态分配的存储区域,运行期)
(2) 智能指针:智能指针的设计解决了普通指针由于对象的销毁不合适导致的内存泄漏等问题。智能指针类型对应的头文件是,包含了shared_ptr共享对象指针(允许多个指针指向同一个对象),unique_ptr独占对象指针(只允许一个指针指向该对象),weak_ptr伴随类(弱引用,指向shared_ptr管理的对象);
(3) 智能指针解决内存泄漏问题的原理:我们可以认为每一个shared_ptr都会拥有一个关联的计数器,通常称为引用计数,当我们对对象进行拷贝或者赋值操作的时候,每一个shared_ptr都会记录有多少个其他的shared_ptr指向相同的对象
(1) 拷贝一个shared_ptr的时候,对象的计数器会加一;
(2) Shared_ptr作为参数传递的时候,对象的计数器会加一;
(3) Shared_ptr作为函数的返回值返回的时候,对象的计数器加一;
(4) 调用析构函数的时候对象的计数器会减一;
(5) 对shared_ptr进行赋值的时候,等号左侧智能指针原来指向的对象的计数器减一,等号右侧的智能指针指向的对象的计数器加一;
(6) 一个shared_ptr指向的对象的计数器变为0,则会自动销毁这个对象,并释放其占用的内存。
(4) 智能共享对象指针的使用方法:shared_ptr p=make_shared(eg)使用eg作为初始值产生一个T类型对象的智能指针,并将其赋值给p;p.unique()判断p是否是一个独立的对象指针,也就是use_count是否为0;p.use_count()返回与p指针共享对象的智能指针的数量,可能很慢,主要用于调试
(5) 动态内存:由new和delete负责创建和销毁的内存区域,销毁对象的时机不合适可能会导致内存泄漏和非法指向内存的指针等。
(6) 使用动态内存的几种情况:
(1) 程序不知道自己需要使用多少对象;
(2) 程序不知道所需对象的准确类型;
(3) 程序需要在多个对象间共享数据;
(7) 动态内存管理:
(1) 使用new动态分配和初始化对象;
Int *p=new int;//p指向一个动态分配的、未初始化对象
Int *p=new int(1);//p指向一个初始化为1的int数据
Const int *p=new const int(1);//p指向整型常量1
(2) 内存耗尽:
使用int *p=new (nothrow) int;这种形式的new叫做定位new,nothrow定义在new头文件当中,当这种形式的new不能分配内存的时候会返回一个空指针;
(3) 释放动态内存:
Delete p;//p是指向一个动态分配的对象的指针或空指针
4、 哪些函数不能声明为虚函数?
(1) 普通函数:非成员函数,普通函数只能被重载,不能被重写,而虚函数是动态绑定的,往往会在类的继承当中出现,是实现多态的机制,因此会要求某些函数能够被重写,以此来实现多态,二者有矛盾;
(2) 构造函数:构造函数是用来创建对象的,所以在构造函数被调用之前是没有对象产生的,而虚函数恰恰是在对象生成之后才能实现其多态的机制;
(3) 内联函数:内联函数是当函数体长度比较短,语句比较简单的时候,能够在编译期直接在代码中展开的一种机制,该展开是否执行完全由编译器决定,能够以此降低函数调用的代价,而虚函数运行时动态绑定的函数,二者存在矛盾;
(4) 静态成员函数:静态成员函数是隶属于类的,并不是属于对象的,因此无论创建了多少个对象,该函数仍然是只有一份,由所有对象共享,没有动态绑定的必要性,也无法实现多态;
(5) 友元函数:友元函数不是类的成员函数,无法被继承,更不能实现多态;