4.C++表达式

1. 运算符概念

1.1 运算符分类

C++ 运算符的种类有3种,作用于1个运算对象的运算符是一元运算符,如取地址符解引用符。作用于2个运算对象的运算符是二元运算符,如相等运算符乘法运算符。除此之外,还有一个作用于3个运算符对象的三元运算符
1.重载运算符
当运算符作用于类类型的运算对象时,用户可以自定义其含义。这种自定义的过程实际上为已存在的运算符赋予了另一层含义,称之为重载运算符。我们使用重载运算符,其包括运算对象的类型和返回值的类型都是由该运算符定义的,但是运算对象的个数,运算符的优先级和结合律都是无法改变的。

#include <iostream>
class Complex {
private:
    double real;
    double imag;
public:
    Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}
    // 重载 + 运算符
    Complex operator+(const Complex& obj) const {
        Complex temp;
        temp.real = real + obj.real;
        temp.imag = imag + obj.imag;
        return temp;
    }
    void display() const{
        std::cout << "Real: " << real << " Imaginary: " << imag << std::endl;
    }
};
int main() {
    Complex c1(2.0, 3.0);
    Complex c2(1.0, 4.0);
    Complex result = c1 + c2; // 使用重载的 + 运算符
    result.display();
    return 0;
}

1.2 优先级和结合律

复合表达式是指含有2个或多个运算符的表达式。求复合表达式的值需要先将运算符和运算对象合理的组合在一起,优先级与结合律决定了运算对象组合的方式。示例如下:

int a = 5, b = 10;
c = a + b * 2;
// 乘法操作符 * 拥有比加法操作符 + 更高的优先级,所以 b * 2 将首先计算。
// 乘法是左结合的,意味着 b * 2 会在与 a 相加之前先进行计算,这个表达式就变成了 c = a + 20。
// 因为加法操作符 + 有着比赋值操作符 = 更低的优先级,所以 a + 20 将会先计算。

注意: 括号无视普通的组合规则,表达式中括号括起来的部分被当成一个单元来求值,然后再与其它部分一起按照优先级组合。

1.3 类型转换

在表达式求值过程中,一般二元运算符要求2个运算对象的类型相同,但很多时候即使不同也没有关系,因为它们可以被转换成同一种类型。
1.隐式转换
1.整型提升:小于 int 的整型值在表达式中会被提升为 int 或更大的整型类型。
2.算术转换:运算符应用于不同类型的操作数时会执行算术转换。

short a = 5;
int b = a;              // 整型提升,将 short 提升为 int
double y = 2.5;
double result = b + y; // 算术转换,将 int 转换为 double

2.显式转换
1.C风格的强制类型转换:在变量前用括号标注想要转换的类型即可。
2.static_cast:允许进行比较宽泛的转换,例如指针类型转换、基本类型转换。
3.const_cast:用于去除变量的 const 属性。

int a = 10;
double b = (double)a;              // C 风格的强制类型转换,将 int 转换为 double
int b = 20;
double c = static_cast<double>(b); // static_cast,将 int 转换为 double
const int* ptr = new int(5);       // 指向常量整数的指针
int* nonConstPtr = const_cast<int*>(ptr); // 移除常量性
*nonConstPtr = 10;  // 修改值
cout << *ptr;       // 原指针指向的值也发生了变化

2.运算符

2.1 算术运算符

运算符功能用法运算符功能用法
+一元正号+ expr%求余expr % expr
-一元负号- expr+加法expr + expr
*乘法expr * expr-减法expr - expr
/除法expr / expr

一元运算符的优先级最高,接下来是乘法和除法,优先级最低的是加法和减法。优先级相同时按照从左到右的顺序进行组合。

2.2 逻辑运算符

关系运算符作用于算术类型或指针类型,逻辑运算符作用于任意能转换成布尔值的类型,逻辑运算符和关系运算符的返回值都是布尔类型。

结合律运算符功能用法结合律运算符功能用法
逻辑非!expr>=大于等于expr >= expr
<小于expr < expr==相等expr == expr
<=小于等于expr <= expr! =不相等expr != expr
>大于expr > expr&&逻辑与expr && expr

2.3 赋值运算符

赋值运算符满足右结合律,如下所示:

