命名空间
变体
操作

比较运算符

来自 cppreference.cn
< cpp‎ | language
 
 
C++ 语言
通用主题
流程控制
条件执行语句
if
迭代语句 (循环)
for
范围 for (C++11)
跳转语句
函数
函数声明
Lambda 函数表达式
inline 说明符
动态异常规范 (在 C++17* 前已弃用)
noexcept 说明符 (C++11)
异常
命名空间
类型
说明符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
存储期说明符
初始化
 
 

比较参数。

运算符名称  语法  可重载 原型示例 (对于 class T)
在类定义内 在类定义外
等于 a == b bool T::operator==(const U& b) const; bool operator==(const T& a, const U& b);
不等于 a != b bool T::operator!=(const U& b) const; bool operator!=(const T& a, const U& b);
小于 a < b bool T::operator<(const U& b) const; bool operator<(const T& a, const U& b);
大于 a > b bool T::operator>(const U& b) const; bool operator>(const T& a, const U& b);
小于或等于 a <= b bool T::operator<=(const U& b) const; bool operator<=(const T& a, const U& b);
大于或等于 a >= b bool T::operator>=(const U& b) const; bool operator>=(const T& a, const U& b);
三路比较 (C++20) a <=> b T::operator<=>(const U& b) const;[1] operator<=>(const T& a, const U& b);[1]
注释
  • 当内建运算符返回 bool 时,大多数用户定义的重载也返回 bool,以便用户定义的运算符可以像内建运算符一样使用。但是,在用户定义的运算符重载中,任何类型都可以用作返回类型(包括 void)。
  • U 可以是任何类型,包括 T
  1. 1.0 1.1 Roperator<=> 的返回类型(见下文

内容

[编辑] 双向比较

双向比较运算符表达式具有以下形式

[编辑] 关系运算符
lhs < rhs (1)
lhs > rhs (2)
lhs <= rhs (3)
lhs >= rhs (4)
[编辑] 相等运算符
lhs == rhs (5)
lhs != rhs (6)
1) 如果 lhs 小于 rhs,则返回 true,否则返回 false
2) 如果 lhs 大于 rhs,则返回 true,否则返回 false
3) 如果 lhs 小于或等于 rhs,则返回 true,否则返回 false
4) 如果 lhs 大于或等于 rhs,则返回 true,否则返回 false
5) 如果 lhs 等于 rhs,则返回 true,否则返回 false
6) 如果 lhs 不等于 rhs,则返回 true,否则返回 false

[编辑] 内建双向比较运算符

对于内建双向比较运算符,左值到右值转换数组到指针转换(C++26 前)函数到指针转换 应用于 lhsrhs

如果 lhsrhs 在应用这些转换之前都具有数组类型,则比较已被弃用。

(自 C++20 起)
(C++26 前)

对于内建关系运算符,如果其中一个操作数是指针,则对另一个操作数执行 数组到指针转换

对于内建相等运算符,如果其中一个操作数是指针或空指针常量,则对另一个操作数执行数组到指针转换。

(自 C++26 起)

对于内建双向比较运算符,结果是 bool 右值。

[编辑] 内建算术比较

如果转换后的操作数都具有算术或枚举类型(带作用域或不带作用域),则对两个操作数执行常用算术转换。在转换后比较这些值

#include <iostream>
 
int main()
{
    static_assert(sizeof(unsigned char) < sizeof(int),
                  "Cannot compare signed and smaller unsigned properly");
    int a = -1;
    int b = 1;
    unsigned int c = 1;
    unsigned char d = 1;
 
    std::cout << std::boolalpha
              << "Comparing two signed values:\n"
                 " -1 == 1 ? " << (a == b) << "\n"
                 " -1 <  1 ? " << (a <  b) << "\n"
                 " -1 >  1 ? " << (a >  b) << "\n"
                 "Comparing signed and unsigned:\n"
                 // may issue different-signedness warning:
                 " -1 == 1 ? " << (a == c) << "\n"
                 // may issue different-signedness warning:
                 " -1 <  1 ? " << (a <  c) << "\n"
                 // may issue different-signedness warning:
                 " -1 >  1 ? " << (a >  c) << "\n"
                 "Comparing signed and smaller unsigned:\n"
                 " -1 == 1 ? " << (a == d) << "\n"
                 " -1 <  1 ? " << (a <  d) << "\n"
                 " -1 >  1 ? " << (a >  d) << '\n';
}

