C++ 参考手册
- C++11
 - C++14
 - C++17
 - C++20
 - C++ 编译器支持情况表
 - 独立与宿主实现
 - C++ 语言
 - 变量模板(C++14 起)
 - 整数字面量
 - 聚合初始化
 - 比较运算符
 - 默认比较(C++20 起)
 - 转义序列
 - for 循环
 - while 循环
 - 用户定义转换
 - SFINAE
 - 主函数
 - ASCII 码表
 - 标识符
 - 类型
 - 内存模型
 - 对象
 - 基本概念
 - 表达式
 - 声明
 - 初始化
 - 函数
 - 语句
 - 类
 - 运算符重载
 - 模板
 - 异常
 - 事务性内存
 - 占位符类型说明符 (C++11 起)
 - decltype 说明符
 - 函数声明
 - final 说明符 (C++11 起)
 - override 说明符(C++11 起)
 - 引用声明
 - 移动构造函数
 - 移动赋值运算符
 - 枚举声明
 - constexpr 说明符(C++11 起)
 - 列表初始化 (C++11 起)
 - 构造函数与成员初始化器列表
 - using 声明
 - nullptr,指针字面量
 - 基础类型
 - 类型别名,别名模版 (C++11 起)
 - 形参包
 - 联合体声明
 - 字符串字面量
 - 用户定义字面量 (C++11 起)
 - 属性说明符序列(C++11 起)
 - Lambda 表达式 (C++11 起)
 - noexcept 说明符 (C++11 起)
 - noexcept 运算符 (C++11 起)
 - alignof 运算符(C++11 起)
 - alignas 说明符 (C++11 起)
 - 存储类说明符
 - 基于范围的 for 循环 (C++11 起)
 - static_assert 声明
 - 隐式转换
 - 代用运算符表示
 - 自增/自减运算符
 - 折叠表达式(C++17 起)
 - 类模板实参推导(C++17 起)
 - 模板形参与模板实参
 - if 语句
 - inline 说明符
 - 结构化绑定声明 (C++17 起)
 - switch 语句
 - 字符字面量
 - 命名空间
 - 求值顺序
 - 复制消除
 - consteval 说明符 (C++20 起)
 - constinit 说明符 (C++20 起)
 - 协程 (C++20)
 - 模块 (C++20 起)
 - 约束与概念 (C++20 起)
 - new 表达式
 - do-while 循环
 - continue 语句
 - break 语句
 - goto 语句
 - return 语句
 - 动态异常说明
 - throw 表达式
 - try 块
 - 命名空间别名
 - 类声明
 - cv(const 与 volatile)类型限定符
 - 默认初始化
 - 值初始化(C++03 起)
 - 零初始化
 - 复制初始化
 - 直接初始化
 - 常量初始化
 - 引用初始化
 - 值类别
 - C++ 运算符优先级
 - 布尔字面量
 - 浮点字面量
 - typedef 说明符
 - 显式类型转换
 - static_cast 转换
 - dynamic_cast 转换
 - const_cast 转换
 - reinterpret_cast 转换
 - delete 表达式
 - 构造函数与成员初始化器列表
 - this 指针
 - 访问说明符
 - 友元声明
 - virtual 函数说明符
 - explicit 说明符
 - 静态成员
 - 默认构造函数
 - 复制构造函数
 - 复制赋值运算符
 - 析构函数
 - 类模板
 - 函数模板
 - 显式(全)模板特化
 - 汇编声明
 - C++ 的历史
 - 作用域
 - 生存期
 - 定义与单一定义规则(ODR)
 - 名字查找
 - 有限定的名字查找
 - 无限定的名字查找
 - 如同规则
 - 未定义行为
 - 翻译阶段
 - 常量表达式
 - 赋值运算符
 - 算术运算符
 - 逻辑运算符
 - 成员访问运算符
 - 其他运算符
 - sizeof 运算符
 - typeid 运算符
 - 指针声明
 - 数组声明
 - 语言链接
 - 详述类型说明符
 - 默认实参
 - 变长实参
 - 实参依赖查找
 - 重载决议
 - 重载函数的地址
 - 注入类名
 - 非静态数据成员
 - 非静态成员函数
 - 嵌套类
 - 派生类
 - 空基类优化
 - 抽象类
 - 位域
 - 转换构造函数
 - 成员模板
 - 模板实参推导
 - 部分模板特化
 - sizeof... 运算符
 - 待决名
 - 函数 try 块
 - 扩充命名空间 std
 - 字母缩写
 - RAII
 - 三/五/零之法则
 - PImpl
 - 零开销原则
 - 类型
 - 隐式转换
 - 注释
 - C++ 关键词
 - 预处理器
 - C++ 标准库头文件
 - 具名要求
 - 功能特性测试 (C++20)
 - 工具库
 - 类型支持(基本类型、RTTI、类型特性)
 - 概念库 (C++20)
 - 错误处理
 - 动态内存管理
 - 日期和时间工具
 - 字符串库
 - 容器库
 - 迭代器库
 - 范围库 (C++20)
 - 算法库
 - 数值库
 - 输入/输出库
 - 文件系统库
 - 本地化库
 - 正则表达式库
 - 原子操作库
 - 线程支持库
 - 实验性 C++ 特性
 - 有用的资源
 - 索引
 - std 符号索引
 - 协程支持 (C++20)
 - C++ 关键词
 
