Namespaces
Variants

Comparison operators

From zh.cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

比较参数。

运算符名称 语法 可重载性 原型示例(针对 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 是 R T :: operator <=> ( const U & b ) const ; [1] R operator <=> ( const T & a, const U & b ) ; [1]
注意
  • 当内置运算符返回 bool 时,大多数 用户定义重载 也会返回 bool ,以便用户定义运算符能够以与内置运算符相同的方式使用。然而在用户定义的运算符重载中,可以使用任何类型作为返回类型(包括 void )。
  • U 可以是包括 T 在内的任意类型。
  1. ↑ 1.0 1.1 R 是 operator<=> 的返回类型 ( 详见下文 )

目录

双向比较

双向比较运算符表达式的形式为

关系运算符
lhs < rhs (1)
lhs > rhs (2)
lhs <= rhs (3)
lhs >= rhs (4)
说明:根据要求保留了所有HTML标签、属性及 标签内的C++运算符,仅对表格结构进行了完整保留。由于原文中除HTML标签和代码外的文本内容仅为序号(1)-(4),无需翻译,因此输出结果与原文完全一致。
相等运算符
lhs == rhs (5)
lhs != rhs (6)
(注:根据要求,HTML标签、属性及 标签内的运算符均未翻译,仅对非代码文本进行了保留处理。由于原文中除标签和代码外无其他可翻译的自然语言文本,故输出内容与原文完全一致)
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 。

内置双向比较运算符

对于内置的双向比较运算符, lvalue-to-rvalue conversions , array-to-pointer conversions (until C++26) 和 function-to-pointer conversions 会被应用于 lhs 和 rhs 。

若在应用这些转换前 lhs 与 rhs 均具有数组类型,则该比较被弃用。

(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 起) 指针类型或成员指针类型。

内置指针相等性比较具有三种可能结果:相等、不相等和未指定。以下是内置指针相等性比较中相等运算符所产生值的列表:

p与q的比较结果 表达式返回值
p == q p ! = q
相等 true false
不相等 false true
未指定 未指定的 bool 值

如果转换后的 lhs 和 rhs 中至少有一个是指针, 则会执行 指针转换 、 函数指针转换 (C++17 起) 以及 限定转换 ,使两个转换后的操作数达到其 复合指针类型 。随后按以下方式比较复合指针类型的两个指针:

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

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

  • 若两个成员指针均为空成员指针值,则它们比较相等。
  • 若两个成员指针中仅有一个为空成员指针值,则它们比较不相等。
  • 若其中任意一个是指向 virtual member function 的指针,则结果未指定。
  • 若一个指向类 C1 的成员,而另一个指向不同类 C2 的成员(且二者互不为基类),则结果未指定。
  • 若两者均指向同一 union 的(可能不同的)成员,则它们比较相等。
  • 否则,当通过关联类类型的假设对象进行间接寻址时,若两个成员指针会指向同一 most derived object 或同一子对象的相同成员,则它们比较相等;否则比较不相等。
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); // 未指定
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 类型而另一个为空指针常量时,比较结果相等。

(since C++11)

内置指针关系比较

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

对不相等指针 p 和 q 进行内置指针关系比较时存在三种可能结果: p 较大、 q 较大以及未指定结果。内置指针关系比较中关系运算符所生成的取值如下所示:

p 与 q 的比较结果 表达式返回值
p > q p < q p >= q p <= q
相等 false false true true
p 较大 true false true false
q 较大 false true false true
未指定 未指定的 bool 值

