温习C++ Primer【一】

前言

上次看《C++ Primer》还是刚毕业出来工作那会,虽然当时看得比较快,但大体还是翻完了,毕竟自己是半路出家,收获还是很大的,当时的经理说我进步很大,这本书有很大的功劳。俗话说,温故而知新,坚持学习,天天向上。如今已经有了一定的开发经验,回过头来温习这本经典,对c++知识做进一步的学习。在此记录学习的要点,主要是针对个人的知识面做个记录,如,对自己不熟的点做记录,或者对有个用法结合自己的经验所产生的一些感想,并不是对该书所有内容做笔记。可能相关点记录不是特别详细,需要进一步了解可另外搜索相关资料看。当然还有就是c++20要出了,c++11都还没熟悉完,看的是第五版,已经是包含c++11的很多特性了。

内容会根据章节来记录,有些章节没什么内容就不做记录了,下面进入正题。

【第二章-变量和基本类型(上)】

1.算数类型

C++:算数类型
类型 含义 最小尺寸
bool    
char 字符 8位
wchar_t 宽字符 16位
char16_t Unicode字符 16位
char32_t Unicode字符 32位
short 短整型 16位
int 整形 16位
long 长整型 32位
long long 长整型 64位
float 单精度浮点数 6位有效数字
double 双精度浮点数 10位有效数字
long double 扩展精度浮点数 10位有效数字

其中wchar_t在win编程中用到比较多,当我们编写的win程序采用unicode,所有的win api涉及的字面值变量都是宽字符,当然后如果采用的是ASCII,还是用传统char,正常情况都是选用unicode的方式,这样显示非ASCII就不会出现乱码,比如中文。

还有long long是C++11新定义,这个类型一般用在64位程序中,现代机器64位已经很普及,当long无法满足,就使用long long

2.指定字面值类型

字符和字符串字面值
前缀 含义 类型
u Unicode16字符 char16_t
U Unicode32字符 char32_t
L 宽字符 wchar_t
u8 UTF-8(仅用于字符串字面常量) char

定义宽字符型字面值时前缀加L,如L"123",定义utf-8字符串字面值添加前缀u8,如u8“微软雅黑”,即采用utf-8编码字符,使用中文时采用u8的方式很有效

整型字面值
后缀 最小匹配类型
u or U unsigned
l or L long
ll or LL long long
浮点型字面值
后缀 类型
f或F float
l或L long double

注意区别与上面的字符串字面值,这个是放在后缀,如42ULL,为无符号整形字面值,类型是unsigned long long;3.14159L,为扩展精度浮点型字面值,类型为long double

 

3.变量定义

定义变量时,最好给变量初始化,当变量未初始化时,编译器会根据变量类型赋予初值,这个初值可能不是我们想要的,当程序使用到这个变量就可能会出问题,所以都应该养成初始化变量的习惯。

定义并初始化变量一般采用等号,如int sum = 0;

看到这里使用=来初始化,有些人会觉得这是赋值。事实上在c++语言中,初始化和赋值是两个完全不同的操作。然而在很多编程语言中二者的区别几乎可以忽略不计,即使在c++语言中有时这种区别也无关紧要,所以人们特别容易把二者混为一谈。

初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而以一个新值来替代 

 

4.初始化列表

c++11支持初始化列表初始化的方式,即 使用花括号进行初始化,就和数组使用花括号初始化的方式一样

int sum = {0};
int sum{0};
int sum(0);
std::string str{"9999"};
std::vector<int> vec = {2, 2};
std::pair<int, float> testPair = {1, 1.1};

除了内置类型能够使用初始化列表,标准库的大部分容器都能够使用初始化列表,如vector、pair等

我们可以通过查看该类型的构造函数或者重载=函数是否支持传参initializer_list,如果支持initializer_list的传参即可使用初始化列表

//vector定义的initializer_list
vector(_XSTD initializer_list<value_type> _Ilist,
		const _Alloc& _Al = allocator_type())
		: _Mybase(_Al)
		{	// construct from initializer_list
		_Construct(_Ilist.begin(), _Ilist.end());
		}

	_Myt& operator=(_XSTD initializer_list<value_type> _Ilist)
		{	// assign initializer_list
		assign(_Ilist.begin(), _Ilist.end());
		return (*this);
		}

当然也可以通过initializer_list定义自己的类型支持初始化列表,我们看到Qt封装的容器也是支持了

//QList
QList(std::initializer_list<T> args)
//QVector
QVector(std::initializer_list<T> args)
QList<int> intList = {8, 9};

容器使用初始化列表,比使用传统的函数追加的方式简洁很多

 

5.变量声明与定义

为了支持分离式编译,c++语言将声明和定义区分开来。

声明使得名字为程序所知,一个文件如果想使用别处定义的名字则必须包含对那个名字的声明。

定义负责创建于名字关联的实体

变量声明规定变量的类型和名字,在这一点上定义与之相同。但是除此之外,定义还申请了存储空间,也可能会为变量赋一个初始值

变量能且只能被定义一次,但是可以被多次声明

声明变量使用extern关键字,c++中建议不使用这种全局变量的方式,代码结构耦合度变高,具体用法就不介绍了,知道定义和声明是咋回事就够了

 

6.静态类型

c++是一种静态类型语言,其含义是在编译阶段检查类型。其中,检查类型的过程称为类型检查。对象的类型决定了对象所能参与的运算,在c++语言中,编译器负责检查数据类型是否支持要执行的运算,如果试图执行类型不支持的运算,编译器将报错并且不会生成可执行文件。程序越复杂,静态类型检查越有助于发现问题。然而,前提是编译器必须知道每一个实体对象的类型,这就要求我们在使用某个变量之前必须声明其类型。

反过来其他动态类型语言的数据类型在代码运行才会确定,数据类型绑定是代码运行的时候确定的。比如:JavaScript,php 。这些语言定义变量一般是var 变量名,这个变量可以赋各种类型的值。

上述的区别也可称为强类型定义语言和弱类型定义语言。

 

第二章剩下部分内容留在下一篇进行介绍。

 

 

 

 

 

上一篇:C++ Primer第5版 第十八章课后练习答案


下一篇:C++ Primer第三章 心得笔记