C++ | C++入门总结(四)运算符、空语句、switch内部变量

  • 短路求值

逻辑与运算符(&&)和逻辑或运算符(||)都是先求左侧运算对象的值再求右侧运算对象的值,当且仅当左侧运算对象无法确定表达式的结果时才会计算右侧运算对象的值。这种策略称为短路求值。

  1. 对于逻辑与运算符(&&)来说,当且仅当左侧运算对象为真时才对右侧运算对象求值。
  2. 对于逻辑或运算符(||)来说,当且仅当左侧运算对象为假时才对右侧运算对象求值。

  • 关系运算符与赋值运算符

  1. C++中bool值可以转化成为其他算数类型:false转化成0,true转化成1;
  2. C++中允许用赋值运算作为条件。
	int a = 10, b = 5, c = 2;
	if (a > b > c)//a>b为true,1与c进行比较
	{
		cout << "enheng" << endl;
	}
	if (a = b)//将b的值赋给a,如果b的值不是0,则为真
	{
		cout << a << endl;//5
	}

  • 递增递减运算符

推荐使用前置版本的递增运算符:前置版本的递增运算符(++i)避免了不必要的工作 , 它把值加 1 后直接返回改变了的运算对象。与之相比 , 后置版本(i++)需要将原始值存储下来以便于返回这个未修改的内容。如果我们不需要修改前的值 , 那么后置版本的操作就是一种浪费。


  • 解引用与递增运算符

        *p++:后置递增运算符的优先级高于解引用运算符,因此 *p++ 等价于 *( p++)。p++ 把p的值加 1,然后返回p的初始值的副本作为其求值结果,此时解引用运算符的运算对象是p未增加之前的值。最终,这条语句输出p开始时指向的那个元素,并将指针向前移动一个位置。


  • 解引用与点运算符

(*p).empty():因为解引用运算符的优先级低于点运算符,所以执行解引用运算的子表达式两端必须加上括号。


  • 位运算符

  1. 位运算符有左移<<、右移>>、位求反~、位与&、位或|、位异或^。
  2. 位运算符作用于整数类型的运算对象,并把运算对象看成是二进制位的集合。
  3. 移位运算符(<<、>>,又叫IO运算符)的优先级不高不低,介于中间:比算术运算符的优先级低,但比关系运算
    符、赋值运算符和条件运算符的优先级高。
	cout << 5 + 10 << endl;//15
	cout << (5 < 10) << endl;//1,需要加括号,否则报错

  • sizeof运算符

  1. sizeof运算符返回一条表达式或一个类型名字所占的字节数。sizeof 运算符满足右结合律 , 其所得的值是一个 size_t 类型的常量表达式。运算符的运算对象有两种形式:
        sizeof ( type )
        sizeof expr
  2. sizeof并不实际计算其运算对象的值。
  3. 在sizeof的运算对象中解引用一个无效指针仍然是一种安全的行为 , 因为指针实际上并没有被真正使用。sizeof不需要真的解引用指针也能知道它所指对象的类型。
  4. C ++11新标准允许我们使用作用域运算符来获取类成员的大小。通常情况下只有通过类的对象才能访问到类的成员 , 但是 sizeof 运算符无须我们提供一个具体的对象 , 因为要想知道类成员的大小无须真的获取该成员。
  5. 对数组执行 sizeof 运算得到整个数组所占空间的大小,等价于对数组中所有的元素各执行一次 sizeof 运算并将所得结果求和。注意,sizeof运算不会把数组转换成指针来处理。
  6. 因为执行 sizeof 运算能得到整个数组的大小,所以可以用数组的大小除以单个元素的大小得到数组中元素的个数。
	char chars[] = "hello";
	auto byteSize1 = sizeof(char);
	auto byteSize2 = sizeof chars;
	cout << byteSize1 << "  " << byteSize2 << endl;//1  6


	int num[] = { 1,2,3 };
	auto byteSize3 = sizeof(num);
	auto length = byteSize3 / sizeof(num[0]);
	cout << byteSize3 << "  " << length << endl;//12  3

  • 强制类型转换(命名的强制类型转换):  

  1. 一个命名的强制类型转换具有如下形式 : cast-name < type > ( expression ) ; 其中 , type 是转换的目标类型,expression 是要转换的值。cast-name是 static_cast 、dynamic_cast、const_cast 和 reinterpret_cast中的一种 。
  2. static_cast:任何具有明确定义的类型转换,只要不包含底层 const ,都可以使用 static _ cast ;当需要把一个较大的算术类型赋值给较小的类型时, static _ cast 非常有用。
  3. dynamic_cast:dynamic_cast 支持运行时类型识别。
  4. const_cast :只能改变运算对象的底层const。对于将常量对象转换成非常量对象的行为,我们一般称其为“去掉 const 性质
  5. ”。const_cast参数只能是指针,不能用const_cast改变表达式的类型。
  6. reinterpret_cast:通常为运算对象的位模式提供较低层次上的重新解释。
	int a = 10, b = 3;
	double slope1 = a / b;//3
	double slope2 = static_cast<double>(a) / b;//3.333


	const int* num;
	int* _num = const_cast<int*>(num);

  • 空语句

  1. 如果在程序的某个地方,语法上需要一条语句但是逻辑上不需要,此时应该使用空语句。
  2. 一种常见的情况是,当循环的全部工作在条件部分就可以完成时,我们通常会用到空语句。例如,我们想读取输入流的内容直到遇到一个特定的值为止,除此之外什么事情也不做。
  3. 多余的空语句并非总是无害的,如在一个while判断中,条件部分只有判断,则会造成死循环。
	string s;
	while (cin >> s && s != "not")
	{
		;//空语句
	}

  • Switch内部的变量定义 

switch 的执行流程有可能会跨过某些 case 标签。如果程序跳转到了某个特定的 case ,则 switch 结构中该 case 标签之前的部分会被忽略掉。这种忽略掉一部分代码的行为引出了一个有趣的问题:如果被略过的代码中含有变量的定义该怎么办?
        答案是:如果在某处一个带有初值的变量位于作用域之外,在另一处该变量位于作用域之内,则从前一处跳转到后一处的行为是非法行为。

int num = 10;
	switch (num)
	{
	case 5:
		//int a = 0;//错误,会提示:a的初始化操作由"case"标签跳过
		int a;//正确
		break;
	case 10:
		a = 0;
		a++;
		cout << a << endl;
		break;
	default:
		break;
	}

猜你喜欢

转载自blog.csdn.net/weixin_39766005/article/details/106549144