如果转换后的 lhs 和 rhs 均为指针类型, 将对其执行 指针转换 、 函数指针转换 (C++17 起) 以及 限定转换 ,使其转换为对应的 复合指针类型 。复合指针类型的两个指针将按以下方式进行比较:

  • 若指针比较相等或相等比较结果未指定,则关系比较结果属于同一类别。
  • 否则(指针比较不相等),若任一指针不是指向对象的指针,则结果未指定。
  • 否则(两个指针均指向对象),结果按符合以下规则的部分顺序定义:
  • 给定数组中的两个不同元素 high 和 low ,其中 high 的下标高于 low ,若一个指针指向 high (或 high 的子对象),而另一个指针指向 low (或 low 的子对象),则前者比较结果大于后者。
  • 若一个指针指向数组元素 elem (或 elem 的子对象),而另一个指针指向同一数组的尾后位置,则尾后指针的比较结果大于另一个指针。
  • 若一个指针指向完整对象、基类子对象或成员子对象 obj (或 obj 的子对象),而另一个指针指向 obj 的尾后位置,则尾后指针的比较结果大于另一个指针。

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

指针全序

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

严格全序的指针比较适用于以下情况:

(since C++14)
(since C++20)

双向比较运算符的重载

重载

在 针对用户定义运算符的重载决议 中,对于每一对提升后的算术类型 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 ) ;
注:根据要求,所有HTML标签、属性及 标签内的C++代码(包括关键字、运算符和参数)均保持原样未作翻译。

对于每个类型 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 ) ;
说明:由于所有内容均位于 ` ` 标签内(属于代码标签),且包含C++特定术语和运算符,根据要求未进行任何翻译。表格结构和HTML标签均保持原样。

对于每个类型 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 << "指向数组元素的指针:\n"
              << "p1 == p2? " << (p1 == p2) << '\n'
              << "p1 <  p2? " << (p1 <  p2) << '\n';
    Foo f;
    int* p3 = &f.n1;
    int* p4 = &f.n2;
    std::cout << "指向类成员的指针:\n"
              << "p3 == p4? " << (p3 == p4) << '\n'
              << "p3 <  p4? " << (p3 <  p4) << '\n';
    Union u;
    int* p5 = &u.n;
    double* p6 = &u.d;
    std::cout << "指向联合体成员的指针:\n"
              << "p5 == (void*)p6? " << (p5 == (void*)p6) << '\n'
              << "p5 <  (void*)p6? " << (p5 <  (void*)p6) << '\n';
}

输出:

指向数组元素的指针:
p1 == p2? false
p1 <  p2? true
指向类成员的指针:
p3 == p4? false
p3 <  p4? true
指向联合体成员的指针:
p5 == (void*)p6? true
p5 <  (void*)p6? false

三路比较

三路比较运算符表达式的形式为

a <=> b

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

  • ( a <=> b ) < 0 当 a < b 时,
  • ( a <=> b ) > 0 当 a > b 时,
  • ( a <=> b ) == 0 当 a 与 b 相等/等价时。

如果其中一个操作数的类型为 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::unordered ( NaN <=> anything 为无序关系)。

如果两个操作数具有相同的枚举类型 E ,该运算符会将操作数转换为 E 的基础类型,并对转换后的操作数应用 <=> 以生成结果。

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

