C++11、C++14、C++17、C++20里面的一些常用新特性

C++11

  1. 自动类型推断(auto关键字):C++11引入了auto关键字,可以根据变量初始值自动推导出变量类型。例如:
auto i = 42;  // i被推导为int类型
auto d = 3.14;  // d被推导为double类型
  1. 基于范围的for循环(range-based for loop):可以方便地遍历容器中的元素,例如:
std::vector<int> v = {1, 2, 3, 4, 5};
for (auto& i : v) {
    i *= 2;
}
  1. lambda表达式:lambda表达式可以用来定义匿名函数,方便地传递函数对象,例如:
auto f = [](int x, int y) -> int { return x + y; };
int result = f(3, 4);  // result = 7
  1. 移动语义和右值引用(move semantics和rvalue references):通过右值引用可以实现资源的有效移动而不是复制,提高程序的效率,例如:
std::vector<int> v1 = {1, 2, 3, 4, 5};
std::vector<int> v2 = std::move(v1);  // v2接管了v1的资源,v1变为无效状态
  1. 智能指针(smart pointers):C++11引入了三种智能指针:unique_ptr、shared_ptr和weak_ptr,可以更好地管理动态内存,避免内存泄漏和悬空指针,例如:
std::unique_ptr<int> p(new int(42));
std::shared_ptr<int> q = std::make_shared<int>(42);
std::weak_ptr<int> r = q;
  1. 空指针常量(nullptr):C++11引入了nullptr关键字,用于表示空指针,避免了NULL宏带来的一些问题,例如:
void f(int* p) {}
f(nullptr);  // 可以显式地传递空指针
  1. 右值引用与移动构造函数:右值引用可以方便地实现移动构造函数和移动赋值运算符,用于高效地处理临时对象和避免复制开销,例如:
class MyVector {
public:
    MyVector(MyVector&& other) noexcept {
        // 移动构造函数
    }
    MyVector& operator=(MyVector&& other) noexcept {
        // 移动赋值运算符
        return *this;
    }
};
  1. 初始化列表:可以方便地初始化数组和容器,例如:
std::vector<int> v = {1, 2, 3, 4, 5};
std::map<std::string, int> m = {{"one", 1}, {"two", 2}, {"three", 3}};
  1. 类型别名(type alias):可以使用using关键字定义类型别名,例如:
using IntVec = std::vector<int>;
IntVec v = {1, 2, 3, 4, 5};
  1. 模板别名(template alias):可以使用using关键字定义模板别名,例如:
template <typename T>
using Vec = std::vector<T>;
Vec<int> v = {1, 2, 3, 4, 5};
  1. constexpr函数和变量:可以在编译期计算出值,例如:
constexpr int fib(int n) {
    return (n <= 1) ? 1 : fib(n-1) + fib(n-2);
}
constexpr int x = fib(10);  // 编译期计算出x的值为89
  1. 变长参数模板(variadic templates):可以接受任意数量和类型的参数,例如:
template <typename... Args>
void print(Args... args) {
    std::cout << sizeof...(args) << std::endl;  // 打印参数个数
}
print(1, 2, 3);  // 打印3
print("hello", 3.14);  // 打印2

C++14

  1. 泛型lambda表达式:可以使用auto关键字在lambda表达式中推断参数类型,例如:
auto sum = [](auto x, auto y) { return x + y; };
std::cout << sum(1, 2) << std::endl;  // 输出3
std::cout << sum(1.5, 2.5) << std::endl;  // 输出4.0
  1. return type deduction for normal functions(函数返回类型推断):可以使用auto关键字让编译器自动推断函数的返回类型,例如:
auto add(int x, int y) {
    return x + y;  // 返回类型会自动推断为int
}
  1. 模板变量(template variable):可以使用关键字template定义模板变量,例如:
template <typename T>
constexpr T pi = T(3.1415926535897932385);
std::cout << pi<double> << std::endl;  // 输出3.14159...
  1. 静态断言(static_assert)的增强:可以在静态断言中加入一个字符串提示,例如:
