跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++11 核心新特性详解:初始化、声明与移动语义

综述由AI生成C++11 标准引入统一列表初始化、自动类型推导及右值引用等关键特性。梳理了 initializer_list 机制、nullptr 与 decltype 用法,以及 STL 容器新增的 emplace 接口和移动语义优化。重点解析左值右值引用区别、移动构造原理及完美转发实现,帮助开发者理解底层资源转移逻辑,提升代码性能与安全性。

LinuxPan发布于 2026/3/15更新于 2026/6/917 浏览
C++11 核心新特性详解:初始化、声明与移动语义

C++ 作为一门经典且持续演进的编程语言,其标准迭代始终围绕提升开发效率、优化性能和完善语言特性展开。1998 年发布的 C++98 奠定了语言基础,而 2011 年发布的 C++11 标准则堪称一次里程碑式的更新。它不仅修复了早期版本的诸多缺陷,更引入了大量革命性特性,从根本上改变了 C++ 的编程范式,为开发者提供了更简洁、高效且安全的编码工具。

本文将聚焦 C++11 标准的核心新增特性,从统一列表初始化的语法简化、auto/decltype/nullptr 的声明优化,到 STL 容器与接口的扩展,再到右值引用、移动语义、完美转发等深刻影响性能的底层机制,以及类功能的增强(如默认移动构造、final/override 关键字),系统梳理这些特性的设计逻辑与实际应用场景。

无论是初学时对 C++11 语法的困惑,还是开发中对为何优先用 emplace_back 而非 push_back、move 与 forward 该如何正确使用等问题的疑问,都能通过本文的拆解得到解答。文中将结合具体代码示例,区分易混淆概念,同时兼顾实用性与原理性,帮助读者不仅会用,更能理解为什么这么用。

统一的列表初始化

C++11 扩大了用大括号括起的列表的使用范围,使其可用于所有的内置类型和用户自定义的类型。使用列表初始化时,可添加等号 (=),也可不添加。此外,列表初始化也可以适用于 new 表达式中。

int y = {2};
int y{2};

struct Point {
    Point(int x, int y) : _x(x), _y(y) {}
    int _x;
    int _y;
};
Point p1 = {1, 1};
Point p1{1, 1}; // 等价于 Point p1(1, 1)

注意,上面这两种写法其实是调用了 Point 的构造函数,这是 C++11 支持多参数构造函数的隐式类型转换。如果不想发生这种隐式转换,可以在构造函数前加 explicit:

explicit Point(int x, int y);

另外,在 new 表达式中使用列表初始化时:

Point* ptr3 = new Point[2]{{0, 0}, {1, 1}};
const Point& r = {3, 3}; // const 不能去掉,因为创建了一个 Point 临时对象

initializer_list

这是一个特殊的类型。当 auto 用于初始化列表 {...} 时,编译器会优先推导出 std::initializer_list<T> 类型。一般容器的构造函数和赋值操作符都支持这个类型。

vector<int> v1 = {1, 2, 3, 4, 3}; // 调用 initializer_list 的 vector 构造函数
Point p1 = {1, 1}; // 多参数构造函数的隐式类型转换

这两个规则要区分开。注意,上面的 {1, 2, 3, 4, 3} 转换成 initializer_list 类型时,其实是编译器会在常量区自动创建一个隐藏的常量数组,initializer_list 只是用指针引用这个数组,而不是自己存储数据。这个类型自己模拟实现不太行,库里面的这个类型编译器会做特殊照顾。

声明

C++11 增加了 auto、nullptr 和 decltype。

nullptr 和 NULL 的区别

NULL 有时直接被定义成 0,既能表示指针常量,又能表示整形常量。宏定义如下:

#define NULL ((void*)0)
// 或者
#define NULL 0

nullptr 是空指针字面量,类型安全。引申一下,宏不常用的,基本上用 const、enum、inline 去代替宏。

decltype

关键字 decltype 可以将变量的类型声明为表达式指定的类型。decltype 推出对象的类型,再定义变量,或者作为模板实参。其实也就是把 decltype(pf) 看成一个类型去用。

跟 auto 的区别:auto 不能像 auto x; 这样不带初始化。

int pf = 0;
int a = 0;
double b = 1.0;
dedtype(a * b) c = 2;
dedtype(pf) pf2;
B<dedtype(pf)> bb1; // B 是类

引申:函数能通过函数指针调用。例如:

auto x = malloc;
// 之后 x 和 malloc 的用法和作用就相同了

STL 里面的一些变化

新容器

增加了 array、forward_list、unordered_map、unordered_set。但是 array(数组)和 forward_list(单链表)没啥用。关于数组的话,一般也用 vector 代替,因为原生数组容易越界之后检查不出来。

新接口

对于 const 迭代器,给它添加了 cbegincendcrbegincrend,但是这几个接口没啥用,没必要。

所有的容器的构造函数都支持了 initializer_list 那种方式的初始化。所有的容器都支持了移动构造和移动赋值。大多数容器的很多接口都多了 emplace 系列的,比如以前是 back,现在多了个 emplace_back,并且本来的接口有些也支持了右值引用的方式。

新的类功能

新增加了移动构造函数和移动赋值运算符重载。

如果你没有自己实现移动构造,且没有实现析构函数、拷贝构造、拷贝赋值重载中的任意一个,编译器会自动生成一个默认移动构造——对内置类型会浅拷贝,对自定义类型如果有移动构造就用移动构造,没有就用拷贝构造。

如果你没有自己实现移动赋值重载函数,且没有实现析构函数、拷贝构造、拷贝赋值重载中的任意一个,编译器会自动生成一个默认移动赋值——对内置类型会浅拷贝,对自定义类型如果有移动赋值就用移动赋值,没有就用拷贝赋值。

