首先记录一下markdown语法, - 是列表,#表示标题。
虚函数
答:
- 虚函数的语法是在函数声明前加上virtual关键词。
- 虚函数的作用时避免父类引用指向子类对象时子类对象调用父类成员函数的问题。
- 虚函数实现的底层机制是vfptr和vftable。当一个函数被声明为虚函数时,父类对象的底层维护的是一个虚函数表,虚函数表存储了成员函数的地址, 通过虚函数指针访问。当子类重写父类虚函数时,虚函数表也会被重写,更换为子类成员函数的地址,这样当子类对象利用vfptr访问的成员函数对应的就是子类的成员函数。
内联函数
答:
- 内联函数语法:在函数定义前加inline关键词
- 内联函数作用:将函数在每个调用点展开为函数定义,提高程序运行的效率,同时也让代码更简洁。
虚函数可以是内联的吗?
答:
- inline virtual只能发生在编译器可以确定所调用的对象是哪个类时,这时编译器具有实际对象而不是对象的引用或指针,才能发生。
- 当虚函数发生动态多态时,在运行时才能确定其定义,在编译时要展开为函数定义的内联技术自然无法展开。
c++11的智能指针
答:
- 三类unique _ptr、shared_ptr、weak_ptr。
- 利用关键词new创建出来的动态对象的释放delete容易出错,c++11标准库定义了两个动态指针来管理动态分配的对象,确保他们被释放且不被重复释放。
- 动态内存存储在堆(heap)区。
- 动态指针定义在memory头文件中。
shared_ptr
- shared_ptr 允许多个指针指向同一个对象。
- shared_ptr初始维护一个空指针。
- 当用一个shared_ptr初始化另一个shared_ptr,或将他作为参数传递给一个函数以及作为函数的返回值时,他所关联的计数器就会递增。
- 当给shared_ptr赋予一个新值或者一个局部的shared_ptr离开其作用域,计数器递减。当计数器变为0,它自动释放其管理的对象。
- shared_ptr的析构函数递减它所指向对象的引用计数,当计数器变为0销毁对象并释放对象占用的内存。
//创建智能指针
Base *p=new Base();
//利用智能指针sptr管理指针p。相当于参数初始化。
Std::shared_ptr<Base> sptr(p);
// 返回与sptr共享对象的智能指针数量。
count<<sptr.use_count()<<endl;
程序使用动态内存的三个原因:
- 程序不知道自己需要使用多少对象
- 程序不知道所需对象的准确类型
- 程序需要在多个对象间共享数据
- 一般而言,如果两个对象共享底层的数据,当某个对象被销毁时不能单方面地销毁底层数据。
Blob<string> B1;
{
Blob<string> B2={“a”,”aa”,”the”};
B1=B2;
}
//离开作用域,B2被销毁,但是B1指向最初由B2创建的元素。
unique_ptr
- unique_ptr某个时刻只能指向一个特定对象,当unique_ptr被销毁时其指向对象也销毁。。
- unique_ptr不支持普通的拷贝或赋值操作。例外:可以拷贝或赋值一个将要被销毁的unique_ptr,例如从函数返回unique_ptr。
- 定义unique_ptr时需将他绑定到一个new返回的指针上,初始化必须直接初始化。
unique_ptr<int> p1(new int(42));
//release()返回unique_ptr当前保存的指针并将其置为空
unique_ptr<int> p2(p1.release());
unique_ptr<int> p3(new int(42));
//reset将原来对象释放,重新只想给定指针。
p2.reset(p3.release());
weak_ptr
- weak_ptr指向由一个shared_ptr管理的对象,并且不会改变其引用计数。
//需要由shared_ptr初始化weak_ptr
auto p=make_shared<int>(42);
weak_ptr<int> wp(p);
//当lock调用返回true时才进入if,因为对象有可能不存在
if(shared_ptr<int> np=wp.lock()){
}