C++
编译器支持
自由(freestanding)与宿主(hosted)
语言
标准库
标准库头文件
具名要求
特性测试宏 (C++20)
语言支持库
概念库 (C++20)
诊断库
内存管理库
元编程库 (C++11)
通用工具库
容器库
迭代器库
范围库 (C++20)
算法库
字符串库
文本处理库
数值库
日期和时间库
输入/输出库
文件系统库 (C++17)
并发支持库 (C++11)
执行控制库 (C++26)
技术规范
符号索引
外部库
[编辑] C++ 语言
通用主题
预处理器
注释
关键词
转义序列
流程控制
条件执行语句
if
switch
迭代语句(循环)
for
范围-for (C++11)
while
do-while
跳转语句
continue - break
goto - return
函数
函数声明
Lambda 函数表达式
inline 说明符
动态异常规范 (直到 C++17*)
noexcept 说明符 (C++11)
异常
throw 表达式
try 块
catch 处理程序
命名空间
命名空间声明
命名空间别名
类型
基本类型
枚举类型
函数类型
类/结构体类型
联合类型
说明符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
存储期说明符
初始化
默认初始化
值初始化
零初始化
复制初始化
直接初始化
聚合初始化
列表初始化 (C++11)
常量初始化
引用初始化
表达式
值类别
求值顺序
运算符
运算符优先级
替代表示
字面量
布尔 - 整型 - 浮点型
字符 - 字符串 - nullptr (C++11)
用户定义 (C++11)
工具
属性 (C++11)
类型
typedef 声明
类型别名声明 (C++11)
类型转换
隐式转换
static_cast
const_cast
显式转换
dynamic_cast
reinterpret_cast
内存分配
new 表达式
delete 表达式
类
类声明
构造函数
this 指针
访问说明符
friend 说明符
类特有的函数属性
虚函数
override 说明符 (C++11)
final 说明符 (C++11)
explicit (C++11)
static
特殊成员函数
默认构造函数
复制构造函数
移动构造函数 (C++11)
复制赋值
移动赋值 (C++11)
析构函数
模板
类模板
函数模板
模板特化
参数包 (C++11)
杂项
内联汇编
C++ 历史
[编辑] 表达式
通用
值类别
求值顺序
常量表达式
主表达式
Lambda 表达式 (C++11)
Requires 表达式 (C++20)
包索引表达式 (C++26)
潜在求值表达式
字面量
整数字面量
浮点数字面量
布尔字面量
字符字面量
转义序列
字符串字面量
空指针字面量 (C++11)
用户定义字面量 (C++11)
运算符
赋值运算符
递增和递减
算术运算符
逻辑运算符
比较运算符
成员访问运算符
其他运算符
new 表达式
delete 表达式
throw 表达式
alignof
sizeof
sizeof... (C++11)
typeid
noexcept (C++11)
折叠表达式 (C++17)
运算符的替代表示
优先级和结合性
运算符重载
默认比较 (C++20)
转换
隐式转换
显式转换
常用算术转换
用户定义转换
const_cast
static_cast
dynamic_cast
reinterpret_cast
[编辑]
赋值运算符修改对象的值。
运算符名称
语法
可重载
原型示例(对于 class T)
类定义内部
类定义外部
简单赋值
a = b
是
T& T::operator =(const T2& b);
不适用
加法赋值
a += b
是
T& T::operator +=(const T2& b);
T& operator +=(T& a, const T2& b);
减法赋值
a -= b
是
T& T::operator -=(const T2& b);
T& operator -=(T& a, const T2& b);
乘法赋值
a *= b
是
T& T::operator *=(const T2& b);
T& operator *=(T& a, const T2& b);
除法赋值
a /= b
是
T& T::operator /=(const T2& b);
T& operator /=(T& a, const T2& b);
取余赋值
a %= b
是
T& T::operator %=(const T2& b);
T& operator %=(T& a, const T2& b);
按位与赋值
a &= b
是
T& T::operator &=(const T2& b);
T& operator &=(T& a, const T2& b);
按位或赋值
a |= b
是
T& T::operator |=(const T2& b);
T& operator |=(T& a, const T2& b);
按位异或赋值
a ^= b
是
T& T::operator ^=(const T2& b);
T& operator ^=(T& a, const T2& b);
按位左移赋值
a <<= b
是
T& T::operator <<=(const T2& b);
T& operator <<=(T& a, const T2& b);
按位右移赋值
a >>= b
是
T& T::operator >>=(const T2& b);
T& operator >>=(T& a, const T2& b);
注意
所有内置赋值运算符都返回 *this,大多数用户定义重载也返回 *this,以便用户定义的运算符可以像内置运算符一样使用。然而,在用户定义运算符重载中,任何类型都可以用作返回类型(包括 void)。 T2 可以是包括 T 在内的任何类型。
目录
1 定义
2 赋值运算符语法
3 内置简单赋值运算符
3.1 从表达式赋值
3.2 从非表达式初始化子句赋值
4 内置复合赋值运算符
5 示例
6 缺陷报告
7 参阅
[编辑] 定义
复制赋值将对象 a 的内容替换为 b 内容的副本(b 不会被修改)。对于类类型,这在特殊的成员函数中执行,详见复制赋值运算符。
移动赋值将对象 a 的内容替换为 b 的内容,如果可能则避免复制(b 可能会被修改)。对于类类型,这在特殊的成员函数中执行,详见移动赋值运算符。
(C++11 起)
对于非类类型,复制赋值和移动赋值无法区分,统称为直接赋值。
复合赋值将对象 a 的内容替换为 a 的先前值与 b 的值之间二元操作的结果。
[编辑] 赋值运算符语法
赋值表达式的形式为
target-expr = new-value
(1)
target-expr op new-value
(2)
target-expr
-
要赋值的表达式[1]
op
-
以下之一:*=, /= %=, += -=, <<=, >>=, &=, ^=, |=
new-value
-
赋值给目标的表达式[2](直到 C++11)初始化子句(从 C++11 开始)
↑ target-expr 必须具有比赋值表达式更高的优先级。
↑ new-value 不能是逗号表达式,因为它的优先级较低。
1) 简单赋值表达式。
2) 复合赋值表达式。
如果 new-value 不是表达式,则赋值表达式永远不会匹配重载的复合赋值运算符。
(C++11 起)
[编辑] 内置简单赋值运算符
对于内置简单赋值,target-expr 必须是可修改的左值。
由 target-expr 引用的对象通过将其值替换为 new-value 的结果而被修改。如果引用的对象是整型 T,并且 new-value 的结果是对应的有符号/无符号整型,则对象的值将替换为类型 T 的值,其值表示与 new-value 的结果相同。
内置简单赋值的结果是 target-expr 类型的左值,引用 target-expr。如果 target-expr 是位域,则结果也是位域。
[编辑] 从表达式赋值
如果 new-value 是表达式,它会隐式转换为 target-expr 的 cv-无限定类型。当 target-expr 是不能表示表达式值的位域时,位域的最终值是实现定义的。
如果 target-expr 和 new-value 标识重叠对象,则行为未定义(除非重叠完全且类型相同)。
如果 target-expr 的类型是 volatile 限定的,则赋值被弃用,除非(可能带括号的)赋值表达式是丢弃值表达式或未求值操作数。
(C++20 起)
从非表达式初始化子句赋值
new-value 仅在以下情况才允许不是表达式:
target-expr 是标量类型 T,并且 new-value 为空或只有一个元素。在这种情况下,给定一个发明的变量 t 声明并初始化为 T t = new-value ,x = new-value 的含义是 x = t。 target-expr 是类类型。在这种情况下,new-value 作为通过重载决议选择的赋值运算符函数的参数传递。
#include
std::complex
z = {1, 2}; // meaning z.operator=({1, 2})
z += {1, 2}; // meaning z.operator+=({1, 2})
int a, b;
a = b = {1}; // meaning a = b = 1;
a = {1} = b; // syntax error
(C++11 起)
在针对用户定义运算符的重载决议中,对于每种类型 T,以下函数签名参与重载决议:
T*& operator=(T*&, T*);
T*volatile & operator=(T*volatile &, T*);
对于每个枚举类型或指向成员的指针类型 T(可选 volatile 限定),以下函数签名参与重载决议:
T& operator=(T&, T);
对于每对 A1 和 A2,其中 A1 是算术类型(可选 volatile 限定),A2 是提升的算术类型,以下函数签名参与重载决议:
A1& operator=(A1&, A2);
[编辑] 内置复合赋值运算符
每个内置复合赋值表达式 target-expr op = new-value 的行为与表达式 target-expr = target-expr op new-value 的行为完全相同,除了 target-expr 只被求值一次。
对内置简单赋值运算符的 target-expr 和 new-value 的要求也适用。此外
对于 += 和 -=,target-expr 的类型必须是算术类型或指向(可能 cv 限定的)完全定义对象类型的指针。对于所有其他复合赋值运算符,target-expr 的类型必须是算术类型。
在针对用户定义运算符的重载决议中,对于每对 A1 和 A2,其中 A1 是算术类型(可选 volatile 限定),A2 是提升的算术类型,以下函数签名参与重载决议:
A1& operator*=(A1&, A2);
A1& operator/=(A1&, A2);
A1& operator+=(A1&, A2);
A1& operator-=(A1&, A2);
对于每对 I1 和 I2,其中 I1 是整型(可选 volatile 限定),I2 是提升的整型,以下函数签名参与重载决议:
I1& operator%=(I1&, I2);
I1& operator<<=(I1&, I2);
I1& operator>>=(I1&, I2);
I1& operator&=(I1&, I2);
I1& operator^=(I1&, I2);
I1& operator|=(I1&, I2);
对于每个可选 cv 限定的对象类型 T,以下函数签名参与重载决议:
T*& operator+=(T*&, std::ptrdiff_t);
T*& operator-=(T*&, std::ptrdiff_t);
T*volatile & operator+=(T*volatile &, std::ptrdiff_t);
T*volatile & operator-=(T*volatile &, std::ptrdiff_t);
[编辑] 示例
运行此代码
#include
int main()
{
int n = 0; // not an assignment
n = 1; // direct assignment
std::cout << n << ' ';
n = {}; // zero-initialization, then assignment
std::cout << n << ' ';
n = 'a'; // integral promotion, then assignment
std::cout << n << ' ';
n = {'b'}; // explicit cast, then assignment
std::cout << n << ' ';
n = 1.0; // floating-point conversion, then assignment
std::cout << n << ' ';
// n = {1.0}; // compiler error (narrowing conversion)
int& r = n; // not an assignment
r = 2; // assignment through reference
std::cout << n << ' ';
int* p;
p = &n; // direct assignment
p = nullptr; // null-pointer conversion, then assignment
std::cout << p << ' ';
struct { int a; std::string s; } obj;
obj = {1, "abc"}; // assignment from a braced-init-list
std::cout << obj.a << ':' << obj.s << '\n';
}
可能的输出
1 0 97 98 1 2 (nil) 1:abc
[编辑] 缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告
应用于
发布时的行为
正确的行为
CWG 1527
C++11
对于类类型对象的赋值,右操作数只能是初始化列表,当赋值由用户定义的赋值运算符定义时
移除用户定义赋值约束
CWG 1538
C++11
E1 = {E2} 等价于 E1 = T(E2)(T 是 E1 的类型),这引入了 C 风格的转换
它等价于E1 = T{E2}
CWG 2654
C++20
volatile 限定类型的复合赋值运算符被不一致地弃用
它们都没有被弃用
CWG 2768
C++11
从非表达式初始化子句赋值到标量值会执行直接列表初始化
改为执行复制列表初始化
CWG 2901
C++98
通过 int 左值赋值给 unsigned int对象的值不明确
已明确
P2327R1
C++20
volatile 类型的按位复合赋值运算符在某些平台上很有用,但被弃用
它们没有被弃用
[编辑] 另请参阅
运算符优先级
运算符重载
常见运算符
赋值
递增递减
算术
逻辑
比较
成员访问
其他
a = ba += ba -= ba *= ba /= ba %= ba &= ba |= ba ^= ba <<= ba >>= b
++a
--aa++a--
+a
-aa + ba - ba * ba / ba % b~aa & ba | ba ^ ba << ba >> b
!aa && ba || b
a == ba != ba < ba > ba <= ba >= ba <=> b
a[...]
*a
&aa->ba.ba->*ba.*b
函数调用a(...)
逗号a, b
条件a ? b : c
特殊运算符
static_cast 将一种类型转换为另一种相关类型
dynamic_cast 在继承层次结构内进行转换
const_cast 添加或移除 cv-限定符
reinterpret_cast 将类型转换为不相关类型
C 风格转换通过 static_cast、const_cast 和 reinterpret_cast 的混合将一种类型转换为另一种类型
new 创建具有动态存储期的对象
delete 销毁先前由 new 表达式创建的对象并释放获得的内存区域
sizeof 查询类型的大小
sizeof... 查询 包 的大小 (C++11 起)
typeid 查询类型的类型信息
noexcept 检查表达式是否可以抛出异常 (C++11 起)
alignof 查询类型的对齐要求 (C++11 起)
C 文档,关于 赋值运算符