允许在类定义时给成员变量初始缺省值。新增了 final 和 override 关键字。

强制生成默认函数的关键字 default:

Person(Person&& p) = default;

禁止生成默认函数的关键字 delete:

Person(Person&& p) = delete;

左值引用和右值引用

左值引用是以前本来就支持的,右值引用还是 C++11 引入的。

左值和右值

可以取地址的叫做左值,左值一般是可以被修改的。不能取地址的叫做右值(右值是不允许被修改的)。内置类型的右值叫做纯右值,自定义类型的右值叫做将亡值。

左值引用和右值引用

左值引用就是 int &a = b;,粗略理解为给左值取别名(b 是 int b = 0;)。右值引用是 double &&r = x + y;,粗略理解为给右值取别名(x、y 本来是 double,x = 1.1, y = 2.0)。注意,右值引用之后其实是让它拥有了左值的属性(有地址,并且可以被修改)。

问题:左值引用可以给右值取别名吗?const 的左值引用可以,例如 const int a = ...。右值引用可以给左值取别名吗?move 以后的左值可以,例如 int &&c = move(b);。

关于这个 move:拿上面举例:

void func(const int& r) {}
void func(int&& r) {}

也构成函数重载哈,编译器会选择最匹配的去用。传的是右值,用第二个;传的是左值,用第一个。

左值引用的核心价值就是减少拷贝,提高效率。右值引用的核心价值是进一步减少拷贝,弥补左值引用没有解决的场景,比如传值返回。

场景举例:

  1. 自定义类型中深拷贝的类,必须传值返回时(类大的时候用,小用不用区别不大)。
  2. 容器的插入接口,如果插入对象是右值,可以用移动构造转移资源给数据结构中的对象,也可以进一步减少拷贝。

注意:浅拷贝的类只能直接拷贝,移动拷贝是不行的——因为给也给的是指针。

移动构造

这个的话在出现将亡值赋值的时候会出现。这个的话就相当于把将亡值的东西给那个被赋值的,被赋值的把之前的东西给将亡值(将亡值之前存储东西的地方直接给被赋值的人了,有点像吸收别人的功力那种意思)。只是资源被转移了哈,原来的对象还在那,不算是空对象。

纯右值也会的哈,只是没啥必要而已,除非像 vector<int> 那种数组很大的。

string func() // 不能搞成 string& 或者 string&& 哈
{
    string str("xxxx");
    return str;
}

main 函数里面
string s = func(); // 这里的话会 str 先深拷贝给 func(),再 func() 移动拷贝给 s

编译器会进行优化:

  1. 连续的构造或者拷贝构造,合二为一。
  2. 开绿灯行为:这里的 str 直接被当成将亡值给了 s。

例如:

list<string> lt;
lt.push_back("22222");

此时也是一次移动拷贝,因为 "22222" 隐式转换成 string 的时候生成了个匿名对象(C++11 的认知)。如果用的是自己模拟实现的那种 string 的话,生成匿名对象时还会有一次拷贝构造(现代写法),有移动定义也是这样。

移动语义:就是用右值引用实现移动构造和移动赋值。

完美转发

万能引用

万能引用的作用:既可以接收左值,又可以接受右值。实参如果是左值的话,他就是左值引用,此时是引用折叠。实参如果是右值的话,他就是右值引用。

完美转发

补充:上面的 Fun 是 void Fun(int& x){}。调用 PerfectForward(std::move(a)) 和 PerfectForward(std::move(b)),这俩个的话其实最后一个是用的 1,一个用的 2。因为 Fun(t) 传的时候 t 是右值引用,所以是左值的属性。没用右值属性的话,在移动定义时,无法完成资源转移!此时如果想保留右值引用是右值的属性的话,就要用到完美转发了。完美转发就是加个 forward<T>。

template<typename T>
void PerfectForward(T&& t) {
    Fun(forward<T>(t));
}

要注意的是:如果想一直保持原来的属性,在每次传参的时候都要使用完美转发。中间少用了一次就会永远丢失原本的属性。

目录

  1. 统一的列表初始化
  2. initializer_list
  3. 声明
  4. nullptr 和 NULL 的区别
  5. decltype
  6. STL 里面的一些变化
  7. 新容器
  8. 新接口
  9. 新的类功能
  10. 左值引用和右值引用
  11. 左值和右值
  12. 左值引用和右值引用
  13. 移动构造
  14. 完美转发
  15. 万能引用
  16. 完美转发
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 基于 RetinaFace 和 CurricularFace 的教育考勤自动化方案
  • 挖 SRC 时的信息收集方法与工具实践
  • 突破内存瓶颈:llama.cpp 项目中 KV 缓存优化策略全解析
  • MySQL 表操作实战:创建、修改与删除全解析
  • Llama-Factory 微调中 Batch Size 的设置与性能调优
  • C++ 模拟实现二叉搜索树
  • 2025 年 9 月电子学会 Python 一级编程等级考试真题及解析
  • FPGA 门电路映射机制:从逻辑到硬件架构解析
  • 大模型微调(Fine-tuning)原理与实战指南
  • C++ 红黑树原理与实现:变色旋转及完整代码
  • MCP 协议详解:与 Function Call 的区别及使用方式
  • VSCode 禁用 GitHub Copilot 设置方法
  • GitHub 配置公钥与 Token 令牌
  • Qwen3.5 小尺寸模型开源:昇腾适配完成及部署指南
  • Discord 机器人创建与配置完整指南
  • 数据结构实战:双向链表实现与算法解析
  • 算法实战:寻找数组中心下标与除自身外数组乘积
  • 前端转产品经理一年经验总结与思考
  • 数据结构:常见时间复杂度与空间复杂度
  • Ubuntu 系统下 Python 连接 KingbaseES 数据库实现增删改查

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online