复制初始化
从另一对象初始化对象
语法
 T object = other;
 | 
(1) | ||||||||
 T object = {other} ;
 | 
(2) | (C++11 前) | |||||||
 f(other)
 | 
(3) | ||||||||
 return other;
 | 
(4) | ||||||||
 throw object;
  | 
(5) | ||||||||
 T array[N] = {other};
 | 
(6) | ||||||||
解释
复制初始化在下列情况进行:
1) 当声明非引用类型 
T 的具名变量(自动、静态或线程局部),带有以等号后随一个表达式所构成的初始化器时。3) 当按值传递参数到函数时
4) 当从具有返回值的函数返回时
6) 作为聚合初始化的一部分,以初始化提供了初始化器的每个元素
复制初始化的效果为:
| (C++17 起) | 
-  若 
T为类类型,且 other 的类型的无 cv 限定版本是T或是从T派生的类,则检测T的非显式构造函数,并由重载决议选择最佳匹配。然后调用构造函数以初始化该对象。 
-  若 
T为类类型,且 other 的类型的无 cv 限定版本并非是T或从T派生,或若T是非类类型,但 other 的类型为类类型,则检测能从 other 的类型转换到T(或当T是类类型且存在转换函数时,转换到从T派生的类型)的用户定义转换序列,并通过重载决议选择最佳者。该转换的结果,若使用转换构造函数则为纯右值临时量 (C++17 前)纯右值表达式 (C++17 起),随后被用于直接初始化该对象。最后一步通常会被优化掉,而直接将转换结果构造于分配给目标对象的内存之中,但即便不会使用,也要求适合的构造函数(移动或复制)是可以访问的。 (C++17 前) 
-  否则(若 
T和 other 的类型均不是类类型),若需要,则用标准转换将 other 的值转换成T的无 cv 限定版本。 
注解
复制初始化不如直接初始化自由:explicit 构造函数不是转换构造函数,而不被复制初始化所考虑。
struct Exp { explicit Exp(const char*) {} }; // 不可从 const char* 转换 Exp e1("abc"); // OK Exp e2 = "abc"; // 错误,复制初始化不考虑 explicit 构造函数 struct Imp { Imp(const char*) {} }; // 可从 const char* 转换 Imp i1("abc"); // OK Imp i2 = "abc"; // OK
另外,复制初始化中的隐式转换必须从初始化器直接生成 T,然而直接初始化则期待一个从初始化器到 T 的构造函数实参的隐式转换。
struct S { S(std::string) {} }; // 可从 std::string 转换 S s("abc"); // OK:从 const char[4] 转换到 std::string S s = "abc"; // 错误:无从 const char[4] 到 S 的转换 S s = "abc"s; // OK:从 std::string 转换到 S
若 other 是右值表达式,则重载决议选择移动构造函数并在复制初始化期间调用它。没有“移动初始化”的概念。
隐式转换以复制初始化的方式定义:若能以表达式 E 复制初始化 T 类型对象,则可隐式转换 E 为 T。
具名变量的复制初始化中的等号 = 与赋值运算符无关。重载的赋值运算符对复制初始化没有影响。
示例
运行此代码
#include <string> #include <utility> #include <memory> struct A { operator int() { return 12; } }; struct B { B(int) {} }; int main() { std::string s = "test"; // OK:构造函数非 explicit std::string s2 = std::move(s); // 此复制初始化进行移动 // std::unique_ptr<int> p = new int(1); // 错误:构造函数为 explicit std::unique_ptr<int> p(new int(1)); // OK:直接初始化 int n = 3.14; // 浮点整型转换 const int b = n; // 不受 const 与否 int c = b; // ……影响 A a; B b0 = 12; // B b1 = a; // < 错误:要求从 'A' 到非标量类型 'B' 的转换 B b2{a}; // < 等同:调用 A::operator int() ,然后是::B(int) B b3 = {a}; // < auto b4 = B{a}; // < // b0 = a; // < 错误:需要重载赋值运算符 }