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

【C++】 C++11 知识点梳理(上)


一、C++11 发展概述

版本发布年份核心新增特性
C++981998模板、STL、容器、算法、字符串、流
C++112011列表初始化、auto/decltype、Lambda、右值引用 / 移动语义、constexpr、多线程、内存模型、正则、智能指针、哈希容器、std::array
C++142014读写锁、泛型 Lambda
C++172017折叠表达式、constexpr if、结构化绑定、string_view、文件系统、std::any/optional/variant
C++202020协程、模块、Concept、Ranges 库
C++232023类模板参数推导、标准库模块化、打印接口、扁平容器等

二、列表初始化 &std::initializer_list

2.1 C++98 旧式{}初始化

仅支持数组、结构体使用大括号初始化,语法零散:

struct Point { int _x; int _y; }; int main() { int arr1[] = {1,2,3,4,5}; int arr2[5] = {0}; Point p = {1, 2}; return 0; }

2.2 C++11 统一列表初始化

C++11 实现万物可用{}初始化,支持内置类型、自定义类、容器,且可省略 =;同时会做窄转换检查。

核心用法
#include <iostream> #include <vector> using namespace std; struct Point { int _x; int _y; }; class Date { public: Date(int year = 1, int month = 1, int day = 1) : _year(year), _month(month), _day(day) {} private: int _year, _month, _day; }; int main() { // 1. 内置类型 int x1 = {2}; int x2{2}; // 省略 = // 2. 自定义结构体/类 Point p1{1, 2}; Date d1{2025, 1, 1}; const Date& d2{2024, 7, 25}; // 引用绑定临时对象 // 3.需要注意的是C++98⽀持单参数时类型转换,也可以不⽤{} Date d3 = { 2025}; Date d4 = 2025; // 4. 容器便捷构造/插入 vector<Date> v; v.push_back({2025, 1, 1}); // 直接传初始化列表,简化代码 return 0; }
特性
  1. 编译器会优化:Date d = {a,b,c}不会产生额外临时对象 + 拷贝构造,直接构造
  2. 禁止隐式窄转换:int a{3.14};编译报错,int a = 3.14;C++98 允许截断。

2.3std::initializer_list

解决容器批量初始化问题,STL 所有容器都增加了接收initializer_list的构造函数与赋值重载。

底层原理
  • std::initializer_list内部仅保存两个指针(起始、末尾),不拷贝数据,开销极小。
  • ⭐底层指向栈上数组,支持迭代器遍历。
示例
#include <iostream> #include <vector> #include <map> using namespace std; int main() { // 1. 容器直接批量初始化 vector<int> v1{1,2,3,4,5}; vector<int> v2 = {10,20,30}; // 2. map 结合列表初始化 map<string, string> dict{ {"name", "zhangsan"}, {"age", "20"} }; // 3. 列表赋值 v1 = {100, 200, 300}; return 0; }
自定义类支持initializer_list
#include <initializer_list> #include <vector> class MyVector { private: vector<int> data; public: // 接收初始化列表构造函数 MyVector(initializer_list<int> il) { for (auto val : il) data.push_back(val); } }; // 使用 MyVector mv{1,2,3,4}; std::initializer_list<int> mylist; mylist = { 10, 20, 30 }; cout << sizeof(mylist) << endl; // 这⾥begin和end返回的值initializer_list对象中存的两个指针 // 这两个指针的值跟i的地址跟接近,说明数组存在栈上 int i = 0; cout << mylist.begin() << endl; cout << mylist.end() << endl; cout << &i << endl; // {}列表中可以有任意多个值 // 这两个写法语义上还是有差别的,第⼀个v1是直接构造, // 第⼆个v2是构造临时对象+临时对象拷⻉v2+优化为直接构造 vector<int> v1({ 1,2,3,4,5 }); vector<int> v2 = { 1,2,3,4,5 }; const vector<int>& v3 = { 1,2,3,4,5 }; // 这⾥是pair对象的{}初始化和map的initializer_list构造结合到⼀起⽤了 map<string, string> dict = { {"sort", "排序"}, {"string", "字符串"}};

三、右值引用 & 移动语义(C++11 性能核心)

3.1 左值 & 右值

  • 左值 (lvalue):有名字、可寻址、能出现在赋值号左边(普通变量、解引用指针、引用)。
  • 右值 (rvalue):无名字、临时对象、字面量、表达式结果,不可寻址。
int a = 10; // a 左值 int b = a + 20; // a+20 右值 string s = "hello"; // "hello" 字符串字面量是右值


3.2 左值引用 & 右值引用

语法:

  • 左值引用:类型&,只能绑定左值;const 左值引用可绑定右值。
  • 右值引用:类型&&,只能绑定右值;想要绑定左值需要move