对于转换后的指针操作数 p 和 q , p <=> 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; 可能产生警告
        << ((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 等。

指向同一类不同非静态数据成员的 指针比较结果 表明,非静态数据成员 在三种 成员访问模式 (until C++23) 下均按声明顺序在内存中排列。

尽管比较随机来源的指针(例如并非全部指向同一数组成员)的结果是未指定的,但许多实现提供了指针的 严格全序 关系,例如当指针被实现为连续虚拟地址空间中的地址时。那些不提供此类保证的实现(例如指针并非所有位都表示内存地址且比较时需要忽略某些位,或需要额外计算,或指针与整数非一一对应关系),会为指针提供特化版本的 std::less 以满足该保证。这使得所有随机来源的指针都可以用作标准关联容器(如 std::set 或 std::map )的键值。

对于同时满足 EqualityComparable 和 LessThanComparable 要求的类型,C++标准库区分了 相等性 (即表达式 a == b 的值)与 等价性 (即表达式 ! ( a < b ) && ! ( b < a ) 的值)。

指针与空指针常量之间的比较已通过 CWG issue 583 的解决方案被移除,该方案包含在 N3624 中:

void f(char* p)
{
    if (p > 0) { /*...*/ } // 使用 N3624 时报错,N3624 前可编译
    if (p > nullptr) { /*...*/ } // 使用 N3624 时报错,N3624 前可编译
}
int main() {}

三路比较可为类类型自动生成,参见 default comparisons 。

如果两个操作数都是数组,三路比较将无法形成有效表达式。

unsigned int i = 1;
auto r = -1 < i;    // 现有陷阱:返回‘false’
auto r2 = -1 <=> i; // 错误:需要窄化转换
功能测试 宏 值 标准 功能
__cpp_impl_three_way_comparison 201907L (C++20) 三路比较(编译器支持)
__cpp_lib_three_way_comparison 201907L (C++20) 三路比较(库支持);向库中添加三路比较功能

标准库

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

(removed in C++20)
检查对象是否引用相同类型
( std::type_info 的 公开成员函数)
(C++20中移除) (C++20中移除) (C++20)
比较两个 error_code
(函数)
(C++20中移除) (C++20中移除) (C++20)
比较 error_condition 和 error_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)
按字典序比较元组中的值
(函数模板)
(C++20 中移除)
比较内容
( std::bitset<N> 的公开成员函数)
(在 C++20 中移除)
比较两个分配器实例
( std::allocator<T> 的公开成员函数)
与另一个 unique_ptr 或与 nullptr 进行比较
(函数模板)
(C++20中移除) (C++20中移除) (C++20中移除) (C++20中移除) (C++20中移除) (C++20)
与另一个 shared_ptr 或与 nullptr 进行比较
(函数模板)
(C++20 中移除)
将 std::function 与 nullptr 进行比较
(函数模板)
(C++11) (C++11) (C++20中移除) (C++11) (C++11) (C++11) (C++11) (C++20)
比较两个时长
(函数模板)
(C++11) (C++11) (C++20中移除) (C++11) (C++11) (C++11) (C++11) (C++20)
比较两个时间点
(函数模板)
(在 C++20 中移除)
比较两个 scoped_allocator_adaptor 对象
(函数模板)
比较底层 std::type_index 对象
( std::type_index 的公开成员函数)
(C++20中移除) (C++20中移除) (C++20中移除) (C++20中移除) (C++20中移除) (C++20)
按字典序比较两个字符串
(函数模板)
(在 C++20 中移除)
区域设置对象之间的相等性比较
( 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) (removed in C++20)
比较 unordered_map 中的值
(函数模板)
(C++11) (C++11) (removed in C++20)
比较 unordered_multimap 中的值
(函数模板)
(C++11) (C++11) (removed in C++20)
比较 unordered_set 中的值
(函数模板)
(C++11) (C++11) (removed in 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
(函数模板)
(removed in C++20)
比较两个复数或复数与标量
(函数模板)
比较两个 valarray 或 valarray 与值
(函数模板)
(C++11) (C++11) (removed in C++20)
比较两个伪随机数引擎的内部状态
(函数)
(C++11) (C++11) (removed in 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++ 标准。

缺陷报告 应用于 已发布行为 正确行为
CWG 583
( N3624 )
C++98 所有六个比较运算符都可用于
将指针与空指针常量进行比较
仅允许相等性运算符
进行此类比较
CWG 661 C++98 算术比较的实际语义(例如
1 < 2 是否产生 true 或 false )未作规定
添加了相关规范说明
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 通过 N3624 移除了
指向 void 类型和函数指针的关系比较( > 、 >= 、 < 和 <= )定义
已恢复该定义
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_cast 、 const_cast 和 reinterpret_cast 将一种类型转换为另一种类型
new 创建具有动态存储期的对象
delete 销毁先前由new表达式创建的对象并释放获取的内存区域
sizeof 查询类型的大小
sizeof... 查询 参数包 的大小 (C++11起)
typeid 查询类型的类型信息
noexcept 检查表达式是否能抛出异常 (C++11起)
alignof 查询类型的对齐要求 (C++11起)

C 文档 关于 比较运算符