当前位置: 首页 > news >正文

【C++】基础:C++11-14-17常用新特性介绍

😏★,°:.☆( ̄▽ ̄)/$:.°★ 😏
这篇文章主要介绍C++11-14-17常用新特性介绍。
学其所用,用其所学。——梁启超
欢迎来到我的博客,一起学习,共同进步。
喜欢的朋友可以关注一下,下次更新不迷路🥞

文章目录

    • :smirk:1. C++11
    • :blush:2. C++14
    • :satisfied:3. C++17

C++11、14、17 是现代 C++ 发展的三个关键里程碑,每一个版本都极大地改变了我们编写 C++ 代码的方式,下面来认识一下:

  • C++11: **现代 C++ 的开端。**从“能工作”的语言转变为对开发者友好、安全、高效的语言。核心是:减少样板代码、防止常见错误、提供零成本抽象。
  • C++14: **“C++11 的完善版”。**主要是对 C++11 特性的增强和缺陷修复,让 C++11 用起来更顺畅。
  • C++17: **“功能扩充版”。**引入了几个重要的新库和语言特性,进一步丰富标准库,并提供了更多表达能力强、运行效率高的工具。

😏1. C++11

  1. 自动类型推导 (auto)
    目的: 让编译器根据初始化表达式自动推导变量类型,简化代码,避免冗长复杂的类型名。
std::vector<std::map<std::string, std::list<int>>> complex_data;
// C++98 非常繁琐
std::vector<std::map<std::string, std::list<int>>>::iterator it = complex_data.begin();
// C++11
auto it = complex_data.begin(); // 清晰明了// 也常用于lambda表达式、模板编程等场景
for (auto& entry : complex_data) { ... } 
  1. 基于范围的 for 循环
    目的: 以更简洁、更安全的方式遍历容器和序列。
std::vector<int> vec = {1, 2, 3, 4, 5};
// C++98
for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {std::cout << *it << std::endl;
}
// C++11
for (int value : vec) { // 拷贝元素std::cout << value << std::endl;
}
for (const auto& value : vec) { // 常引用,避免拷贝,推荐方式std::cout << value << std::endl;
}
  1. 智能指针 (std::unique_ptr, std::shared_ptr, std::weak_ptr)
    目的: 自动化内存管理,从根本上解决内存泄漏和悬空指针问题。这是最重要的特性之一。
#include <memory>
// 不再需要手动 delete
void foo() {// unique_ptr: 独占所有权,移动而非拷贝auto ptr = std::make_unique<MyClass>(arg1, arg2);// shared_ptr: 共享所有权,引用计数auto sharedPtr = std::make_shared<MyClass>();auto sharedPtr2 = sharedPtr; // 引用计数+1// weak_ptr: 观察 shared_ptr,不增加计数,解决循环引用问题std::weak_ptr<MyClass> weakObserber = sharedPtr;
} // ptr 和 sharedPtr 在这里自动释放内存
  1. 右值引用和移动语义 (&&, std::move)
    目的: 允许资源(如动态内存)的转移而非拷贝,极大提升性能。这是理解现代 C++ 性能的关键。
class BigData {int* huge_data;
public:// 移动构造函数: “偷” 走临时对象的资源BigData(BigData&& other) noexcept : huge_data(other.huge_data) {other.huge_data = nullptr; // 源对象置空,确保其析构安全}// std::move: 将左值转换为右值,表示“我允许你移动我的资源”
};BigData a;
BigData b = std::move(a); // 调用移动构造函数,高效
// 此后,a 不再拥有资源,处于有效但未定义的状态(通常不应再使用)
  1. Lambda 表达式
    目的: 在调用的地方就地定义匿名函数对象,极大地简化了回调函数的编写(如与 库配合)。