int main() { int a = 10; int& r1 = a; // 左值引用绑定左值 const int& r2 = 20; // const 左值引用绑定右值 int&& rr1 = 20; // 右值引用绑定右值 // int&& rr2 = a; // 报错:右值引用不能直接绑左值 int&& rr3 = move(a);// std::move 将左值转为右值 // 重点:右值引用变量本身是**左值** int&& rr4 = 100; // int&& rr5 = rr4; // 报错 int&& rr6 = move(rr4); return 0; }

3.3 引用延长生命周期

const 左值引用右值引用都可以延长临时对象生命周期:

#include <string> using namespace std; int main() { string s1 = "test"; const string& r1 = s1 + s1; // 延长生命周期,不可修改 string&& r2 = s1 + s1; // 延长生命周期,可修改 r2 += "end"; return 0; }

3.4 重载匹配规则

同时提供三种重载时:

  1. 普通左值 → 匹配T&
  2. const左值 → 匹配const T&
  3. 右值 /move(左值)→ 匹配T&&
#include <iostream> using namespace std; void f(int& x) { cout << "左值引用\n"; } void f(const int& x) { cout << "const 左值引用\n"; } void f(int&& x) { cout << "右值引用\n"; } int main() { int a = 1; const int ca = 2; f(a); // 左值引用 f(ca); // const 左值引用 f(100); // 右值引用 f(move(a)); // 右值引用 return 0; }

3.5 移动构造 & 移动赋值

针对深拷贝类(string/vector)设计,转移资源所有权,替代深拷贝,提升性能。

函数原型

// 移动构造 类名(类名&& 源) noexcept; // 移动赋值 类名& operator=(类名&& 源) noexcept;

模拟简易 string(完整示例)

#include <iostream> #include <cstring> #include <algorithm> using namespace std; class String { private: char* _str = nullptr; size_t _size = 0; size_t _capacity = 0; public: String(const char* str = "") { _size = strlen(str); _capacity = _size; _str = new char[_capacity + 1]; strcpy(_str, str); } // 拷贝构造(深拷贝) String(const String& s) { _size = s._size; _capacity = s._capacity; _str = new char[_capacity + 1]; strcpy(_str, s._str); } // 移动构造(窃取资源) String(String&& s) noexcept { swap(_str, s._str); swap(_size, s._size); swap(_capacity, s._capacity); } // 拷贝赋值 String& operator=(const String& s) { if (this != &s) { delete[] _str; _size = s._size; _capacity = s._capacity; _str = new char[_capacity + 1]; strcpy(_str, s._str); } return *this; } // 移动赋值 String& operator=(String&& s) noexcept { if (this != &s) { swap(_str, s._str); swap(_size, s._size); swap(_capacity, s._capacity); } return *this; } ~String() { delete[] _str; _str = nullptr; } const char* c_str() const { return _str; } }; int main() { String s1("hello"); String s2 = s1; // 拷贝构造 String s3 = move(s1); // 移动构造 String s4("world"); s4 = move(s3); // 移动赋值 return 0; }

3.6 移动语义两大应用场景

  1. 函数传值返回局部对象:局部对象作为右值,触发移动构造,减少拷贝。
  2. 容器接口重载:STLpush_back/insert都提供const T&T&&两个版本:
    • 传入左值 → 拷贝构造
    • 传入右值 /move对象 → 移动构造

int main() { std::list<bit::string> lt; bit::string s1("111111111111111111111"); lt.push_back(s1); cout << "*************************" << endl; lt.push_back(bit::string("22222222222222222222222222222")); cout << "*************************" << endl; lt.push_back("3333333333333333333333333333"); cout << "*************************" << endl; lt.push_back(move(s1)); cout << "*************************" << endl; return 0; } 运⾏结果: string(char* str) string(const string& s) -- 拷⻉构造 ************************* string(char* str) string(string&& s) -- 移动构造 ~string() -- 析构 ************************* string(char* str) string(string&& s) -- 移动构造 ~string() -- 析构 ************************* string(string&& s) -- 移动构造 ************************* ~string() -- 析构 ~string() -- 析构 ~string() -- 析构 ~string() -- 析构 ~string() -- 析构

3.7 值类别细分(C++11 扩展)

C++11 把右值细分为两类:

  1. 纯右值 (prvalue):字面量、表达式结果、传值返回临时对象(传统意义上的右值)。
  2. 将亡值 (xvalue)move结果、右值引用转换结果。

合称:泛左值 (glvalue) = 左值 + 将亡值。


3.8 引用折叠 & 万能引用

C++ 不允许 “引用的引用”,模板中出现时遵循引用折叠规则:

  • T& &T&
  • T& &&T&
  • T&& &T&
  • T&& &&T&&

万能引用:模板参数T&&

  • 传入左值 → 推导T = 类型&,折叠后为左值引用
  • 传入右值 → 推导T = 类型,最终为右值引用
template<class T> void f1(T& x) {} // 由于引⽤折叠限定,f2实例化后可以是左值引⽤,也可以是右值引⽤ template<class T> void f2(T&& x) {} int main() { typedef int& lref; typedef int&& rref; int n = 0; lref& r1 = n; // r1 的类型是 int& lref&& r2 = n; // r2 的类型是 int& rref& r3 = n; // r3 的类型是 int& rref&& r4 = 1; // r4 的类型是 int&& // 没有折叠->实例化为void f1(int& x) f1<int>(n); f1<int>(0); // 报错 // 折叠->实例化为void f1(int& x) f1<int&>(n); f1<int&>(0); // 报错 // 折叠->实例化为void f1(int& x) f1<int&&>(n); f1<int&&>(0); // 报错 // 折叠->实例化为void f1(const int& x) f1<const int&>(n); f1<const int&>(0); // 折叠->实例化为void f1(const int& x) f1<const int&&>(n); f1<const int&&>(0); // 没有折叠->实例化为void f2(int&& x) f2<int>(n); // 报错 f2<int>(0); // 折叠->实例化为void f2(int& x) f2<int&>(n); f2<int&>(0); // 报错 // 折叠->实例化为void f2(int&& x) f2<int&&>(n); // 报错 f2<int&&>(0); return 0;

3.9 完美转发std::forward

作用:保留参数原有左 / 右值属性,配合万能引用使用。

  • std::move:一律转为右值
  • std::forward<T>:原样转发(左值转左值,右值转右值)
template<class T> void wrapper(T&& t) { // fun(t); // t 是左值,永远调用左值版本 fun(forward<T>(t)); // 完美转发,保留原值类别 }

http://www.rkmt.cn/news/1541898.html

相关文章:

  • 如何在wpf项目里插入Quill 编辑器
  • 深圳黄金回收哪家靠谱?2026全市星级测评榜单,本地人变现放心选 - zzlzzl6688
  • 官方最新发布2026年:安徽六安电大中专计算机应用专业,衔接大专升学跳板 - 我叫小周
  • 合肥个人闲置大牌包出手完整教程,避开压价、快速拿到合理市价 - 禹竞
  • 红河哈尼族彝族自治州黄金回收实体店怎么选?这份清单帮你货比三家 - 奢金汇
  • Java毕设选题推荐:基于 SpringBoot+Vue 的数码产品展示与购物结算系统设计 移动端适配型数码电商购物平台设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 从零搭建微信小程序后端:域名、备案、HTTPS 证书与 Nginx(以 perfecttools.top 为例)
  • 2026年6月最新江诗丹顿中国官方售后电话热线客服地址服务网点 - 江诗丹顿服务中心
  • 2026武汉黄金回收避坑实录:哪家靠谱?收收金到底值不值得选? - 热点速览
  • 2026年长沙高端系统门窗定制怎么选|断桥铝隔音窗品牌深度测评与避坑指南 - 优质企业观察收录
  • 泸州汽车灯光升级行业实力门店解析:欧特车灯深耕行业二十年,以专业工艺树立行业标准 - 热点速览
  • 2026长沙高端系统门窗定制:断桥铝隔音方案与全屋定制品牌深度横评 - 优质企业观察收录
  • 2015+充电协议解析
  • 福州防腐木地板生产厂家哪家售后好:2026年匠心精选 - 品牌推广大师
  • 成都保险被拒赔怎么办?李晓伟律师教你三步维权法 - 行路心安
  • 借条丢了怎么办?专业律所帮你补救证据链 - 品牌2026
  • 2026深圳黄金回收探店报告,筛选11家口碑门店,新手变现不踩雷 - 奢侈品回收测评
  • 福建菠萝格生产厂商推荐:匠心精选 - 品牌推广大师
  • 2026年五轴CNC精密加工TOP厂家推荐:如何筛选靠谱供应商 - 余文22
  • 银川保险理赔律师推荐:李晓伟律师团队综合实力全解析 - 行路心安
  • 2026哈尔滨实体店铺推广运营怎么选?行业避坑总结 - 最新行业资讯
  • OpenClaw 数据库灾备全方案:定时备份、异地灾备、故障自动切换
  • UI-TARS Desktop终极指南:用自然语言控制你的电脑
  • 2026 福州黄金回收全流程指南:实时金价、门店梯队、变现干货,轻松高价出手闲置黄金 - 薛定谔的梨花猫
  • Microsoft Office LTSC 2024 for Mac 16.110 发布 - 文档、电子表格、演示文稿和电子邮件
  • 2026长沙库存积压设备回收公司 实测 - LYL仔仔
  • 2026深圳黄金回收门店盘点,11家合规老店,本地居民实测推荐 - 奢侈品回收测评
  • 25.条件构造器 分页插件
  • 基于LCU API的英雄联盟客户端工具包架构设计与技术实现
  • 厦门专业中职学校排行:适配本地产业的5家实力院校 - 奔跑123