static_assert(sizeof(int) == 4, "int必须是4字节");  // 如果sizeof(int)不等于4,会输出提示信息
  1. 字符串字面量的增强:可以使用单引号(')包围字符,例如:
constexpr char operator""_c(char c) { return c; }  // 将字符转化为字符
std::cout << 'a'_c << std::endl;  // 输出字符'a'
  1. 按值捕获的增强:可以使用关键字init来对按值捕获的变量进行初始化,例如:
int x = 1, y = 2;
auto f = [x, y = x + 1] { return x + y; };
std::cout << f() << std::endl;  // 输出4
  1. 变量模板(variable template):可以使用关键字template定义变量模板,例如:
template <typename T>
constexpr T pi = T(3.1415926535897932385);
std::cout << pi<double> << std::endl;  // 输出3.14159...
  1. 内存模型的增强:增加了对内存模型的规定,例如:
std::atomic<int> x = 0;  // 原子变量
#pragma omp parallel for
for (int i = 0; i < 1000; ++i) {
    x.fetch_add(1);  // 线程安全的对x进行加一操作
}
std::cout << x << std::endl;  // 输出1000

C++17

  1. 结构化绑定(Structured Binding):可以使用auto关键字对一个结构体或元组进行结构化绑定,例如:
std::pair<int, int> p = {1, 2};
auto [x, y] = p;  // 结构化绑定
std::cout << x << " " << y << std::endl;  // 输出1 2
  1. if语句和switch语句的初始化:可以在if语句和switch语句的判断条件中进行变量初始化,例如:
if (int x = get_value(); x > 0) {  // 在if语句中初始化变量x
    std::cout << "x is positive" << std::endl;
}
  1. 类模板的参数推断(Class Template Argument Deduction,CTAD):可以让编译器自动推断类模板的模板参数,例如:
std::pair p{1, 2};  // 编译器可以自动推断出std::pair<int, int>
  1. constexpr if:可以在编译期进行条件判断,根据判断结果选择不同的代码路径,例如:
template <typename T>
void foo(T t) {
    if constexpr (std::is_pointer_v<T>) {  // 如果T是指针类型
        std::cout << "t is a pointer" << std::endl;
    } else {  // 如果T不是指针类型
        std::cout << "t is not a pointer" << std::endl;
    }
}
  1. 折叠表达式(Fold Expression):可以使用折叠表达式来简化代码,例如:
template <typename... Args>
auto sum(Args... args) {
    return (args + ...);  // 对args进行折叠求和
}
std::cout << sum(1, 2, 3, 4) << std::endl;  // 输出10
  1. 内联变量(Inline Variable):可以使用inline关键字来定义内联变量,例如:
inline int x = 1;  // 定义一个内联变量x,初始值为1
  1. 嵌套命名空间(Nested Namespace):可以在命名空间中嵌套命名空间,例如:
namespace A {
    namespace B {
        void foo() {
            std::cout << "hello, world!" << std::endl;
        }
    }
}
A::B::foo();  // 调用函数foo

C++20

  1. 概念(Concepts):概念是一种新的语言结构,可以用来描述模板参数的要求,例如:
template <typename T>
concept Integral = std::is_integral_v<T>;
template <typename T>
void foo(T t) requires Integral<T> {  // 使用概念描述模板参数要求
    std::cout << t << std::endl;
}
foo(1);  // 调用foo函数
  1. 三方合并运算符(Three-way Comparison Operator):可以使用<=>运算符对两个对象进行三方比较,例如:
struct Point {
    int x, y;
    auto operator<=>(const Point& other) const {
        return std::tie(x, y) <=> std::tie(other.x, other.y);
    }
};
bool operator==(const Point& lhs, const Point& rhs) {
    return lhs.x == rhs.x && lhs.y == rhs.y;
}
std::set<Point> s{{1, 2}, {2, 1}, {1, 1}, {2, 2}};
for (const auto& p : s) {
    std::cout << p.x << ", " << p.y << std::endl;
}

输出结果为:

1, 1
1, 2
2, 1
2, 2
  1. 初始化的捕获列表(Init-Capture):可以在lambda表达式的捕获列表中进行初始化,例如:
int x = 1;
auto lambda = [value = x * 2]() {  // 在捕获列表中初始化变量value
    std::cout << value << std::endl;
};
lambda();  // 调用lambda表达式
  1. consteval函数:可以在编译期计算表达式的值,例如:
consteval int get_value() { return 42; }  // 定义一个在编译期计算的函数
std::array<int, get_value()> arr;  // 在编译期创建一个大小为42的数组
  1. 模块(Modules):可以使用模块来管理和组织代码,替代传统的头文件包含方式,例如:
// 定义一个模块
module my_module;
export void foo() {
    std::cout << "hello, world!" << std::endl;
}

// 使用模块
import my_module;
int main() {
    foo();  // 调用函数foo
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/1014.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用Qt画一个温度计

示例1 以下是用Qt绘制一个简单的温度计的示例代码&#xff1a; #include <QPainter> #include <QWidget> #include <QApplication> class Thermometer : public QWidget { public:Thermometer(QWidget *parent 0); protected:void paintEvent(QPaintEvent …

【Hive】配置

目录 Hive参数配置方式 参数的配置方式 1. 文件配置 2. 命令行参数配置 3. 参数声明配置 配置源数据库 配置元数据到MySQL 查看MySQL中的元数据 Hive服务部署 hiveserver2服务 介绍 部署 启动 远程连接 1. 使用命令行客户端beeline进行远程访问 metastore服务 …

LC-146.LRU 缓存

题解&#xff1a;https://leetcode.cn/problems/lru-cache/solution/lru-ce-lue-xiang-jie-he-shi-xian-by-labuladong/ 文章目录[146. LRU 缓存](https://leetcode.cn/problems/lru-cache/)思路从0开始实现使用LinkedHashMap实现拓展&#xff1a;[460. LFU 缓存](https://leet…

【2024考研】计算机考研,4轮复习时间安排

文章目录&#x1f3a8;第1轮复习&#xff08;暑假前&系统课&#xff09;英语1/2数学1/2专业课408&#x1f3a8;第2轮复习&#xff08;开学前&真题&#xff09;英语1/2试卷数学1/2试卷专业课408试卷&#x1f3a8;第3轮复习&#xff08;报名前&政治&#xff09;政治试…

什么是数据治理,如何保障数据质量?_光点科技

随着信息化和数据化的发展&#xff0c;数据已经成为企业最为重要的资产之一。数据治理作为一种管理和保障数据质量的方法&#xff0c;越来越受到企业的重视。什么是数据治理&#xff1f;数据治理是一种管理和保障数据质量的方法。数据治理的主要目的是确保数据的可靠性、准确性…

Android APP隐私合规检测工具Camille使用

目录一、简介二、环境准备常用使用方法一、简介 现如今APP隐私合规十分重要&#xff0c;各监管部门不断开展APP专项治理工作及核查通报&#xff0c;不合规的APP通知整改或直接下架。camille可以hook住Android敏感接口&#xff0c;检测是否第三方SDK调用。根据隐私合规的场景&a…

二、数据结构-线性表

目录 &#x1f33b;&#x1f33b;一、线性表概述1.1 线性表的基本概念1.2 线性表的顺序存储1.2.1 线性表的基本运算在顺序表上的实现1.2.2 顺序表实现算法的分析1.2.3 单链表类型的定义1.2.4 线性表的基本运算在单链表上的实现1.3 其他运算在单链表上的实现1.3.1 建表1.3.2 删除…

Adam优化器算法详解及代码实现

文章目录学习率调整与梯度估计修正RMSprop 算法动量法Adam学习率调整与梯度估计修正 在介绍Adam算法之前&#xff0c;先谈谈Adam中两个关键的算法&#xff1a;学习率调整&#xff08;RMSprop 算法&#xff09;与梯度估计修正。 RMSprop 算法 学习率是神经网络优化时的重要超…

计算机组成原理(3)-哈工大

概述存储器分类按存储介质分类第一个是易失的&#xff0c;后面三个是非易失的按存取方式分类按在计算机中的作用分类RAM可读可写 ROM只读存储器的层次结构存储器的三个主要特性的关系缓存-主存层次和主存-辅存层次时间局部性就是cpu访问了一个数据&#xff0c;在不久的将来可能…

python学习——【第六弹】

前言 上一篇文章 python学习——【第五弹】中我们了解了python中的不可变序列元组&#xff0c;这篇文章接着介绍可变序列 字典。 字典 字典的实现原理&#xff1a; 字典&#xff0c;顾名思义其实现原理和字典类似&#xff0c;字典中的元素都是key—value&#xff0c;以键值对…

操作系统学习笔记 ---- 网络系统

1 DMA技术 直接内存访问&#xff08;Direct Memory Access&#xff09; 技术。 在进行 I/O 设备和内存的数据传输的时候&#xff0c;数据搬运的工作全部交给 DMA 控制器&#xff0c;而 CPU 不再参与任何与数据搬运相关的事情&#xff0c;这样 CPU 就可以去处理别的事务。 DM…

js逆向学习、安卓逆向

JS基础 提示信息 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn 安卓逆向 1.模拟器环境搭建 Magisk 是一套用于定制 Android 的开源软件&#xff0c;支持高于 Android 5.0 的设备。 以下是一些功能亮点&#xff1a; MagiskSU&#xff1a;为应用程序提供 root 访…

什么是 .com 域名?含义和用途又是什么?

随着网络的发展&#xff0c;网络上出现了各种不同后缀的域名&#xff0c;这些域名的后缀各有不同的含义&#xff0c;也有不同的用途。今天&#xff0c;我们就一起来探讨一下 .com 后缀的域名知识。 .com 域名是一种最常见的顶级域名&#xff0c;它是由美国国家网络信息中心&…

第3章 多层感知器

这章节我们来解决的问题是&#xff1a;如何使用神经网络实现逻辑电路中的“异或门”模型&#xff1f;如下图&#xff1a;根据第2章我们知道&#xff0c;单层感知器是能够解决“与门”、“或门”、“非门”这些简单的线性问题&#xff0c;但是不能解决“异或门”这类非线性问题。…

内存函数的简单实用

本篇要分享的是常见的内存函数 前面分享的函数都是和字符串相关&#xff0c;但是当我们在操作数据的时候不仅仅要操作字符数据 接下来分享几个与内存相关的函数 目录 本篇要分享的是常见的内存函数 1.memcpy 2.memmove 自定函数模拟实现memmove函数 3.memcmp 4.memset …

【算法经典题集】DP和枚举(持续更新~~~)

&#x1f63d;PREFACE&#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐ 评论&#x1f4dd;&#x1f4e2;系列专栏&#xff1a;算法经典题集&#x1f50a;本专栏涉及到的知识点或者题目是算法专栏的补充与应用&#x1f4aa;种一棵树最好是十年前其次是现在DPDP就是动态规划&a…

Web前端 JS WebAPI

1、操作DOM 1.1、什么DOM&#xff1f; DOM&#xff08;Document Object Model——文档对象模型&#xff09;&#xff1a;DOM是浏览器提供的一套专门用来操作网页内容的功能 DOM作用&#xff1a;开发网页内容特效和实现用户交互 DOM树是什么&#xff1f; 将 HTML 文档以树状…

手把手教你使用vue创建第一个vis.js

先看一下实现效果吧 &#xff0c;如下图 &#xff1a; 为什么要写这篇文章呢&#xff1f;因为之前有浅浅的了解一下vis.js&#xff0c;后期开发中没有使用vis&#xff0c;所以太深奥的也不懂&#xff0c;但是当时是用js写的。这两天有人问我用vue怎么写&#xff0c;然后说看到…

减治法实现插入排序,减治法实现二叉查找树(二叉搜索数,二叉排序数)的创建、插入与查找(含解析与代码实现)

&#x1f38a;【数据结构与算法】专题正在持续更新中&#xff0c;各种数据结构的创建原理与运用✨&#xff0c;经典算法的解析✨都在这儿&#xff0c;欢迎大家前往订阅本专题&#xff0c;获取更多详细信息哦&#x1f38f;&#x1f38f;&#x1f38f; &#x1fa94;本系列专栏 -…

嵌入式软件开发之Linux下C编程

目录 前沿 Hello World&#xff01; 编写代码 编译代码 GCC编译器 gcc 命令 编译错误警告 编译流程 Makefile 基础 何为 Makefile Makefile 的引入 前沿 在 Windows 下我们可以使用各种各样的 IDE 进行编程&#xff0c;比如强大的 Visual Studio。但是在Ubuntu 下如何进…
最新文章