输出

Comparing two signed values:
 -1 == 1 ? false
 -1 <  1 ? true
 -1 >  1 ? false
Comparing signed and unsigned:
 -1 == 1 ? false
 -1 <  1 ? false
 -1 >  1 ? true
Comparing signed and smaller unsigned:
 -1 == 1 ? false
 -1 <  1 ? true
 -1 >  1 ? false

[编辑] 内建指针相等比较

相等运算符 ==!= 的转换后操作数也可以具有类型 std::nullptr_t(自 C++11 起) 指针类型或指向成员的指针类型。

内建指针相等比较有三种可能的结果:相等、不相等和未指定。下表列出了内建指针相等比较的相等运算符产生的值

 比较结果 
对于 pq
由以下项产生的值
p == q p != q
相等 true false
不相等 false true
未指定  未指定的 bool 值 

如果转换后的 lhsrhs 中至少有一个是指针,则对两个转换后的操作数执行指针转换函数指针转换(自 C++17 起)限定转换,以使它们达到其复合指针类型。两个复合指针类型的指针按如下方式比较

  • 表示一个不同完整非数组对象的末尾后地址,或
  • 表示一个不同完整数组对象的最后一个元素后地址,
则比较的结果是未指定的。
  • 否则,如果指针都为空,都指向同一个函数,或者都表示同一个地址(即,它们指向同一个对象或位于同一个对象的末尾之后),则它们比较相等。
  • 否则,指针比较不相等。

如果转换后的 lhsrhs 中至少有一个是指向成员的指针,则对两个转换后的操作数执行指向成员的指针转换函数指针转换(自 C++17 起)限定转换,以使它们达到其复合指针类型。两个复合指针类型的指向成员的指针按如下方式比较

  • 如果两个指向成员的指针都是空成员指针值,则它们比较相等。
  • 如果两个指向成员的指针中只有一个是空成员指针值,则它们比较不相等。
  • 如果其中一个是虚成员函数的指针,则结果是未指定的。
  • 如果一个指向类 C1 的成员,另一个指向不同类 C2 的成员,且两者都不是对方的基类,则结果是未指定的。
  • 如果两者都指向同一联合体的(可能不同的)成员,则它们比较相等。
  • 否则,如果两个指向成员的指针在通过假设的关联类类型的对象执行间接寻址时,将指向同一个最派生对象或同一个子对象,则它们比较相等,否则它们比较不相等。
struct P {};
struct Q : P { int x; };
struct R : P { int x; };
 
int P::*bx = (int(P::*)) &Q::x;
int P::*cx = (int(P::*)) &R::x;
 
bool b1 = (bx == cx); // unspecified
 
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

类型为 std::nullptr_t 的两个操作数,或者一个类型为 std::nullptr_t 的操作数和另一个空指针常量,比较相等。

(自 C++11 起)

[编辑] 内建指针关系比较

关系运算符 ><>=<= 的转换后操作数也可以具有指针类型。

对不相等指针 pq 的内建指针关系比较有三种可能的结果:p 较大,q 较大和未指定。下表列出了关系运算符对于内建指针关系比较产生的值

 比较结果 
对于 pq
由以下项产生的值
 p > q   p < q   p >= q   p <= q 
相等 false false true true
p 较大 true false true false
q 较大 false true false true
未指定 未指定的 bool