std::vector<int> numbers = {5, 2, 8, 1, 4};
// 排序:按降序排列
std::sort(numbers.begin(), numbers.end(),[](int a, int b) { return a > b; }); // Lambda// 捕获列表:让lambda访问外部变量
int threshold = 3;
auto count = std::count_if(numbers.begin(), numbers.end(),[threshold](int x) { return x > threshold; }); // 值捕获
[&threshold](int x) { ... } // 引用捕获
[=]() { ... } // 捕获所有外部变量(值方式)
[&]() { ... } // 捕获所有外部变量(引用方式)
  1. 初始化列表 (std::initializer_list) 和统一初始化
    目的: 提供一种统一的、通用的初始化语法(使用花括号 {})。
// 初始化任何容器都变得非常简单直观
std::vector<int> v = {1, 2, 3, 4, 5};
std::map<std::string, int> m = {{"Alice", 25}, {"Bob", 30}};// 也可以用于自定义类
class MyClass {
public:MyClass(int, double, const std::string&);
};
MyClass obj{42, 3.14, "hello"}; // 统一初始化语法
  1. nullptr
    目的: 替代 NULL 宏,具有明确的指针类型,避免在重载函数时与整型 0 产生歧义。
void foo(int);
void foo(char*);
foo(NULL);   // 可能调用 foo(int),不符合直觉
foo(nullptr); // 明确调用 foo(char*)

😊2. C++14

  1. 泛型 Lambda
    目的: Lambda 的参数可以使用 auto 推导,使其成为模板函数。
// C++11: Lambda 参数必须是具体类型
auto lambda = [](int x) { return x; };
// C++14: 参数类型自动推导
auto genericLambda = [](auto x, auto y) { return x + y; };
std::cout << genericLambda(1, 2) << std::endl; // 3
std::cout << genericLambda(1.5, 2.3) << std::endl; // 3.8
  1. 函数返回类型推导 (auto 返回值)
    目的: 简化函数声明,让编译器根据 return 语句推导返回类型。
// C++14
auto add(int a, int b) { // 编译器推导为 intreturn a + b;
}
auto get_data() { // 可以返回复杂类型std::vector<std::map<int, std::string>> data;// ... 填充 datareturn data; // 编译器能正确推导
}
  1. std::make_unique
    目的: 为 std::unique_ptr 提供类似 std::make_shared 的工厂函数,保证异常安全,并且代码更简洁。
// C++11 必须这样
std::unique_ptr<MyClass> ptr(new MyClass);
// C++14 更安全、更简洁
auto ptr = std::make_unique<MyClass>();
  1. 二进制字面量和数字分隔符
    目的: 提升代码的可读性。
auto binary = 0b1010; // 二进制,等于十进制的 10
auto big_number = 1000000000; // 用撇号分隔,更容易看出是10亿
auto pi = 3.1415926535;

😆3. C++17

  1. 结构化绑定 (Structured Bindings)
    目的: 将 tuple、pair、结构体或数组的成员一次性解包到多个变量中。
std::map<std::string, int> get_map() { return {{"a", 1}, {"b", 2}}; }// C++17 之前:非常繁琐
auto entry = get_map().begin();
std::string key = entry->first;
int value = entry->second;// C++17: 一行搞定,清晰直观
auto [key, value] = *get_map().begin(); // key是string,value是intstd::tuple<int, double, std::string> get_data() { return {1, 2.0, "hi"}; }
auto [id, score, name] = get_data(); // 解包tuple
  1. std::optional
    目的: 表示一个“可能存在的值”。完美替代使用特殊值(如 -1, nullptr)来表示无效操作的做法。