ival = jval = 0;  // 先计算jval=0,再把结果赋值给ival

注意: 切勿混淆相等运算符和赋值运算符。

2.4 递增和递减运算符

递增和递减运算符有两种形式,前置版本和后置版本。前置版本首先将运算对象加 1,然后将改变后的对象作为求值结果。后置版本也会将运算对象加 1,但是求值结果是运算对象改变之前那个值的副本。

int i = 0, j;
j = ++i;   // j = 1, i = 1;
j = i++;   // j = 1, i = 2;

1.解引用和递增运算符的优先级
后置递增运算符的优先级高于解引用运算符,如下所示:

#include <iostream>
using namespace std;
int main() {
	int arr[] = { 10, 20, 30, 40, 50 };
	int *ptr = arr; // 指向数组的指针,指向第一个元素
	cout << "初始值: " << *ptr++ << endl;  // 结果为10
	return 0;
}
// ptr++ 会先将指针 ptr 的值递增(指向下一个元素),但 * 运算符作用的是递增前的 ptr 值所指向的元素,而不是递增后的值

2.5 成员访问运算符

点运算符和箭头运算符都可以用于访问成员,如下所示:

#include <iostream>
using namespace std;
// 定义一个简单的类
class MyClass {
public:
	int memberVar = 10;
	void memberFunction() {
		cout << "这是一个成员函数" << endl;
	}
};
int main() {
	// 创建一个 MyClass 的对象
	MyClass obj;
	// 使用 . 运算符访问成员变量和成员函数
	cout << "成员变量的值:" << obj.memberVar << endl;
	obj.memberFunction();
	// 使用 -> 运算符访问成员变量和成员函数
	MyClass *ptr = &obj;
	cout << "通过指针访问成员变量的值:" << ptr->memberVar << endl;
	ptr->memberFunction();
	return 0;
}

2.6 条件运算符

条件运算符如下所示:

#include <iostream>
#include<string>
using namespace std;
int main() {
    int num = 10;
    string result;
    // 使用条件运算符将结果赋给字符串
    result = (num > 5) ? "大于5" : "小于等于5";
    // 输出结果
    cout << "结果是:" << result << endl;
    return 0;
}

注意: 条件运算符的优先级非常低,因此当有一条长表达式中嵌套了条件运算子表达式时,通常在子表达式两端加上括号。

2.7 位运算符

位运算符作用于整数类型的运算对象,并把运算对象看成是二进制位的集合。位运算符提供检查和设置二进制位的功能,一种名为bitset的标准库类型也可以表示任意大小的二进制位集合。

运算符功能用法运算符功能用法
~位求反~ expr&位与expr1 & expr2
<<左移expr1 << expr2^位异或expr1 ^ expr2
>>右移expr1 >> expr2

1.移位运算符
左移:将一个数的二进制表示向左移动指定的位数,右侧空出的位用零填充。例如,x << y 将 x 向左移动 y 位。
右移:将一个数的二进制表示向右移动指定的位数。对于有符号整数,空出的位使用符号位填充(即保持正负号不变),而对于无符号整数,空出的位用零填充。例如,x >> y 将 x 向右移动 y 位。

#include <iostream>
using namespace std;
int main() {
    int x = 10; // 二进制表示为 1010
    // 左移示例
    int leftShifted = x << 2; // 1010 << 2 -> 101000(二进制),相当于十进制的 40
    cout << "左移结果:" << leftShifted << endl;
    // 右移示例
    int rightShifted = x >> 1; // 1010 >> 1 -> 101(二进制),相当于十进制的 5
    cout << "右移结果:" << rightShifted << endl;
    return 0;
}

2.位求反运算符
位求反运算符将运算对象逐位求反后生成一个新值,将 1 置为 0,将 0 置为 1。
3.位与、位或、位异或运算符
1.位与运算符: 如果两个运算对象的对应位置都是 1,则运算结果中该位为 1,否则为 0。
2.位或运算符: 如果两个运算对象的对应位置至少有一个为 1,则运算结果中该位为 1,否则为 0。
3.位异或运算符: 如果两个运算对象的对应位置有且只有一个为 1,则运算结果中该位为 1,否则为 0。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Litle_Pudding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值