如果转换后的 lhsrhs 都是指针,则对两个转换后的操作数执行指针转换函数指针转换(自 C++17 起)限定转换,以使它们达到其复合指针类型。两个复合指针类型的指针按如下方式比较

  • 如果指针比较相等或相等比较结果未指定,则关系比较结果属于同一类别。
  • 否则(指针比较不相等),如果指针都不是指向对象的指针,则结果是未指定的。
  • 否则(两个指针都指向对象),结果根据与以下规则一致的部分顺序定义
  • 给定数组的两个不同元素 highlow,使得 high 的下标高于 low,如果一个指针指向 high(或 high 的子对象),而另一个指针指向 low(或 low 的子对象),则前者比较大于后者。
  • 如果一个指针指向数组的元素 elem(或 elem 的子对象),而另一个指针位于同一数组的末尾之后,则末尾后指针比较大于另一个指针。
  • 如果一个指针指向完整对象、基类子对象或成员子对象 obj(或 obj 的子对象),而另一个指针位于 obj 的末尾之后,则末尾后指针比较大于另一个指针。

  • 如果指针指向同一非联合类类型的同一对象的不同 非零大小的(自 C++20 起) 非静态数据成员,具有相同的成员访问权限(C++23 前),或此类成员的子对象(以递归方式),则指向稍后声明的成员的指针比较大于另一个指针。
  • 否则,结果是未指定的。

[编辑] 指针全序

每个程序中都存在一个实现定义的指针严格全序。严格全序与上述部分顺序一致:未指定的结果变为实现定义的,而其他结果保持不变。

在以下情况下应用具有严格全序的指针比较

(自 C++14 起)
(自 C++20 起)

[编辑] 重载

针对用户定义的运算符的重载决议中,对于每对提升的算术类型 LR(包括枚举类型),以下函数签名参与重载决议

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);

对于每种类型 MP,它是指向成员对象的指针或指向成员函数的指针std::nullptr_t(自 C++11 起),以下函数签名参与重载决议

bool operator==(MP, MP);
bool operator!=(MP, MP);
#include <iostream>
 
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 << "Pointers to array elements:\n"
              << "p1 == p2? " << (p1 == p2) << '\n'
              << "p1 <  p2? " << (p1 <  p2) << '\n';
 
    Foo f;
    int* p3 = &f.n1;
    int* p4 = &f.n2;
    std::cout << "Pointers to members of a class:\n"
              << "p3 == p4? " << (p3 == p4) << '\n'
              << "p3 <  p4? " << (p3 <  p4) << '\n';
 
    Union u;
    int* p5 = &u.n;
    double* p6 = &u.d;
    std::cout << "Pointers to members of a union:\n"
              << "p5 == (void*)p6? " << (p5 == (void*)p6) << '\n'
              << "p5 <  (void*)p6? " << (p5 <  (void*)p6) << '\n';
}

输出

Pointers to array elements:
p1 == p2? false
p1 <  p2? true
Pointers to members of a class:
p3 == p4? false
p3 <  p4? true
Pointers to members of a union:
p5 == (void*)p6? true
p5 <  (void*)p6? false

三路比较

三路比较运算符表达式具有以下形式

a <=> b

该表达式返回一个对象,使得

  • (a <=> b) < 0 如果 a < b
  • (a <=> b) > 0 如果 a > b
  • (a <=> b) == 0 如果 ab 相等/等价。

如果其中一个操作数的类型为 bool,而另一个操作数的类型不是,则程序是非良构的。

如果两个操作数都具有算术类型,或者如果一个操作数具有无作用域枚举类型,而另一个操作数具有整型类型,则对操作数应用常用算术转换,然后

  • 如果需要窄化转换(从整型类型到浮点类型除外),则程序是非良构的。
  • 否则,如果操作数具有整型类型,则运算符产生类型为 std::strong_ordering 的右值
  • std::strong_ordering::equal 如果两个操作数在算术上相等,
  • std::strong_ordering::less 如果第一个操作数在算术上小于第二个操作数,
  • 否则为 std::strong_ordering::greater。
  • 否则,若操作数具有浮点类型,则运算符产生类型为 std::partial_ordering 的纯右值。表达式 a <=> b 产生
  • std::partial_ordering::less ,如果 a 小于 b
  • std::partial_ordering::greater ,如果 a 大于 b
  • std::partial_ordering::equivalent ,如果 a 等价于 b ( -0 <=> +0 为等价),
  • std::partial_ordering::unorderedNaN <=> anything 为无序)。

