c++ 技巧

智能指针

指针管理的困难:

1. 资源释放了,指针没有置空

(1)野指针

指针没有置空,后续接着使用。

(2)指针悬挂

多个指针指向同一个资源,其中一个指针释放了资源,也置空了,其他指针不知道该情况

(3)踩内存

资源已经释放,这块内存有了其他内容,还按照之前的方式去访问。

2.没有释放资源,引发内存泄漏

3.重复释放资源,引发core dump

RAII思想(Resource Acquisition Is Initialization):利用对象的生命周期来管理指针。

shared_ptr

解决指针悬挂的问题,只有引用计数为0,才调用析构函数。

使用场景:在容器中管理指针/资源需要通过函数进行传递

shared_ptr共享它指向的对象,多个shared_ptr可以指向相同的对象,在内部采用计数机制来实现

当新的shared_ptr与对象关联时,引用计数增加1。

当shared_ptr超出作用域时,引用计数减1。当引用计数变为0时,表示没有任何shared_ptr与对象关联,则释放该对象。

unique_ptr

一个资源只有一个指针指向它,unique_ptr独享它指向的的对象,同时只有一个unique_ptr指向同一个对象。当这个unique_ptr被销毁时,指向的对象也被销毁

c++ 技巧_第1张图片

不要用同一个裸指针初始化多个unique_ptr

get()方法返回裸指针

不要用unique_ptr管理不是new分配的内存

weak_ptr: 如何解决shared_ptr的循环引用问题

智能指针是类模板,在栈上创建智能指针对象

把普通指针交给智能指针对象。

volatile关键字

volatile用于声明一个变量,告诉编译器该变量值容易发生改变,在编译、读取、存储该变量的时候都不要做任何优化,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取存储数据,不做优化,在做嵌入式开发的时候,因为有时变量地址有可能是系统的一个外设地址,他的值的变化并不在程序控制范围内,随时有可能变化,因此需要对他进行声明,每次读取或者存储直接对地址进行操作。

变量如果加了 volatile 修饰,则会从内存重新装载内容,而不是直接从寄存器拷贝内容。

重载与重写的区别 

重载是同一个作用域下函数名称相同,参数不同,重写是子类重写父类的方法

函数的返回值不可以作为函数重载的条件:两个函数只有返回值不同,不符合重载的条件

当函数重载碰到默认参数,会出现二义性。

引用

引用就是变量的别名

引用必须初始化

引用在初始化后不可以修改

引用与指针的区别:

  • 引用不可以为空,指针可以为空
  • 引用的大小是指向的变量的大小,指针的大小是4字节
  • 引用的指向不可以改变,指针的指向可以改变

引用作函数的返回值:不要返回局部变量的引用,

函数调用可以作为左值:如果函数的返回值是引用,这个函数调用可以作为左值。

引用的本质在c++内部的实现是一个指针常量。

在函数形参列表中,可以加const修饰形参,防止形参改变实参

const修饰指针

const int *p 常量指针

指针的指向可以更改,指针指向的内容不可以更改。

int * const p 指针常量

指针的指向不可以更改,指针指向的内容可以更改。

const int * const p

指针的指向和指针指向的内容不可以更改。

深拷贝与浅拷贝

浅拷贝带来的问题是:堆区的内存重复释放。

结构体对齐

https://www.cnblogs.com/hyacinthLJP/p/16041690.html
C++结构体字节对齐_c++ 结构体对齐_桃溪小小生的博客-CSDN博客
 

*&

*&首先是一个指针,然后&代表是这个指针的引用。指针的引用其实是指针的一个别名,和指针具有相同的地址。

c++ primer plus

c++是大小写敏感的,也是拼写敏感的。

强制类型转换不会修改变量本身,而是创建一个新的、指定类型的值。

继承

c++ 技巧_第2张图片

父类中所有非静态成员属性都会被子类继承。

父类中私有成员属性是被编译器给隐藏了,因为访问不到,但确实被继承了。

子类和父类中有同名成员时,子类中可以直接访问子类中同名成员,加作用域可以访问父类中同名成员。

当子类和父类中有同名成员函数,子类会隐藏父类中所有同名成员函数,加作用域可以访问父类中同名成员函数。

菱形继承问题

动态多态

动态多态的条件:

  • 有继承关系
  • 子类重写父类的虚函数
  • 父类指针或引用指向子类对象

动态多态原理:

虚函数表指针(vfptr)指向虚函数表(vftable)。动态多态会让子类重写父类的虚函数表。

vf=virtual function

类中只要有一个纯虚函数就成为抽象类。抽象类是在虚函数后面加上 = 0 。

抽象类的两个特点:

  • 无法实例化对象
  • 抽象类的子类必须重写父类中的纯虚函数,否则也是抽象类。

多态时通过父类指针释放子类对象时,如果子类中有堆区的数据成员,无法通过父类指针释放,父类指针只会调用父类的析构函数,不会调用子类的析构函数。这时需要将父类的析构函数声明为虚函数,即虚析构函数,这样父类指针析构时就会既调用父类的析构函数,也会调用子类的析构函数。

纯虚析构函数不仅需要声明,也需要实现,但是需要在类外实现。类中如果有纯虚析构函数也是抽象类。

继承时,先调用父类的构造函数,再调用子类的构造函数。析构顺序与构造顺序相反。

STL

c++ vector.end()指向vector()最后一个元素的下一个位置

dynamic_cast

假如基类的指针指向派生类的对象,那么这个指针可以通过dynamic cast变成派生类的指针,并且是操作安全的;假如基类的指针指向基类的对象,那么这个指针不能通过dynamic cast的类型检查,新指针会是空指针,但是这个指针可以通过static cast变成派生类的指针,但是操作会出现问题。

封装

  • 将属性和行为作为一个整体,表现生活中的事物。
  • 将属性和行为加以权限控制。
  • 实例化:通过类创建对象。

访问权限

  • public:类内可以访问,类外也可以访问。
  • protected:类内可以访问,类外不可以访问。
  • private:类内可以访问,类外不可以访问。

父类中的protected的内容子类也可以访问。

父类中的private的内容子类不可以访问。

struct和class的区别

struct默认权限为public,class默认权限为private。

你可能感兴趣的:(c,c++,开发语言)