栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++Primer学习笔记(3)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++Primer学习笔记(3)

 这篇笔记的内容是表达式。

一、表达式的基本概念

 1.基本概念

 值得注意的是函数也是一种运算符。符号的运算符类型是编译器根据上下文来决定的。

常见的运算符的作用有:

组合运算、运算对象转换、重载运算符、左值和右值。

其中有一个值得注意的是:decltype在使用指针类型时

 如下,即decltype中放指针时需要注意,其赋值的是引用,而不是int。

	int a=1,* p=&a;
	decltype(*p) delc1=*p;
	decltype(p) delc2 = p;
	decltype(&p) delc2 = &(p);
二、算术运算符

这个好像没啥好说的。

三、逻辑与关系运算符

这个好像也没啥好说的。

四、赋值运算符

这个好像也没啥好说的。

五、递增递减运算符

这个好像也没啥好说的。

六、成员访问运算符

 这里主要得注意一个点。对象指针要用点来调用函数的话要加上括号。

 七、条件运算符

这个还是蛮有用的,可以精简代码量。条件运算符也称三目运算符。

1.条件运算符嵌套 

 值得注意的是不要嵌套太多层,要不然可读性降低了。

 2.输出表达式中使用条件运算符

 以上语句执行的结果:

 八、位运算符

 

 1.移位运算符

 2.位求反运算符

 3.位与、位或、位异或运算符

 

 4.位运算符使用

 关于1UL<<27

0UL 表示无符号长整型 0
1UL 表示无符号长整型 1
1UL<<27  表示输入一个仅27位为1的无符号数  
 5.移位运算符(又称IO运算符)满足左结合律

 主要是注意优先级,尤其在打印的时候很容易出问题。

九、sizeof运算符

 需要注意的是sizeof一个数组会返回数组的大小,而sizeof一个string或者vector返回的都是固定值。这也说明了string和vector的本质是封装的对象而不是基本数据类型。

另外一个值得注意的就是sizeof的返回值是size_t类型。size_t类型是一个无符号整型数。

在32位平台运行的话:

 

 在64位平台运行的话:

 

最终总结即size_t的大小是由运行的目标平台所决定的,其代表目标平台下最大可能的数组尺寸。关于size_t可进一步参考:size_t 这个类型的意义是什么? - 知乎

 十、逗号运算符

这个似乎也没啥好说的。

十一、类型转换 1.隐式转换

1)举例

 即注意,ival在实际执行过程中是将3转换为double类型与3.14运算,最终再截断的。

2)隐式转换发生的情况

 2.算术转换

通俗点解释就是把两种不同数据类型的变量放一块了,最终计算机会怎么处理这两个变量。

1)整型提升

怎么个提升这些都是需要经验积累的

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

这个地方还蛮复杂的。 接下来举几个例子把。

	//unsigned int与int之间的较量--a>b>0
	unsigned int a1 = 2;
	int b1 = 1;
	cout << typeid(a1 + b1).name() << endl << a1 + b1<0>b
	unsigned int a2 = 2;
	int b2 = -3;
	cout << typeid(a2 + b2).name() << endl << a2 + b2 << endl;
	//unsigned int与int之间的较量--a>0>b
	unsigned int a3 = 2;
	int b3 = -1;
	cout << typeid(a3 + b3).name() << endl << a3 + b3 << endl;
	//unsigned int与long之间的较量,最后是unsinged long比较有意思了
	unsigned int a4 = 2;
	long b4 = -1;
	cout << typeid(a4 + b4).name() << endl << a4 + b4 << endl;
	//unsigned int与long long之间的较量
	unsigned int a5 = 2;
	long long b5 = -1;
	cout << typeid(a5 + b5).name() << endl << a5 + b5 << endl;
	//unsigned int与double之间的较量
	unsigned int a6 = 2;
	double b6 = -1;
	cout << typeid(a6 + b6).name() << endl << a6 + b6 << endl;
	//unsigned int与float之间的较量,值得关注的是虽然float与unsigned int都只有四位,
     //但是float的级别就是更高
	unsigned int a7 = 2;
	float b7 = -1;
	cout << typeid(a7 + b7).name() << endl << a7 + b7 << endl;

运行结果:

 3)大量例子举例

 2.其他的隐式转换

 关于数组的转换比较恶心,数组名说是指针又和指针有所区别,举一下几个例子:

	int ia[10];//sizeof数组名得到的值是整个数组所占空间
	cout << typeid(ia).name() << endl << sizeof(ia)<< endl;
	decltype(ia) ib;//ib直接是数组
	cout << typeid(ib).name() << endl << sizeof(ib) << endl;
	int* ic = ia;//ic还是一个int指针
	cout << typeid(ic).name() << endl << sizeof(ic) << endl;
	int (&id)[10] = ia;//使用引用进行数组赋值
	cout << typeid(id).name() << endl << sizeof(id) << endl;

 运行结果:

 比较值得注意的是,对隐式转换来说,非常量可以转常量,常量不能转为非常量了,这是一条不归路。

3.显式转换

 即光明正大的强转。结合参考网站进行理解更佳:C++强制类型转换运算符(static_cast、reinterpret_cast、const_cast和dynamic_cast)

1)比较安全的强转

 关于左值右值,参考:什么是左值?_百度知道

C语言左值与右值详解 

static_cast

static_cast基本上能满足正常的cast需求了。

 const_cast

 这一块有点混乱,下面举个几例子说明:

	//example1
    char c = 'a';
	const char* pc = &c;
	char* p = const_cast(pc);
	*p = '1';
	cout << c << endl <<*pc<(pc1);
	*p1 = '2';
	cout << c1 << endl <<*pc1<(&c1);
	*p3 = '3';
	cout << c1 << endl << *pc1 << endl << *p3 << endl << "**************" << endl;
	//强行对&c1直接做强转后的指针也无法改变c1的值

	//example4
    string s1 = static_cast(&c1);
	string s2 = static_cast(pc);//即输出地址,地址不是const的
	cout << (string)s1 << endl << (string)s2 << endl;
	//string s = const_cast(pc1);//错的,const_cast无法改变属性

 运行结果:

 最值得注意的是example1和example2,这里面有大坑,详情看里面注释。

reinterpret_cast

 reinterpret_cast是功能最强大的cast,同时也是最不安全的,在使用的时候要小心谨慎。

4.旧版本的强制转换

 从学C语言过来的话还是会更经常用这种,更简单。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/664609.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号