如果两个操作数都具有相同的枚举类型 E,则运算符产生将操作数转换为 E 的底层类型并将 <=> 应用于转换后的操作数的结果。

如果至少一个操作数是指向对象的指针或指向成员的指针,则将数组到指针的转换指针转换限定转换应用于两个操作数,以将其转换为它们的复合指针类型

对于转换后的指针操作数 pqp <=> q 返回类型为 std::strong_ordering 的纯右值

  • std::strong_ordering::equal ,如果它们比较相等
  • std::strong_ordering::less ,如果 q 比较大于 p
  • std::strong_ordering::greater ,如果 p 比较大于 q
  • 如果双向比较结果未指定,则结果未指定。

否则,程序是非良构的。

重载

对用户定义的运算符的重载决议中,对于指针或枚举类型 T,以下函数签名参与重载决议

R operator<=>(T, T);

其中 R 是上面定义的排序类别类型。

#include <compare>
#include <iostream>
 
int main()
{
    double foo = -0.0;
    double bar = 0.0;
 
    auto res = foo <=> bar;
 
    if (res < 0)
        std::cout << "-0 is less than 0";
    else if (res > 0)
        std::cout << "-0 is greater than 0";
    else if (res == 0)
        std::cout << "-0 and 0 are equal";
    else
        std::cout << "-0 and 0 are unordered";
}

输出

-0 and 0 are equal
(自 C++20 起)

[编辑] 注解

由于比较运算符从左到右分组,表达式 a < b < c 被解析为 (a < b) < c,而不是 a < (b < c)(a < b) && (b < c)

#include <iostream>
 
int main()
{
    int a = 3, b = 2, c = 1;
 
    std::cout << std::boolalpha
        << (a < b < c) << '\n' // true; maybe warning
        << ((a < b) < c) << '\n' // true
        << (a < (b < c)) << '\n' // false
        << ((a < b) && (b < c)) << '\n'; // false
}

用户定义的 operator< 的常见要求是 严格弱序。特别是,这是使用 Compare 类型的标准算法和容器所要求的:std::sortstd::max_elementstd::map 等。

指向同一类的不同非静态数据成员的指针的比较结果暗示非静态数据成员在三种成员访问模式的每一种中(直到 C++23) 都按照声明顺序在内存中排列。

尽管比较随机来源的指针(例如,并非都指向同一数组的成员)的结果未指定,但许多实现提供了指针的 严格全序,例如,如果它们被实现为连续虚拟地址空间内的地址。那些不这样做的实现(例如,并非指针的所有位都是内存地址的一部分并且必须忽略比较,或者需要额外的计算,或者指针和整数不是 1 对 1 的关系),提供了 std::less 的指针特化,它具有该保证。这使得可以将所有随机来源的指针用作标准关联容器(例如 std::setstd::map)中的键。

对于既是 EqualityComparable 又是 LessThanComparable 的类型,C++ 标准库区分了相等性,即表达式 a == b 的值,以及等价性,即表达式 !(a < b) && !(b < a) 的值。

指针和空指针常量之间的比较已通过 CWG 问题 583 的决议删除,该决议包含在 N3624

void f(char* p)
{
    if (p > 0) { /*...*/ } // Error with N3624, compiled before N3624
    if (p > nullptr) { /*...*/ } // Error with N3624, compiled before N3624
}
 
int main() {}

三路比较可以为类类型自动生成,请参阅默认比较

如果两个操作数都是数组,则三路比较是非良构的。

unsigned int i = 1;
auto r = -1 < i;    // existing pitfall: returns ‘false’
auto r2 = -1 <=> i; // Error: narrowing conversion required
特性测试 Std 特性
__cpp_impl_three_way_comparison 201907L (C++20) 三路比较(编译器支持)
__cpp_lib_three_way_comparison 201907L (C++20) 三路比较(库支持);向库添加三路比较

