C++进阶语法(随缘填补...)

1 面向对象编程

1.1 OOP概述

面向对象程序设计的核心思想是数据抽象、继承和动态绑定。

  • 通过数据抽象可以将类的接口与实现分离;
  • 使用继承可以定义相似的类型并对其相似关系建模;
  • 使用动态绑定可以在一定程度上忽略相似类型的区别,而以统一的方式使用它们的对象。

1.2 基类与派生类

1.3 虚函数与抽象基类

1.4 拷贝控制与继承

1.5 作用域与继承

2 泛型编程

面向对象编程和泛型编程都能处理在编写程序时不知道类型的情况。不同之处在于:OOP能处理类型在程序运行之前都未知的情况;而泛型编程中,在编译时就能获知类型了。
模板是C++中泛型编程的基础,一个模板就是一个创建类或函数的蓝图或者说公式。

2.1 函数模板

2.1.1 定义、使用、实例化

template <typename T>

  1. 定义:模板定义以关键字template开始,后跟一个模板参数列表,列表中包含一个或多个模板参数。
  2. 使用:当使用模板时,(可以隐式地或显式地)指定模板实参,将其绑定到模板参数上。
  3. 实例化:当调用一个函数模板时,编译器通常用函数实参来推断模板实参,用推断出的模板参数实例化一个特定版本的函数。这些编译器生成的版本通常被称为模板的实例。

2.1.2 模板参数

  1. 模板类型参数:一般来说,可以将类型参数看作类型说明符。
  2. 非类型模板参数:一个非类型参数表示一个值而非一个类型。通过一个特定的类型名而不是关键字class或typename来指定非类型参数。非类型模板参数的模板实参必须是常量表达式。

2.1.3 inline、constexpr与模板

inline和constexpr说明符放在模板参数列表之后,返回类型之前。

2.1.4 模板编译

只有当实例化出模板的一个特定版本时,编译器才会生成代码。模板的头文件通常既包括声明也包括定义。

2.2 类模板

与函数模板不同的是,编译器不能为类模板推断模板参数类型。为了使用类模板,必须提供额外信息。

2.3 模板实参推断

2.4 重载与模板

2.5 模板特例化

3 IO库

4 容器

5 动态内存

5.1 内存管理概述

  1. 在C++中,动态内存管理是通过一对运算符来完成的,即newdelete
  • new:在动态内存中为对象分配空间并返回一个指向该对象的指针
  • delete:接受一个动态对象的指针,销毁该对象,并释放与之关联的内存
  1. 为了更容易、更安全地使用动态内存,新的标准库提供了智能指针来管理动态对象。所在头文件<memory>
  • shared_ptr:允许多个指针指向同一对象
  • unique_ptr:”独占“所指向的对象
  • weak_ptr:伴随类,是一种弱引用,指向shared_ptr所管理的对象

5.2 shared_ptr

智能指针也是模板。

程序使用动态内存出于以下三种原因之一:

  1. 程序不知道自己需要使用多少对象
  2. 程序不知道所需对象的准确类型
  3. 程序需要在多个对象间共享数据

5.2.1 定义与初始化

  1. 定义:shared_ptr<T> sp
  2. 初始化:默认初始化的智能指针中保存着一个空指针,解引用一个智能指针返回它指向的对象
  3. 支持的操作:…
  4. make_shared:在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr。最安全的分配和使用动态内存的方法。eg:auto p = make_shared<T>()

5.2.2 拷贝、赋值、销毁

  1. 引用计数:当进行拷贝或赋值操作时,每个shared_ptr都会记录有多少个其他shared_ptr指向相同的对象,可以认为每个shared_ptr都有一个关联的计数器,通常称为引用计数。
  • 拷贝一个shared_ptr时,计数器都会递增。如用一个shared_ptr初始化另一个shared_ptr,或者将它作为参数传递给一个函数,或者作为函数的返回值
  • 给shared_ptr赋予一个新值或者被销毁时,计数器会递减
  1. 销毁:

当指向一个对象的最后一个shared_ptr被销毁时,shared_ptr类会自动销毁此对象。它是通过shared_ptr的析构函数来完成销毁工作的。

  • 析构函数控制此类型的对象销毁时执行什么操作
  • 析构函数一般用来释放对象所分配的资源

当动态对象不再被使用时,shared_ptr类会自动释放动态对象,自动释放相关联的内存。

5.2.3 直接管理内存

自己直接管理内存的类与使用智能指针的类不同,它们不能依赖类对象拷贝、赋值和销毁操作的任何默认定义。

  1. 动态分配
  • new分配:默认情况下,动态分配的对象是默认初始化的
  • 动态分配的const对象:一个动态分配的const对象必须进行初始化
  • 定位new:int *p = new (nothrow) int;
  1. 释放动态内存
  • delete释放:销毁给定的指针指向的对象,释放对应的内存
  • 生存期:对于一个由内置指针管理的动态对象,直到被显式释放前它都是存在的
  • 空悬指针:当delete一个指针后,指针值就变为无效了,但是在很多机器上指针仍然保存着(已经释放了的)动态内存的地址,在delete之后,指针就变成了空悬指针。

5.2.4 shared_ptr与new结合

  1. 接受指针参数的智能指针构造函数时explicit的,所以,不能将一个内置指针隐式转换为一个智能指针,必须使用直接初始化形式来初始化一个智能指针。shared_ptr<T> p(new T());
  2. 当临时对象被销毁时,它所指向的内存会被释放。因此,不要混合使用普通指针和智能指针
  3. 异常
  • 智能指针:即使程序块过早结束,智能指针类也能确保在内存不再需要时将其释放
  • 内置指针:在new之后,对应的delete之前,如果发生异常,则内存不会释放
  1. 哑类:自定义删除器来代替delete

5.3 unique_ptr

5.3.1 定义与初始化

  1. 定义:unique_ptr没有类似的make_shared函数。定义时需要将其绑定到一个由new返回的指针上。
  2. 初始化:初始化unique_ptr必须采用直接初始化的形式。

5.3.2 拷贝、赋值、转移、销毁

  1. 拷贝、赋值:由于一个unique_ptr拥有它指向的对象,因此其不支持普通的拷贝或赋值操作。
  2. 转移:可以通过调用releasereset将指针的所有权从一个(非const)unique_ptr转移给另一个。
  3. 销毁:重载一个默认的删除器会影响到unique_ptr类型以及如何构造(reset)该类型的对象。在创建或reset这种unique_ptr类型的对象时,必须提供一个指定类型的可调用对象(删除器)。

可调用对象:对于一个对象或一个表达式,如果可以对其使用调用运算符,则称它是可调用的。

  1. 函数
  2. 函数指针
  3. bind创建的对象
  4. lambda表达式
  5. 重载了函数调用运算符的类

5.4 weak_ptr

weak_ptr是一种不控制所指向对象生存期的智能指针。创建时要用一个shared_ptr来初始化它。

5.5 动态数组

5.5.1 new和数组

  1. 分配并初始化一个对象数组。

5.5.2 allocator类

  1. 分配和初始化分离。
  2. <memory>

6 拷贝控制

7 重载运算与类型转换

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值