#include <optional>
std::optional<int> find_in_database(const std::string& key) {if (/* found */) {return found_value;} else {return std::nullopt; // 表示无值}
}auto result = find_in_database("foo");
if (result.has_value()) { // 或者 if (result)std::cout << "Found: " << result.value() << std::endl; // 或者 *result
} else {std::cout << "Not found" << std::endl;
}
// value_or 提供默认值
std::cout << result.value_or(42) << std::endl; // 如果没找到,输出42
  1. std::variant 和 std::visit
    目的: 类型安全的联合体(union)。一个变量可以持有多种预定义类型中的一种。
#include <variant>
#include <string>std::variant<int, double, std::string> v;
v = 42; // 现在持有 int
v = 3.14; // 现在持有 double
v = "hello"; // 现在持有 std::string// 使用 std::visit 来访问
std::visit([](auto&& arg) {using T = std::decay_t<decltype(arg)>;if constexpr (std::is_same_v<T, int>) {std::cout << "int: " << arg << std::endl;} else if constexpr (std::is_same_v<T, double>) {std::cout << "double: " << arg << std::endl;} else if constexpr (std::is_same_v<T, std::string>) {std::cout << "string: " << arg << std::endl;}
}, v);
  1. std::filesystem
    目的: 提供一套跨平台的文件系统操作库,极大简化了目录遍历、文件信息获取等操作。
#include <filesystem>
namespace fs = std::filesystem;// 遍历目录
for (auto& entry : fs::directory_iterator(".")) {std::cout << entry.path() << std::endl;if (entry.is_regular_file()) {std::cout << "File size: " << entry.file_size() << std::endl;}
}// 创建目录、拷贝文件、获取绝对路径等操作都变得非常简单
fs::create_directories("/tmp/a/b/c");
fs::copy_file("src.txt", "dest.txt");
auto abs_path = fs::absolute("some_file.txt");
  1. 编译期 if 语句 (if constexpr)
    目的: 在模板编程中,根据模板参数在编译期选择不同的分支,被舍弃的分支不会参与编译。这是编写泛型代码的利器。
template<typename T>
auto print_type_info(const T& t) {if constexpr (std::is_integral_v<T>) {std::cout << "Integral: " << t << std::endl;} else if constexpr (std::is_floating_point_v<T>) {std::cout << "Floating point: " << t << std::endl;} else {std::cout << "Other type" << std::endl;}
}
// 调用 print_type_info(10) 时,只有第一个分支会被编译
// 调用 print_type_info(3.14) 时,只有第二个分支会被编译

请添加图片描述

以上。

http://www.xdnf.cn/news/1331713.html

相关文章:

  • 【Obsidian插件】HiNote
  • ansible playbook 实战案例roles | 实现db2自动安装
  • spring第9课,spring对DAO的支持
  • 【C++】模版(初阶)
  • 【STM32】HAL库中的实现(六):DAC (数模转换)
  • wpf之ComboBox
  • uniapp学习【上手篇】
  • Ubuntu 重连usb设备(断电和不断电方案)亲测可行
  • 【科研绘图系列】R语言绘制平滑曲线折线图
  • SQL面试题及详细答案150道(41-60) --- 条件查询与分组篇
  • 【报错】Please do not run this script with sudo bash
  • 开源大模型如何选择?GPT-OSS综合评估
  • IDEA切换分支时,提示:Git Checkout Problem
  • 4位量化:常规的线性层被替换成了4位线性层(48)
  • 服务器硬件电路设计之 SPI 问答(二):SPI 与 I2C 的特性博弈及多从机设计之道
  • 基于单片机环境火灾安全检测
  • 27.语言模型
  • 3D max制作蝴蝶结详细步骤(新手可跟)♥️
  • Angular入门教程
  • Angular由一个bug说起之十八:伴随框架升级而升级ESLint遇到的问题与思考
  • 【机器学习】什么是损失景观(Loss Landscape)?
  • FPGA实现Aurora 64B66B图像视频点对点传输,基于GTH高速收发器,提供2套工程源码和技术支持
  • 大数据毕业设计选题推荐-基于大数据的1688商品类目关系分析与可视化系统-Hadoop-Spark-数据可视化-BigData
  • 新手向:使用STM32通过RS485通信接口控制步进电机
  • 实验8.20
  • Feign - 降级选 fallback 还是 fallbackFactory
  • HTTP/1.1 与 HTTP/2 全面对比:性能革命的深度解析
  • Final Cut Pro X Mac fcpx音视频剪辑编辑
  • MacBook Pro M1升级Burp Suite2025.8
  • 实时视频技术选型深度解析:RTSP、RTMP 与 WebRTC 的边界