成都网站建设设计

将想法与焦点和您一起共享

C++读书笔记——4.表达式-创新互联

表达式 一、sizeof 运算符

sizeof 运算符返回一条表达式 或 一个类型名字所占的字节数。sizeof 运算符满足右结合律,其所得的值是一个size_t 类型的常量表达式。

我们是自2013年创立以来的成都网站建设公司,提供网站建设,电商网站设计开发,外贸网站建设,响应式网页设计,小程序设计、等服务。为客户创造有价值的品牌营销体验,让互联网提升企业的竞争力!
Person person, * p;

	sizeof(Person);    //存储Person类型的对象所占空间的大小
	sizeof person;     //person的类型的大小,即 sizeof (Person)
	sizeof p;          //指针所占空间的大小
	sizeof* p;         //p 所指类型的空间大小,即 sizeof (Person)
	sizeof person.age;  //Person 的 age成员对应类型的大小
	sizeof Person::age; //另一种获取age大小的方式

因为 sizeof 不会实际求运算对象的值,所以即使 p 是一个无效(即 未初始化的)指针,也不会有影响。

在 sizeof 的运算对象中解引用一个无效的指针仍然是一种安全的行为,因为指针实际上并没有被真正的使用。sizeof 不需要真正的解引用指针也能知道它所指对象的类型。

  • 对char 或 类型为char的表达式执行sizeof运算,结果为1
  • 对引用类型执行sizeof运算得到被引用对象所占空间大小
  • 对指针执行sizeof 运算得到指针本身所占空间大小
  • 对解引用指针执行 sizeof 运算得到指针指向的对象所占空间大小,指针不需要有效
  • 对数组执行 sizeof 运算得到整个数组所占空间大小,等价于对数组中的所有元素各执行一次 sizeof 运算 并将所得结果求和。注意:sizeof 运算不会把数组转换成指针处理
  • 对 string 对象 和 vector对象 执行sizeof 运算 只返回该类型固定部分的大小,不会计算对象中的元素占用了多少空间。
二、类型转换

如果两种类型可以相互转换,那么他们就是关联的。

C++ 不会直接将两个不同类型的值相加,而是先根据类型转换规则设法将运算对象的类型统一后再求值。

发生隐式转换的时机:

  • 在大多数表达式中,比 int 类型小的整型值首先提升为较大的整数类型
  • 在条件中,非布尔值转换成布尔类型
  • 初始化过程中,初始值转换成变量的类型;在赋值语句中,右侧运算对象转换成左侧运算对象的类型
  • 如果算术运算 或 关系运算的运算对象有多种类型,需要转换成同一种类型
  • 函数调用时也会发生类型转换
1. 算数转换

算术转换的含义是把一种算术类型转换成另一种算术类型

1. 整型提升

整型提升负责把小整数类型转换成较大的整数类型。对于 bool,char,signed char,unsigned char,short 和 unsigned short 来说,只要它们所有可能的值都能存在 int 里,它们就会提升为 int 类型;否则提升成 unsigned int 类型。

2. 无符号类型的运算对象

如果某一个运算符的运算对象不一致,这些运算对象将转换成同一种类型。

如果一个运算对象是无符号类型,另一个是有符号类型,而其中的无符号类型 不小于 有符号类型,那么有符号运算对象转换成无符号对象。

如果有符号类型大于无符号类型。如果无符号类型的所有值都能存在该有符号类型中,则无符号类型转换成有符号类型;否则有符号类型转换成无符号类型。

3. 理解算数转换
bool flag;
	char cval;
	short sval;
	unsigned short usval;
	int ival;
	unsigned int uival;
	long lval;
	unsigned long ulval;
	float fval;
	double dval;

	3.14159L + 'a'; // 'a' 提升成int,然后int值转换为 long double
	dval + ival;    //ival 转换成 double
	dval + fval;    //fval 转换成 double
	ival = dval;    //dval 转换成int (舍去小数部分)
	flag = dval;    //如果 dval是0 flag为false,否则为true
	cval + fval;    //cval 提升成 int ,然后 int 再转换成 float
	sval + cval;    //sval 和 cval 都提升成 int
	cval + lval;    //cval 转换成 long
	ival + ulval;   //ival 转换成 unsigned long
	usval + ival;   //根据 unsigned short 和 int 所占空间的大小进行提升
	uival + lval;   //根据 unsigned int 和 long 所占空间的大小进行转换
2. 隐式类型转换

数组转换成指针: 在大多数用到数组的表达式中,数组自动转换成指向数组首元素的指针。

当数组被用作 decltype 的参数,或者作为取地址符 & ,sizeof 以及 typeid 等运算符的对象时,不会发生转换。

指针的转换: 常量整数0 或 字面值nullptr 能转换成任意指针类型;指向任意非常量的指针能转换成 void*;指向任意对象的指针能转换成 const void*

转换成布尔类型:如果指针或算数类型的值为0,转换结果是false;否则为true

转换成常量: 允许将指向非常量类型的指针转换成指向相应常量类型的指针,对于引用也是这样。

int i;
	const int& j = i;  //非常量转换成 const int 的引用
	const int* p = &i; //非常量的地址转换成const 的地址
	int& r = j, * q = p; //错误: 不允许const 转换成非常量

类 类型定义的转换:类 类型定义由编译器自动执行的转换,不过编译器每次只能执行一种类 类型转换

3. 显式转换

有时我们希望显式的将对象强制转换为另一种类型。虽然有时不得不使用强制类型转换,但这种方法本质上是非常危险的。

static_cast

任何具有明确定义的类型转换,只要不包含顶层 const ,都可以使用 static_cast。

int i, j;
	double slope = static_cast(j) / i; //强制类型转换以便执行浮点数除法

当需要把一个较大的算术类型 赋值给一个较小的类型时,static_cast 非常有用。

static_cast 对于编译器无法自动执行的类型转换也非常有用。例如:我们可以使用 static_cast 找回存在于 void* 指针中的值:

int d = 3;
	void* ptr = &d;

	double* dp = static_cast(ptr);

强制转换的结果将与原始的地址相等。因此我们必须确保转换后所得的类型就是指针所指的类型。

const_cast

const_cast 只能改变运算对象的底层 const

const char* pc;
	// 正确: 但是通过 p 写值是未定义的行为
	char* p = const_cast(pc);

对于常量对象转换为非常量对象的行为,一般称之为“去掉const性质”。

如果一个对象是 const 常量,再使用const_cast 执行写操作就会产生未定义的后果。

只有 const_cast 能改表表达式的常量属性,使用其他的 命名强制类型转换 改变表达式的常量属性都将引发编译器错误。

const char* cp;

	//错误: static_cast 不能转换掉 const属性
	char* q = static_cast(cp);

	static_cast(cp);

	//错误: const_cast 只改变常量属性
	const_cast(cp);
reinterpret_cast

reinterpret_cast 通常为运算对象的位模式提供较低层次的重新解释。

int* ip;
	char* pc = reinterpret_cast(ip);

	//这一句在运行时就会发生错误
	string str(pc);

reinterpret_cast 本质上依赖于机器。要想安全的使用 reinterpret_cast 必须对涉及 类型 和 编译器实现转换的过程都非常了解。

建议:尽量避免强制类型转换。

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


文章标题:C++读书笔记——4.表达式-创新互联
转载注明:http://chengdu.cdxwcx.cn/article/epjjh.html