[编辑] 标准库

比较运算符为标准库中的许多类重载。

(在 C++20 中移除)
检查对象是否引用同一类型
std::type_info 的公共成员函数) [编辑]
(在 C++20 中移除)(在 C++20 中移除)(C++20 起)
比较两个 error_code
(函数) [编辑]
(在 C++20 中移除)(在 C++20 中移除)(C++20 起)
比较 error_conditionerror_code
(函数) [编辑]
(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(C++20 起)
按字典顺序比较 pair 中的值
(函数模板) [编辑]
(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(C++20 起)
按字典顺序比较 tuple 中的值
(函数模板) [编辑]
(在 C++20 中移除)
比较内容
std::bitset<N> 的公共成员函数) [编辑]
(在 C++20 中移除)
比较两个分配器实例
std::allocator<T> 的公共成员函数) [编辑]
与另一个 unique_ptrnullptr 比较
(函数模板) [编辑]
(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(C++20 起)
与另一个 shared_ptrnullptr 比较
(函数模板) [编辑]
(在 C++20 中移除)
std::functionnullptr 比较
(函数模板) [编辑]
(C++11 起)(C++11 起)(在 C++20 中移除)(C++11 起)(C++11 起)(C++11 起)(C++11 起)(C++20 起)
比较两个 duration
(函数模板) [编辑]
(C++11 起)(C++11 起)(在 C++20 中移除)(C++11 起)(C++11 起)(C++11 起)(C++11 起)(C++20 起)
比较两个 time point
(函数模板) [编辑]
(在 C++20 中移除)
比较两个 scoped_allocator_adaptor 对象
(函数模板) [编辑]
比较底层的 std::type_info 对象
std::type_index 的公共成员函数) [编辑]
(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(C++20 起)
按字典顺序比较两个字符串
(函数模板) [编辑]
(在 C++20 中移除)
locale 对象之间的相等性比较
std::locale 的公共成员函数) [编辑]
(C++11 起)(C++11 起)(在 C++20 中移除)(C++11 起)(在 C++20 中移除)(C++11 起)(在 C++20 中移除)(C++11 起)(在 C++20 中移除)(C++11 起)(在 C++20 中移除)(C++20 起)
按字典顺序比较两个 array 的值
(函数模板) [编辑]
(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(C++20 起)
按字典顺序比较两个 deque 的值
(函数模板) [编辑]
(C++11 起)(C++11 起)(在 C++20 中移除)(C++11 起)(在 C++20 中移除)(C++11 起)(在 C++20 中移除)(C++11 起)(在 C++20 中移除)(C++11 起)(在 C++20 中移除)(C++20 起)
按字典顺序比较两个 forward_list 的值
(函数模板) [编辑]
(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(C++20 起)
按字典顺序比较两个 list 的值
(函数模板) [编辑]
(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(C++20 起)
按字典顺序比较两个 vector 的值
(函数模板) [编辑]
(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(C++20 起)
按字典顺序比较两个 map 的值
(函数模板) [编辑]
(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(C++20 起)
按字典顺序比较两个 multimap 的值
(函数模板) [编辑]
(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(C++20 起)
按字典顺序比较两个 set 的值
(函数模板) [编辑]
(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(C++20 起)
按字典顺序比较两个 multiset 的值
(函数模板) [编辑]
(C++11 起)(C++11 起)(在 C++20 中移除)
比较 unordered_map 中的值
(函数模板) [编辑]
(C++11 起)(C++11 起)(在 C++20 中移除)
比较 unordered_multimap 中的值
(函数模板) [编辑]
(C++11 起)(C++11 起)(在 C++20 中移除)
比较 unordered_set 中的值
(函数模板) [编辑]
(C++11 起)(C++11 起)(在 C++20 中移除)
比较 unordered_multiset 中的值
(函数模板) [编辑]
按字典顺序比较两个 queue 的值
(函数模板) [编辑]
按字典顺序比较两个 stack 的值
(函数模板) [编辑]
比较底层的迭代器
(函数模板) [编辑]
(C++11 起)(C++11 起)(在 C++20 中移除)(C++11 起)(C++11 起)(C++11 起)(C++11 起)(C++20 起)
比较底层的迭代器
(函数模板) [编辑]
(在 C++20 中移除)
比较两个 istream_iterator
(函数模板) [编辑]
(在 C++20 中移除)
比较两个 istreambuf_iterator
(函数模板) [编辑]
(在 C++20 中移除)
比较两个复数或一个复数和一个标量
(函数模板) [编辑]
比较两个 valarray 或一个 valarray 与一个值
(函数模板) [编辑]
(C++11 起)(C++11 起)(在 C++20 中移除)
比较两个伪随机数引擎的内部状态
(函数) [编辑]
(C++11 起)(C++11 起)(在 C++20 中移除)
比较两个分布对象
(函数) [编辑]
(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(C++20 起)
sub_match 与另一个 sub_match、字符串或字符比较
(函数模板) [编辑]
(在 C++20 中移除)
按字典顺序比较两个匹配结果中的值
(函数模板) [编辑]
(在 C++20 中移除)
比较两个 regex_iterator
std::regex_iterator<BidirIt,CharT,Traits> 的公共成员函数) [编辑]
(在 C++20 中移除)
比较两个 regex_token_iterator
std::regex_token_iterator<BidirIt,CharT,Traits> 的公共成员函数) [编辑]
(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(在 C++20 中移除)(C++20 起)
比较两个 thread::id 对象
(函数) [编辑]

命名空间 std::rel_ops 提供了泛型运算符 !=><=>=

在头文件 <utility> 中定义
在命名空间 std::rel_ops 中定义
基于用户定义的 operator==operator< 自动生成比较运算符
(函数模板) [编辑]

[编辑] 缺陷报告

以下行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。

DR 应用于 已发布行为 正确行为
CWG 583
N3624
C++98 所有六个比较运算符都可用于
将指针与空指针常量进行比较
仅允许相等运算符
被允许
CWG 661 C++98 算术比较的实际语义(例如
1 < 2 是否产生 truefalse )未指定
添加了规范
CWG 879 C++98 指向函数类型的指针和指向
void 的指针没有内置比较
为这些指针添加了比较
规范
CWG 1596 C++98 非数组对象被认为属于具有
仅一个元素的数组,用于指针算术
该规则也
应用于比较
CWG 1598 C++98 指向不同类的成员的两个指针,并且
都不是另一个类的基类,则不比较相等
即使指向的成员的偏移量可能相同
结果是
未指定
在这种情况下
CWG 1858 C++98 尚不清楚指向成员的两个指针是否
引用同一联合的不同成员
比较相等,如同它们引用同一成员一样
它们在这种情况下
比较相等
CWG 2419 C++98 指向非数组对象的指针仅被视为
指向大小为 1 的数组的第一个元素的指针
在指针比较中,如果指针是通过 & 获取的
适用于所有指向非数组对象的指针
到非数组对象的指针
CWG 2526 C++98 关系比较(>>=<<=)的定义
指向 void 和函数指针的指针被 N3624 删除
已恢复
CWG 2796 C++17 函数指针转换未在转换后的
指针操作数上执行,在内置指针关系比较期间
在这种情况下执行这些
转换

[编辑] 参见

常用运算符
赋值 递增
递减
算术 逻辑 比较 成员
访问
其他

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[...]
*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_castconst_castreinterpret_cast 将一种类型转换为另一种类型
new 创建具有动态存储期的对象
delete 析构先前由 new 表达式创建的对象并释放获得的内存区域
sizeof 查询类型的大小
sizeof... 查询的大小 (C++11 起)
typeid 查询类型的类型信息
noexcept 检查表达式是否可以抛出异常 (C++11 起)
alignof 查询类型的对齐要求 (C++11 起)

C 文档 关于 比较运算符