[C++] 基础知识之3、C++中的运算符

本文详细介绍了C++中的各类运算符,包括算术、关系、逻辑、位运算符及其重载方法。阐述了运算符的功能、用法及优先级,并讨论了如何通过重载提升程序的可读性和扩展性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++中的运算符

  运算符是一种告诉编译器执行特定的数学或者逻辑操作的符号。C++内置了丰富的运算符。和运算符相关的概念和知识也是C++编程语言中的重要组成部分。这里做一个初步总结。

基本运算符

  主要分为如下五种类型的运算符。

算术运算符

  包括加法运算符(+)、减法运算符(-)、乘法运算符(*)、除法运算符(/)、取模运算符(%)、自增运算符(++)和自减运算符(- -)。其中需要注意的是前缀自增(++a)和后缀自增(a++)的区别。前者表示先执行自增运算,执行完的结果参与其它运算;而后者表示先对a执行其它运算,等到表达式中和a相关的语句执行完成之后,再对a进行自增。除非重载,算术运算符的运算结果一般为数值。

关系运算符

  包括相等运算符(==),不等运算符(!=),大于运算符(>),小于运算符(<),大于等于运算符(>=)以及小于等于运算符(<=)。除非重载,关系运算符的运算结果一般为布尔值。

逻辑运算符

  包括逻辑与运算符(&&)、逻辑或运算符(||)和逻辑非运算符(!)。其中逻辑与和逻辑或运算在C++中采用短路实现,即对于(A&&B),假如已经运算得知A为false,则不再对B进行运算,直接返回结果false;对于(A||B),假如已经运算得知A为true,则不再对B进行运算,直接返回true。

位运算符

  位运算符作用于二进制位,并逐位执行操作。假设A=60=0b00111100, B=13=0b00001101,则位运算的描述如下:

运算符实例解释
&(A&B)=0b00001100=12当且仅当两个操作数的对应位都为1时结果才为1
|(A|B)=0b00111101=61只要有一个操作数的对应位为1则结果为1
^(A^B)=0b00110001=49当且仅当两个操作数的对应位不同时结果为1
~(~A)=0b11000011=-61各位取反
<<(A<<2)=240左操作数的值向左移动右操作数指定的位数,右边补零
>>(A>>2)=15左操作数的值向右移动右操作数指定的位数,左边补零

  关于位运算符有许多神奇的妙用,例如:
   1. 二进制补码运算符(~):一个有符号的二进制数的补码通常通过该运算符获得。计算机中有符号整数通常都是采用补码进行表示的,有诸多好处,感兴趣的读者可以参阅相关文章。
   2. 二进制左移运算符(<<):对于正整数而言,左移一位意味着*2,但是执行效率却比普通的算术运算符高很多。
   3. 二进制右移运算符(>>):对于正整数而言,右移一位意味着/2,但是执行效率却比普通的算术运算符高很多。更多的妙用可以参考:http://www.matrix67.com/blog/archives/263

赋值运算符

  赋值运算符其实就是等号(=)以及它与所有算术运算符和位运算符的结合。例如a+=b就等同于a = a + b。赋值运算符可以起到简化代码的作用。C++支持的赋值运算符主要包括:简单赋值运算符(=)、加赋值运算符(+=)、减赋值运算符(-=)、乘赋值运算符(*=)、除赋值运算符(/=)、求模赋值运算符(%=)、左移赋值运算符(<<=)、右移赋值运算符(>>=)、按位与赋值运算符(&=)、按位或赋值运算符(|=)以及按位异或(^=)赋值运算符。

杂项运算符

  C++中的其它重要的运算符如下:

运算符描述
sizeofsizeof运算符返回变量的大小,以字节为单位。例如sizeof(short) == 2。
Condition?X:Y条件运算符,如果Condition为真则返回X,否则返回Y。
,逗号运算符会顺序执行一系列运算,整个逗号表达式的值是以逗号分隔的列表中的最后一个表达式的值。
.和->成员运算符用于引用类、结构和共用体的成员,其中前者适用于普通变量或者引用类型,后者适用于指针类型。
Cast强制转换运算符把一种数据类型转换为另一种数据类型,例如int(6.5)=6。
&取地址运算符&返回变量的地址;如果出现在左值中则表示后面的变量类型为引用。
*取内容运算符*返回指针所指向的内容;如果出现在左值中则表示后面的变量类型为指针。

