比较运算符
C++
编译器支持
自立实现与有宿主实现
语言
标准库
标准库标头
具名要求
功能特性测试宏 (C++20)
语言支持库
概念库
(C++20)
元编程库 (C++11)
诊断库
通用工具库
字符串库
容器库
迭代器库
范围库
(C++20)
算法库
数值库
本地化库
输入/输出库
文件系统库 (C++17)
正则表达式库
(C++11)
并发支持库
(C++11)
技术规范
符号索引
外部库
C++ 语言
表达式
概述
值类别(左值 lvalue、右值
rvalue、亡值 xvalue)
求值顺序(序列点)
常量表达式
潜在求值表达式
初等表达式
lambda 表达式(C++11)
字面量
整数字面量
浮点字面量
布尔字面量
字符字面量,包含转义序列
字符串字面量
空指针字面量(C++11)
用户定义字面量(C++11)
运算符
赋值运算符:
a=b,a+=b,a-=b,a*=b,a/=b,a%=b,a&=b,a|=b,a^=b,a<<=b,a>>=b
自增与自减:++a,--a,a++,a--
算术运算符:
+a,-a,a+b,a-b,a*b,a/b,a%b,~a,a&b,a|b,a^b,a<>b
逻辑运算符:a||b,a&&b,!a
比较运算符:a==b,a!=b,ab,a<=b,a>=b,a<=>b(C++20)
成员访问运算符:a[b],*a,&a,a->b,a.b,a->*b,a.*b
其他运算符:a(...),a,b,a?b:c
new
表达式
delete 表达式
throw 表达式
alignof
sizeof
sizeof...(C++11)
typeid
noexcept(C++11)
折叠表达式(C++17)
运算符的代用表示
优先级和结合性
运算符重载
默认比较(C++20)
类型转换
隐式转换
一般算术转换
const_cast
static_cast
reinterpret_cast
dynamic_cast
显式转换
(T)a, T(a)
用户定义转换
比较参数。
运算符名
语法
可重载
原型示例(对于 class
T)
类内定义
类外定义
等于
a == b
是
bool
T::operator==(const T2& b) const;
bool
operator==(const T& a, const T2& b);
不等于
a != b
是
bool
T::operator!=(const T2& b) const;
bool
operator!=(const T& a, const T2& b);
小于
a < b
是
bool
T::operator<(const T2& b) const;
bool
operator<(const T& a, const T2& b);
大于
a > b
是
bool
T::operator>(const T2& b) const;
bool
operator>(const T& a, const T2& b);
小于或等于
a <= b
是
bool
T::operator<=(const T2& b) const;
bool
operator<=(const T& a, const T2& b);
大于或等于
a >= b
是
bool
T::operator>=(const T2& b) const;
bool
operator>=(const T& a, const T2& b);
三路比较(C++20)
a <=> b
是
/*R*/ T::operator<=>(const T2& b) const;
/*R*/ operator<=>(const T& a, const T2& b);
注解
内建运算符返回 bool,所以大多数用户定义重载也返回 bool
以使用户定义运算符能以与内建运算符相同的方式使用。然而,在用户定义运算符重载中,任何类型都可用作返回类型(包含 void)。
T2 可以是包括 T 在内的任何类型
/*R*/ 是 operator<=> 的返回类型(见下文)
双路比较
双路比较运算符表达式的形式为
左操作数 < 右操作数
(1)
左操作数 > 右操作数
(2)
左操作数 <= 右操作数
(3)
左操作数 >= 右操作数
(4)
左操作数 == 右操作数
(5)
左操作数 != 右操作数
(6)
1) 在 左操作数 小于 右操作数 时返回 true,否则返回 false。
2) 在 左操作数 大于 右操作数 时返回 true,否则返回 false。
3) 在 左操作数 小于或等于 右操作数 时返回 true,否则返回 false。
4) 在 左操作数 大于或等于 右操作数 时返回 true,否则返回 false。
5) 在 左操作数 等于 右操作数 时返回 true,否则返回 false。
6) 在 左操作数 不等于 右操作数 时返回 true,否则返回 false。
所有情况下,对于内建运算符,左操作数 和 右操作数 在应用左值到右值、数组到指针和函数到指针标准转换后,必须具有下列类型之一
算术或枚举类型(见下文的算术比较运算符)
指针类型(见下文的指针比较运算符)
如果两个运算数在应用这些转换前均具有数组类型,那么这种比较被弃用。 (C++20 起)
任何情况下,结果都是 bool 纯右值。
算术比较运算符
如果两个操作数具有算术或(有作用域或无作用域)枚举类型,那么遵循算术运算符的规则,对两个操作数实施一般算术转换。转换之后进行值的比较:
示例
运行此代码
#include
int main()
{
std::cout << std::boolalpha;
int n = -1;
int n2 = 1;
std::cout << " -1 == 1? " << (n == n2) << '\n'
<< "比较两个有符号值:\n"
<< " -1 < 1? " << (n < n2) << '\n'
<< " -1 > 1? " << (n > n2) << '\n';
unsigned int u = 1;
std::cout << "比较有符号与无符号值:\n"
<< " -1 < 1? " << (n < u) << '\n'
<< " -1 > 1? " << (n > u) << '\n';
static_assert(sizeof(unsigned char) < sizeof(int),
"不能正确地比较有符号值与较小的无符号值");
unsigned char uc = 1;
std::cout << "比较无符号值和较小的有符号值:\n"
<< " -1 < 1? " << (n < uc) << '\n'
<< " -1 > 1? " << (n > uc) << '\n';
}
输出:
-1 == 1? false
比较两个有符号值:
-1 < 1? true
-1 > 1? false
比较有符号与无符号值:
-1 < 1? false
-1 > 1? true
比较无符号值和较小的有符号值:
-1 < 1? true
-1 > 1? false
指针比较运算符
比较运算符能用于比较两个指针。
只有相等性运算符(operator== 与 operator!=)能用于比较下列指针对:
两个成员指针
一个空指针常量与一个指针或成员指针
一个 std::nullptr_t 值与一个空指针常量(也可以是
std::nullptr_t 值)
(C++11 起)
首先,对两个操作数应用指针转换(参数是成员指针时就是成员指针转换)、函数指针转换 (C++17 起)和限定性转换,以获得合成指针类型,规则如下:
1) 如果两个操作数都是空指针常量,那么合成指针类型是 std::nullptr_t
(C++11 起)
2) 如果一个操作数是空指针常量,而另一个是指针,那么合成类型正是该指针类型
3) 如果两个操作数分别是
指向 cv1 void 的指针,和
指向 cv2 T 的指针,其中 T 是对象类型或 void,
那么合成类型是“指向 cv12 void 的指针”,其中 cv12 是 cv1 与 cv2 的合并
4) 如果两个操作数的类型分别是
指向(可有 cv 限定的)T1 的指针 P1,和
指向(可有 cv 限定的)T2 的指针 P2,
且如果 T1 与 T2 相同或是 T2 的基类,那么合成指针类型是 P1 与
P2 的 cv 结合类型。否则,如果 T2 是 T1 的基类,那么合成指针类型是
P2 与 P1 的 cv 结合类型。
5) 如果两个操作数的类型分别是
指向 T1 的成员,它的类型是(可有 cv 限定的)U1,的指针 MP1,和
指向 T2 的成员,它的类型是(可有 cv 限定的)U2,的指针 MP2,
且如果 T1 与 T2 相同或派生自 T2,那么合成指针类型是 MP1 与
MP2 的 cv 结合类型。否则,如果 T2 派生自 T1,那么合成指针类型是
MP2 与 MP1 的 cv 结合类型。
6) 如果操作数 P1 和 P2
的类型具有相同层数的多层混合指针和成员指针类型,而仅在任意层上的 cv 限定性不同,那么合成指针类型是 P1 与 P2 的 cv
结合类型
在上面的定义中,两个指针类型 P1 和 P2 的 cv 结合类型,是与 P1
拥有相同的层数且每层具有与 P1 相同类型的类型 P3,其中每层上的 cv 限定性设定如下:
a) 除顶层之外的每层,它的 cv 限定性是该层上 P1 与
P2 的 cv 限定性的合并
b) 如果有任何层上得到的 cv 限定性与同一层上 P1 或
P2 的 cv 限定性不同,那么对顶层和此层之间的每一层添加 const。
例如,void* 与 const int*
的合成指针类型是 const void*。int** 与 const int**
的合成指针类型是 const int* const*。注意,在解决 CWG 问题 1512(N3624)之前无法比较 int** 和 const int**。
除上述之外,函数指针和指向 noexcept 函数的指针(只要函数类型相同)的合成指针类型是函数指针。
(C++17 起)
注意这意味着任何指针都能与 void* 进行比较。
两个(转换后的)对象指针的比较结果定义如下:
1)
如果两个指针指向同一数组的不同元素,或同一数组的不同元素内的子对象,那么指向拥有较高下标的元素的指针比较大于另一指针。换言之,比较指针的结果与比较它们所指向的元素下标结果相同。
2)
如果一个指针指向数组元素,或数组元素的子对象,而另一指针指向数组末尾元素后一位置,那么后者比较大于前者。指向单个对象的指针被当做指向单元素数组的指针:&obj + 1 比较大于 &obj。
3) 如果在非联合体类类型的对象内,两个指针指向拥有相同成员访问的 (C++23 前)非零大小的 (C++20
起)不同非静态数据成员,或(递归地)指向这种成员的子对象或数组元素,那么指向较后声明的成员的指针比较大于另一指针。换言之,三个成员访问模式的每一者中的类成员按声明顺序置于内存中。
两个(转换后的)指针的相等性比较的结果定义如下:
1) 如果两个指针都是空指针值,那么它们比较相等
2) 如果两个指针都是函数指针且指向同一函数,那么它们比较相等
3)
如果两个指针都是对象指针且表示相同地址,那么它们比较相等(这包括两个指向同一联合体的不同非静态成员的指针,指向标准布局结构体与它的首成员的指针,由 reinterpret_cast 关联的指针等)
4) 所有其他指针的比较都不相等。
两个(转换后的)成员指针的比较结果定义如下:
1) 如果两个成员指针都是空成员指针值,那么它们比较相等。
2) 否则,如果两个成员指针之一是空成员指针值,那么它们比较不相等。
3) 否则,如果其中之一是指向虚成员函数的指针,那么结果未指明。
4) 否则,如果其中一个成员指针表示类 C1 的成员而另一成员指针表示不同类
C2 的成员,且 C1 和 C2 都不是对方的基类,那么结果未指明。
struct A {};
struct B : A { int x; };
struct C : A { int x; };
int A::*bx = (int(A::*)) &B::x;
int A::*cx = (int(A::*)) &C::x;
bool b1 = (bx == cx); // 未指明
5) 否则,如果它们都表示同一个联合体的(可能不同的)成员,那么它们比较相等。
6)
否则,当且仅当以一个它们的关联类类型的假想对象对它们解引用时,它们会指代同一最终派生对象或同一子对象的相同成员,两个成员指针相等。
7) 否则它们的比较不相等。
struct B
{
int f();
};
struct L : B {};
struct R : B {};
struct D : L, R {};
int (B::*pb)() = &B::f;
int (L::*pl)() = pb;
int (R::*pr)() = pb;
int (D::*pdl)() = pl;
int (D::*pdr)() = pr;
bool x = (pdl == pdr); // false
bool y = (pb == pl); // true
如果指针 p 比较等于指针 q,那么 p <= q 和 p >=
q 都会得到 true 而 p < q 和 p >
q 都会得到 false。
如果指针 p 比较大于指针 q,那么 p >= q、p >
q、q <= p 和 q < p 都会得到
true 而 p <= q、p <
q、q >= p 和 q > p 都会得到
false。
如果未指明两个指针的比较大于或比较相等,那么它们的比较结果未指明。该结果可以不确定,并且甚至不必在程序的同一次执行中,在拥有相同操作数的相同表达式的多次求值之间保持一致:
int x, y;
bool f(int* p, int* q) { return p < q; }
assert(f(&x, &y) == f(&x, &y)); // 在遵从标准的实现中可能会引发断言
在针对用户定义运算符的重载决议中,对于(包括枚举类型的)每个提升后算术类型
L 和 R,下列函数签名参与重载决议:
bool
operator<(L, R);
bool
operator>(L, R);
bool
operator<=(L, R);
bool
operator>=(L, R);
bool
operator==(L, R);
bool
operator!=(L, R);
对于每个对象指针或函数指针的类型 P,下列函数签名参与重载决议:
bool
operator<(P, P);
bool
operator>(P, P);
bool
operator<=(P, P);
bool
operator>=(P, P);
bool
operator==(P, P);
bool
operator!=(P, P);
对于每个是成员对象指针、成员函数指针或 std::nullptr_t 的类型 MP,下列函数签名参与重载决议:
bool
operator==(MP, MP);
bool
operator!=(MP, MP);
示例
运行此代码
#include
struct Foo { int n1; int n2; };
union Union { int n; double d; };
int main()
{
std::cout << std::boolalpha;
char a[4] = "abc";
char* p1 = &a[1];
char* p2 = &a[2];
std::cout << "指向数组元素的指针:p1 == p2 " << (p1 == p2)
<< ", p1 < p2 " << (p1 < p2) << '\n';
Foo f;
int* p3 = &f.n1;
int* p4 = &f.n2;
std::cout << "指向类成员的指针:p3 == p4 " << (p3 == p4)
<< ", p3 < p4 " << (p3 < p4) << '\n';
Union u;
int* p5 = &u.n;
double* p6 = &u.d;
std::cout << "指向联合体成员的指针:p5 == (void*)p6 " << (p5 == (void*)p6)
<< ", p5 < p6 " << (p5 < (void*)p6) << '\n';
}
输出:
指向数组元素的指针:p1 == p2 false, p1 < p2 true
指向类成员的指针:p3 == p4 false, p3 < p4 true
指向联合体成员的指针:p5 == (void*)p6 true, p5 < p6 false
注解
因为这些运算符从左到右组合,所以表达式 a < b < c 会被解析为 (a < b) <
c,而不是 a < (b <
c) 或 (a < b) && (b < c)。
运行此代码
#include
int main()
{
int a = 3, b = 2, c = 1;
std::cout << std::boolalpha
<< (a < b < c) << '\n' // true;可能会有警告
<< ((a < b) < c) << '\n' // true
<< (a < (b < c)) << '\n' // false
<< ((a < b) && (b < c)) << '\n'; // false
}
对用户定义的 operator< 的一项常见要求是严格弱序。尤其是,用比较 (Compare)
类型进行工作的标准算法和容器如 std::sort、std::max_element、std::map 等都对此有所要求。
尽管未指明对随机来源(例如不都指向同一数组中的成员)的指针比较的结果,许多实现都提供指针的严格全序,例如它们被实现为连续的虚拟地址空间中的地址。不这样做的实现(例如并非指针的所有位都是内存地址的一部分而在比较中必须被忽略,或要求进行额外的计算否则指针与整数并非一对一关系),为指针提供具有这项保证的
std::less
的特化。这使得程序可以将随机来源的所有指针都用作标准关联容器(如 std::set 或 std::map)的键。
对于同时满足可相等比较 (EqualityComparable)
和可小于比较 (LessThanComparable)
的类型,C++ 标准库在相等(即表达式 a == b 的值),和等价(即表达式 !(a
< b) && !(b
< a) 的值)之间做出区别。
N3624 中包含的 CWG 问题 583 的解决方案移除了指针与空指针常量间的比较。
运行此代码
void f(char * p)
{
if (p > 0) { /*...*/ } // 用 N3624 出错, N3624 前可编译
if (p > nullptr) { /*...*/ } // 用 N3624 出错, N3624 前可编译
}
int main() {}
三路比较
三路比较运算符表达式的形式为
左操作数
<=> 右操作数
表达式返回一个对象,使得
如果 a < b,那么 (a <=> b) < 0
如果 a > b,那么 (a <=> b) > 0
而如果 a 和
b 相等/等价,那么
(a <=> b) == 0。
如果操作数之一是 bool
类型而另一个不是,那么程序非良构。
如果两个操作数均具有算术类型,或一个具有无作用域枚举类型而另一个具有整数类型,那么对各操作数应用一般算术转换,然后
如果需要进行除了从整数类型到浮点类型之外的窄化转换,那么程序非良构。
否则,如果各操作数均具有整数类型,那么运算符产出 std::strong_ordering
类型的纯右值:
如果两个操作数算术上相等则为 std::strong_ordering::equal,
如果第一操作数算术上小于第二个则为 std::strong_ordering::less
否则为 std::strong_ordering::greater。
否则,操作数均具有浮点类型,而运算符产出 std::partial_ordering
类型的纯右值。表达式 a <=> b 产出
如果 a 小于 b 则为
std::partial_ordering::less,
如果 a 大于 b 则为
std::partial_ordering::greater,
如果 a 等价于 b 则为
std::partial_ordering::equivalent(-0 <=> +0 为等价),
否则为 std::partial_ordering::unordered(NaN <=> 任何值 为无序)。
如果两个操作数都具有相同的枚举类型 E,那么运算符产出将各操作数转换到 E 的底层类型再对转换后的操作数应用 <=> 的结果。
如果至少一个操作数是指针或成员指针,那么按需应用数组到指针转换、派生类到基类指针转换、函数指针转换和限定性转换,以将它们转换到同一指针类型,且结果指针类型是对象指针类型,那么
p <=> q 返回 std::strong_ordering
类型的纯右值:
如果 p == q 则为 std::strong_ordering::equal
如果 q > p 则为 std::strong_ordering::less
如果 p > q 则为 std::strong_ordering::greater。
如果未指明这些指针值的比较(例如它们不指向同一对象或数组之中时),那么结果未指明。
否则程序非良构。
在针对用户定义运算符的重载决议中,对于指针或枚举类型
T,下列函数签名参与重载决议:
R operator<=>(T,
T);
其中 R 是上文所定义的顺序类别类型。
示例
运行此代码
#include
#include
int main()
{
double foo = -0.0;
double bar = 0.0;
auto res = foo <=> bar;
if (res < 0)
std::cout << "-0 小于 0";
else if (res > 0)
std::cout << "-0 大于 0";
else // (res == 0)
std::cout << "-0 与 0 相等";
else
std::cout << "-0 与 0 无序";
}
输出:
-0 与 0 相等
注解
类类型可以自动生成三路比较,见默认比较。
如果两个运算数都是数组,那么三路比较非良构。
unsigned int i = 1;
auto r = -1 < i; // 既存陷阱:返回 false
auto r2 = -1 <=> i; // 错误:要求窄化转换
(C++20 起)
标准库
标准库中的许多类都重载了比较运算符。
operator==operator!=
(C++20 中移除)
检查对象是否指代相同类型 (std::type_info 的公开成员函数)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20)
比较两个 error_code (函数)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20)
比较 error_condition 和 error_code (函数)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20)
按字典序比较 pair 中的值 (函数模板)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20)
按字典顺序比较 tuple 中的值 (函数模板)
operator==operator!=
(C++20 中移除)
比较其内容 (std::bitset
operator==operator!=
(C++20 中移除)
比较两个分配器实例 (std::allocator
的公开成员函数)
operator==operator!=operator
(C++20
中移除)(C++20)
与另一个 unique_ptr 或 nullptr 进行比较 (函数模板)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20)
与另一个 shared_ptr 或 nullptr 进行比较 (函数模板)
operator==operator!=
(C++20 中移除)
比较 std::function 和 nullptr (函数模板)
operator==operator!=operator
(C++11)(C++11)(C++20
中移除)(C++11)(C++11)(C++11)(C++11)(C++20)
比较两个时长 (函数模板)
operator==operator!=operator
(C++11)(C++11)(C++20
中移除)(C++11)(C++11)(C++11)(C++11)(C++20)
比较两个时间点 (函数模板)
operator==operator!=
(C++20 中移除)
比较两个 scoped_allocator_adaptor 实例 (std::scoped_allocator_adaptor
的公开成员函数)
operator==operator!=operator
(C++20
中移除)(C++20)
比较底层 std::type_info 对象 (std::type_index 的公开成员函数)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20)
以字典序比较两个字符串 (函数模板)
operator==operator!=
(C++20 中移除)
locale 对象之间的相等性比较 (std::locale 的公开成员函数)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20)
按照字典顺序比较 array 中的值 (函数模板)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20)
按照字典顺序比较 deque 中的值 (函数模板)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20)
按照字典顺序比较 forward_list 中的值 (函数模板)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20)
按照字典顺序比较 list 中的值 (函数模板)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20)
按照字典顺序比较 vector 中的值 (函数模板)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20)
按照字典顺序比较 map 中的值 (函数模板)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20)
按照字典顺序比较 multimap 中的值 (函数模板)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20)
按照字典顺序比较 set 中的值 (函数模板)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20)
按照字典顺序比较 multiset 中的值 (函数模板)
operator==operator!=
(C++20 中移除)
比较 unordered_map 中的值 (函数模板)
operator==operator!=
(C++20 中移除)
比较 unordered_multimap 中的值 (函数模板)
operator==operator!=
(C++20 中移除)
比较 unordered_set 中的值 (函数模板)
operator==operator!=
(C++20 中移除)
比较 unordered_multiset 中的值 (函数模板)
operator==operator!=operator
(C++20)
按照字典顺序比较 queue 中的值 (函数模板)
operator==operator!=operator
(C++20)
按照字典顺序比较 stack 中的值 (函数模板)
operator==operator!=operator
(C++20)
比较迭代器底层迭代器 (函数模板)
operator==operator!=operator
(C++11)(C++11)(C++20
中移除)(C++11)(C++11)(C++11)(C++11)(C++20)
比较迭代器底层迭代器 (函数模板)
operator==operator!=
(C++20 中移除)
比较两个 istream_iterator (函数模板)
operator==operator!=
(C++20 中移除)
比较两个 istreambuf_iterator (函数模板)
operator==operator!=
(C++20 中移除)
比较两个复数,或一个复数与一个标量 (函数模板)
operator==operator!=operator
比较两个 valarrays,或比较一个 valarray 和一个值 (函数模板)
operator==operator!=
(C++11)(C++11)(C++20 中移除)
比较两个伪随机数引擎的内部状态 (函数)
operator==operator!=
(C++11)(C++11)(C++20 中移除)
比较两个分布对象 (函数)
operator==operator!=operator
(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20)
比较一个 sub_match 与另一 sub_match 、字符串或字符 (函数模板)
operator==operator!=
(C++20 中移除)
以字典序比较两个匹配结果的值 (函数模板)
operator==operator!=
(C++20 中移除)
比较两个 regex_iterator (std::regex_iterator
的公开成员函数)
operator==operator!=
(C++20 中移除)
比较两个 regex_token_iterator (std::regex_token_iterator
的公开成员函数)
operator==operator!=operator<
operator<= operator>
operator>= operator<=>
(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20
中移除)(C++20)
比较两个 thread::id 对象 (函数)
命名空间 std::rel_ops 提供了泛型运算符 !=、>、<= 及 >=
在标头
定义
在命名空间 std::rel_ops 定义
operator!=operator>operator<=operator>=
(C++20
中弃用)
自动生成基于用户定义的 operator== 和 operator< 的比较运算符 (函数模板)
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告
应用于
出版时的行为
正确行为
CWG 583(N3624)
C++98
所有六个比较运算符都能用来比较指针和空指针常量
只有相等性运算符可以
CWG 661
C++98
未指明算术比较的实际语义(例如 1 < 2 会生成 true 还是 false)
指明语义
CWG 879
C++98
指向函数类型或 void
的指针缺少内建比较
指明如何比较这些指针
CWG 1512(N3624)
C++98
合成指针类型的规则不完整,从而不允许 int** 与 const int** 间的比较
使之完整
CWG 1596
C++98
仅就指针算术的目的认为非数组对象属于拥有一个元素的数组
该规则也适用于比较
CWG 1598
C++98
两个成员指针在两个成员所属类不同且都不是对方的基类时不会比较相等,即使此时被指向的成员的偏移量可能相等
此时结果未指明
CWG 1858
C++98
表示相同联合体的不同成员的两个成员指针不明确是否会如同它们表示相同的成员那样比较相等
此时它们比较相等
CWG 2419
C++98
只有通过 & 获取的到非数组对象的指针才会在指针比较中被视为到大小为 1 的数组的首元素的指针
应用到所有到非数组对象的指针
CWG 2526
C++98
N3624 移除了指向
void
的指针和函数指针的关系比较(>、>=、< 和
<=)的定义
恢复原本定义
参阅
运算符优先级
运算符重载
比较 (Compare)
(具名要求)
常见运算符
赋值
自增/自减
算术
逻辑
比较
成员访问
其他
a =
b
a += b
a -= b
a *= b
a /= b
a %= b
a &= b
a |= b
a ^= b
a <<= b
a >>= b
++a
--a
a++
a--
+a
-a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b
!a
a && b
a || b
a ==
b
a != b
a < b
a > b
a <= b
a >= b
a <=> b
a[b]
*a
&a
a->b
a.b
a->*b
a.*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 起)