1. 何为透明在 C++14 之前,标准库中的函数对象(如 std::less)是单态的,这意味着你必须在使用时指定具体的类型。C++14 引入了透明版本,即模板参数为 void 的版本(如 std::less<void>)。
所谓的透明,指的是该函数对象不关心参数的具体类型。它就像一个透明的代理,直接将参数传递给底层的运算符(如 operator<),而不强制进行类型转换。
不透明(C++11):std::less<int>
必须传入 int 类型。如果你传一个 short 或者 double,虽然能编译通过(因为有隐式转换),但可能会产生临时对象,或者在关联容器中因为类型不匹配而找不到。
透明(C++14):std::less<void>
它可以接受任意类型的参数,只要这两个参数能被 operator< 比较。
它内部直接调用 std::forward<T>(t) < std::forward<U>(u),不进行任何类型转换。
1.1 为什么需要透明C++14 中关于透明操作符函数对象的引入解 ...
1. unique_ptr在 C++11 引入智能指针(std::unique_ptr, std::shared_ptr, std::weak_ptr)奠定了现代 C++ 内存管理的基础后,C++14 主要在易用性、性能和功能细节上进行了重要的优化和增强。
在 C++11 中,虽然智能指针 std::unique_ptr 是标准的一部分,但创建它的辅助函数 std::make_unique 直到 C++14 才加入。
1.1 在 C++11 中创建对象在 C++11 中,创建一个unique_ptr类型的对象我们有以下几种选择:
方案 A:手动实现 make_unique
12345678910111213141516#include <memory>#include <iostream>// C++11 兼容的 make_unique 实现template<typename T, typename... Args>std::unique_ptr<T> make_unique(Args&&... args) { ...
1. 聚合类在 C++ 中,聚合类 是一种特殊的类类型,它主要用于表示数据的集合,类似于 C 语言的结构体。聚合类的定义非常严格,在C++11 及以后标准中,判定一个类型是否为聚合类通常遵循以下规则:
无用户自定义的构造函数:不能有用户显式提供的构造函数。
非私有/保护的非静态数据成员:所有的非静态数据成员必须是 public 的。
无虚函数:不能有虚函数。
无虚、私有或保护的基类:不能有虚基类,且基类必须是 public 的。
满足上述条件的类、结构体或数组,被称为聚合类。聚合类可以使用花括号初始化列表进行初始化。
123456789101112131415161718192021#include <iostream>struct Point // 这是一个普通的聚合类{ int x; int y;};int main() { // 数组作为聚合的演示 int arr[3] = {10, 20, 30}; // 合法的聚合初始化 // 普通聚合类的演示 Point ...
1. 基本语法在 C++14 之前,我们只能定义函数模板、类模板。C++14 引入了第三种模板变量模板,它允许我们将变量定义为模板。这使得我们可以创建类型相关的常量值或变量,大大增强了模板元编程的能力。
变量模板的声明方式类似于函数模板或类模板,只是在开头使用了 template <...> 和随后的变量声明。
基本语法格式如下:
12345template<typename T>constexpr T pi = T(3.1415926535897932385L);template<typename T>T special_value = T(42);
1.1 简单的变量模板1234567891011121314151617#include <iostream>using namespace std;template<typename T>constexpr T pi = T(3.1415926535897932385L);int main() { // 实例化为 double 类型的 pi doubl ...
1. auto 的改进auto 和 decltype 基础 –> 自动类型推导
C++14 对 auto 关键字进行了非常显著的增强,主要解决了 C++11 中 auto 使用起来比较繁琐的问题,并引入了两大核心改进:函数返回类型推导 和 泛型 lambda。
1.1 函数返回类型推导C++ 中的 auto 类型推导是 C++11 引入的核心特性之一。它主要遵循 模板类型推导 的规则,在 C++14 中允许函数使用 auto 推导返回类型(不含尾置返回类型)。
在 C++11 中必须使用尾置返回类型:
1auto func() -> int { return 42; }
在 C++14 中可以直接使用 auto 进行返回值类型推导:
1234567891011121314151617181920// 编译器自动推导为 doubleauto add(int x, double y) { return x + y;}// 甚至可以用于递归函数(但需要有一个非递归的返回语句)auto factorial(int n) { ...
1. 泛型 Lambda1.1 语法C++14 引入了泛型 Lambda,允许 Lambda 表达式的参数使用 auto 类型推导。这使得编译器能够为每个调用点自动推导参数类型,本质上编译器会生成一个函数对象模板。
1234567891011// 基本语法auto lambda = [](auto param1, auto param2, ...) { // 函数体};// 语法对比// C++11: 显式指定参数类型auto lambda1 = [](int x, int y) { return x + y; };// C++14: 使用 auto 推导参数类型auto lambda2 = [](auto x, auto y) { return x + y; };auto lambda3 = [](auto&& x) { return x * 2; };
每个 auto 参数都是独立的类型参数,也就是说param1,param2可以是不同的类型
例如:lambda2(5, 3.1 ...
1. constexpr 概述constexpr(常量表达式)是 C++11 引入的关键字,用于指定值或函数可以在编译时计算,是编译时计算的核心特性。其设计目标主要有以下几点:
编译时计算:将运行时计算转移到编译时
类型安全:编译时进行类型检查
性能优化:消除运行时开销
泛型编程:增强模板元编程能力
123456// 编译时常量constexpr int size = 100; // ✅ 编译时确定// 编译时函数constexpr int square(int x) { return x * x; }// 编译时使用int array[square(5)]; // ✅ 数组大小在编译时计算:25
关于constexpr的使用和const是类似的,下面的表格中将二者的特性进行是对比:
特性
const
constexpr
主要含义
只读,不可修改
编译时常量
初始化时机
运行时或编译时
必须编译时
能否修改
初始化后不可修改
初始化后不可修改
作用域
类型修饰符
类型修饰符 + 函数修饰符
C++版本
C++98
C++11+
...
1. 自定义字面量1.1 基本语法自定义字面量是C++11引入的特性,允许程序员为字面量定义自己的后缀,从而创建具有特定类型和值的对象。它的基本语法如下:
1234// 定义字面量运算符返回值类型 operator"" 后缀名(参数类型 参数) { // 转换逻辑}
如果详细进行划分,定义字面量的时候有四种重载形式:
整数字面量
12// 整数字面量ReturnType operator"" _suffix(unsigned long long);
浮点数字面量
12// 浮点字面量ReturnType operator"" _suffix(long double);
字符字面量
12// 字符字面量ReturnType operator"" _suffix(char);
字符串字面量
12// 字符串字面量ReturnType operator"" _suffix(const char*, size_t);
关于自定义字面量后缀的命名必须以下划线( ...
1. 基本语法C++14 引入了二进制字面量,允许开发者直接使用二进制数字表示整数,使代码在涉及位操作时更加直观和可读。
下面是基本语法格式:
12int a = 0b101010; // 二进制前缀 0b, 十进制的 42int b = 0B11110000; // 大写 B 也可以
二进制数 0b101010 每一位的权值从右向左依次是 20,21,22,…
二进制数 0B11110000 每一位的权值从右向左依次是 20,21,22,…
我们可以通过代码将指定的二进制数值以十进制的格式进行输出,示例代码如下:
12345678910111213141516#include <iostream>#include <bitset>int main() { // 二进制字面量 int binary1 = 0b1010; // 十进制 10 int binary2 = 0b11110000; // 十进制 240 int binary3 = 0b100000000; // 十进制 ...
1. 回溯算法概述回溯算法(backtracking algorithm)是一种通过穷举来解决问题的方法,它的核心思想是从一个初始状态出发,暴力搜索所有可能的解决方案,当遇到正确的解则将其记录,当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,直到找到解或者尝试了所有可能的选择都无法找到解为止。这种走不通就退回再走的技术称为回溯法,它是一种“优化的暴力搜索”,而满足回溯条件的某个状态的点称为“回溯点”。
回溯算法通常采用深度优先搜索来遍历解空间,前序、中序和后序遍历都属于深度优先搜索。回溯算法的核心思想有两点:
深度优先搜索:回溯算法基于深度优先搜索的思想,它会沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点所在的路径无法得到有效的解时,算法会回溯到上一个节点,尝试其他的路径继续搜索。
穷举与剪枝:本质上是对所有可能的解进行穷举搜索,但与纯粹的暴力枚举不同,回溯算法会在搜索过程中根据问题的约束条件进行剪枝操作,避免对一些明显不可能产生解的分支进行搜索,从而提高搜索效率。
1.1 子集树子集树解决的是选还是不选的问题,也就是组合问题。元素的顺序不重要,只关 ...








