运算符优先级

  运算符的优先级确定表达式中各项的组合顺序。明确定义运算符的优先级可以大量减少括弧的使用,提高代码的可读性。下表将按照运算符优先级从高到低列出各个运算符,具有较高优先级的预算付出现在表格的上面。在表达式中,较高优先级的运算符会优先被计算。

优先级操作符说明结合方向
1::范围解析从左到右
2() [] . -> ++ - - dynamic_cast static_cast reinterpret_cast const_cast typeid后缀从左到右
3++ - - ~ ! sizeof new delete一元(前缀)从右到左
* &指针和取地址
+ -一元符号
4(type)类型转换从右到左
5.* ->*指向成员的指针从左到右
6* / %乘除及取模从左到右
7+ -加减从左到右
8<< >>位移从左到右
9< > <= >=关系操作符从左到右
10== !=相等判定从左到右
11&按位与运算从左到右
12^按位异或运算从左到右
13|按位或运算从左到右
14&&逻辑与运算从左到右
15||逻辑或操作从左到右
16?:条件运算从右到左
17= += -= *= /= %= >>= <<= &= ^= |=赋值运算从右到左
18,逗号从左到右

  事实上上表也无须死记硬背,很多运算符的规则和数学中是相同的。用的多,看得多了自然就记得了。对于拿不准的,可以通过使用括弧达到目标。

运算符重载

  运算符重载允许把标准运算符应用于自定义数据类型的对象,直观自然,可以提高程序的可读性,体现了C++的可扩展性。运算符重载本质上是函数的重载,但不同之处在于运算符重载的一定是操作符。

重载的实现方式

  运算符重载的实现方式有两种,即通过“友元函数”或者“类成员函数”,这两种方式都可以访问类中的私有成员。下面是友元函数操作符重载方式。

class 类名 {
    friend 返回类型 operator 操作符(形参表);
};
// 类外定义格式
返回类型 operator 操作符(形参表) {
    // 函数体
}

下面是类成员函数操作符重载的方式。

class 类名 {
public:
    返回类型 operator 操作符(形参表);
};
// 类外定义格式
返回类型 类名 :: operator 操作符(形参表) {
    // 函数体
}

  利用友元函数重载二元操作符时,形式参数是两个,而利用类成员函数时,形式参数却只有一个。这是因为类成员函数中存在this指针,这相当于一个参数,所以类成员实现操作符重载需要的形式参数比原来少一个。这比如利用类成员函数实现一元操作符”-“时,就不需要参数了。也正是因为这个原因,友元函数实现的操作符重载是有限制的,比如[],(),->和=等不能利用友元函数实现运算符的重载。
  在实际开发过程中,单目运算符建议重载为成员函数,而双目运算符建议重载为友元函数。通常情况下双目运算符重载为友元函数比重载为成员函数更方便,但是有时候双目运算符比如重载为成员函数,例如赋值运算符=。还有如果需要修改对象内部的状态,一般也可以选择利用类成员函数的重载进行修改。

运算符重载的原则

  运算符重载也是要遵循一些原则的:
  1. C++中只能对已有的运算符进行重载(见本贴的基本运算符介绍),不允许用户自己定义新的运算符。
   2. C++中绝大多数运算符可以重载,但是有五个运算符不允许重载,分别是:成员访问运算符(.),作用域运算符(::),长度运算符(sizeof),条件运算符(?:)以及成员指针访问运算符(.*)。
   3. 运算符重载后不能改变运算符的操作对象(操作数)的个数。如:”+”是实现两个操作数的运算符,重载后仍然为双目运算符。
   4. 重载不能改变运算符原有的优先级和原有的结合性。
   5. 运算符重载不能全部是C++中预定义的基本数据,这样做的目的是为了防止用户修改用于基本类型数据的运算符性质。
   6. 对于前置单目运算符U,如“-”(负号)等,如果要重载U为类的成员函数,用来实现表达式U oprd,其中oprd为A类的对象,则U应当重载为A类的成员函数,函数没有形参。经过重载之后,表达式U oprd相当于函数调用oprd.operator U()。
   7. 对于后置运算符“++”和“- -”,如果要将它们重载为类的成员函数,用来实现表达式oprd++或oprd- -,其中oprd为A类的对象,那么运算符就应当重载为A类的成员函数,这时函数要带有一个整型形参。重载之后,表达式oprd++和oprd- - 就想当于函数调用oprd.operator++(0)和oprd.operator- -(0)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值