====================================================================
day02
====================================================================
1.关于类型别名
(1)typedef double d; // d是double的别名
(2)using d = double; // c++11新标准,d是double的别名
注意问题:遇到一条使用了类型别名的声明语句,我们往往会尝试把类型别名替换为它原来的样子,这样是不对的。
eg: typedef char *pstring;
const pstring ctr = 0; // cstr是一个指向char的常量指针,pstring实际上是指向char的指针,
//因此const pstring是指向char的常量指针,而非指向常量字符的指针。
const char *cstr = 0; // 这一句是对const pstring cstr的错误理解,别名不是简单的替换。
2.类型说明符:
(1)auto类型说明符。使用条件:我们常常需要把表达式的值赋给一个变量,而这个表达式的结果的类型我们有时候并不知道,这时可以用auto。auto类型说明符。使用条件:我们常常需要把表达式的值赋给一个变量,而这个表达式的结果的类型我们有时候并不知道,这时可以用auto。
eg: auto item = val1+val2; // 由val1和val2相加的结果来推断item的类型。
(2)decltype类型说明符。使用条件:我们有时希望从表达式的类型推断出要定义的变量的类型,但并不想用该表达式的值来初始化变量,这时可以用decltype。
eg: decltype(f()) sum = x; // sum的类型就是函数f的返回类型。注意,编译器并不实际调用函数f()。
注意点:auto一般会忽略顶层const,而底层const则会保留下来。
const int ci = i,&cr = ci;
auto b = ci; // b是一个整数(ci的顶层const被忽略了)
auto c = cr; // c是一个整数(cr是ci的别名,而ci本身是一个顶层const,被忽略)

但是当将引用的类型设为auto,则保留顶层const。
eg: const int ci = i;
auto &h = ci; // h是一个整型常量引用,绑定到ci

而decltype处理顶层const和引用的方式与auto不同。
如果decltype使用的表达式是一个变量,则decltype返回表达式的类型(包括顶层const和引用在内)
const int ci = i,&cj = ci;
decltype(ci) x = 0; // x的类型是const int
decltype(cj) y = x; // y的类型是const int&,y绑定到常量
如果decltype使用的表达式不是一个变量,则decltype返回表达式结果对应的类型。
int i = 42,*p = &i,&r = i;
decltype(r+0) b; // 表达式的结果是int,因此b是一个int。 decltype(r)的结果是引用类型,
// 如果想让结果是r所指的类型,则可以把r作为表达式的一部分,如r+0
decltype(*p) c; // 表达式的内容是解引用操作,则decltype得到引用类型
decltype((i)) d; // 错误:变量加了一层或多层括号,编译器会把它当成一个表达式,因此d是int&,必须初始化。
注意:decltype((variable))的结果永远是引用!
赋值是会产生引用的一类典型表达式,引用的类型就是左值的类型。也就是说,如果i是int,则表达式i=x的类型是int&

还有,decltype(&p)的结果int**,即一个指向整型指针的指针

还有一点应当注意:当使用数组作为一个auto变量的初始值时,推断得到的类型是指针而非数组,decltype则相反。
eg: int ia[] = {0,1,2,3};
auto ia2(ia); // ia2是一个整型指针,指向ia的第一个元素。
decltype(ia) ia3 ={0}; // ia3是一个含有4个整数的数组,ia有几个元素,ia3就含有几个。

=======================================================================
3.当向string中输入字符串时,string对象会忽略输入的空白符。若想保留输入的空白符,要用getline(cin,str);
eg: string line;
getline(cin,line);
4.string的size()函数的返回值是string::size_type,它是一个无符号类型的值,如果一条语句中已经有了size()函数就不要再使用int了,否则会带来混用无符号和有符号类型的问题。
如s.size()<n,如果n是一个具有负值的int,那么表达式的结果永远是true,因为有符号的值会转换为一个很大的无符号值。
5.处理string中的每一个字符,可使用范围for语句(range for):遍历给定序列中的每个元素,并对序列中的每个值执行某种操作。
for(declaration : expression)
statement;

eg: string str("some string");
for(auto c : str) // 对str中的每个字符c,执行打印操作。 注意:若想改变str中的元素,可以声明为auto &c
cout<<c;
6.若只想处理string中的部分字符,可以使用索引或者迭代器。
7.vector的列表初始化,如何知道括号中的值表示初始值还是元素数量?
如果用的是圆括号,可以说提供的值是用来构造vector对象的。
如果用的是花括号,表示我们想列表初始化该vector对象,初始化过程会尽可能地把花括号内的值当成是元素初始值的列表来处理。如果无法执行,才会考虑其他初始方式。
eg: vector<int> v1(10); // v1有10个元素,每个值都为0
vector<int> v2{10}; // v2有一个元素,值为10
vector<int> v3(10,1); // v3有10个元素,值为1
vector<int> v4{10,1}; // v4有两个元素,值为10和1

vector<string> v5{"hi"}; // v5有一个元素
vector<string> v6("hi"); // 错误
vector<string> v7{10}; // v7有10个默认初始化的元素
vector<string> v8{10,"hi"}; // v8有10个值为"hi"的元素
8.vector对象能高效增长,因此我们倾向于先定义一个空的vector对象,再在运行时向其中添加具体值。
需要注意的是:如果循环体内部有向vector对象添加元素的语句,则不能使用范围for循环(range for)。
9.vector可以通过下标访问元素,但不能通过下标添加元素,添加元素应该使用push_back()。
===================================================================================
10.迭代器。所有的标准库容器都可以使用迭代器,但只有少数几种才同时支持迭代器和下标操作符访问。迭代器类型有两种,iterator和const_iterator。迭代器用到begin和end运算符,它们的返回类型由对象是否为常量来决定。用法:
vector<type>::iterator b = v.begin();
vector<type>::iterator e = v.end();
或者:
auto b = v.begin();
auto e = v.end();
C++11标准引入了两个新函数,cbegin和cend,不论vector对象是否是常量,返回值都是const_iterator。
11.任何一种可能改变vector对象容量的操作,比如push_back(),都会使该vector对象的迭代器失效。
凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素。
12.需要注意,迭代器并未定义"+"操作,它只定义了"-"操作。
两个迭代器相减的结果是它们之间的距离,返回的是difference_type的带符号整型数。
所以,使用二分查找时,使用的是mid = beg + (end-beg)/2,而非mid = (beg+end)/2.
13.与vector相比,数组的缺点有:
(1)数组的维度必须是一个常量表达式,其大小运行过程中不会改变。
(2)数组不允许拷贝和赋值。也就是不能用别的数组来初始化。
(3)数组容易越界,而vector可以用迭代器等机制来控制。
14.指针也是迭代器。数组可以这样用:
eg: int arr[] = {0,1,2,3,4,5,6,7,8,9};
int *e = &arr[10]; // 取arr尾元素下一位置的指针
for(int *b = arr;b != e;++b) // 打印数组中的元素
cout<<*b<<endl;
C++11新标准引入了两个名为begin和end的函数,这两个函数与容器中两个同名成员的功能类似。
这两个函数定义在iterator头文件中,用法:
eg: int arr[] = {0,1,2,3,4,5,6,7,8,9};
int *beg = begin(arr);
int *last = end(arr);
15.初始化一个字符数组时,有两种方法,但它们有所区别:
eg: char a1[] = {'C','+','+'}; // 列表初始化,没有空字符
char a1[] = {'C','+','+','\0'}; // 列表初始化,含有显式的空字符
char a3[] = "C++"; // 拷贝初始化,自动添加空字符!!!
C标准库里cstring头文件中有一些string函数,如strlen(p),strcpy(p1,p2)等,传入此类函数的指针必须指向以空字符作为结束的数组。
eg: char ca[] = {'C','+','+'};
cout<<strlen(ca)<<endl; //严重错误,ca没有以空字符结束,strlen()可能沿着ca在内存中的位置不断寻找,直到遇到空字符。
16.比较两个string变量可以直接比较:
eg: string s1 = "hello";
string s2 = "helloWorld";
if(s1<s2)....
而如果直接比较两个C风格字符串,实际上比较的是指针而非字符串本身。只能使用strcmp()
eg: const char ca1[] = "hello";
const char ca2[] = "helloWorld";
if(ca1<ca2) // 未定义的行为,试图比较两个无关的地址。(使用数组名的时候使用的其实是数组首元素的指针)
17.使用范围for循环处理多维数组时,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型。原因p114
eg: int ia[rowCnt][colCnt];
for(auto &row : ia) // 这一层必须为引用,否则编译无法通过。
for(auto col : row)
...

18.可以使用数组初始化vector对象
eg: int a[] = {0,1,2,3,4,5};
vector<int> ivec(begin(a),end(a));
或者vector<int> ivec(a+1,a+4); //使用a[1]、a[2]、a[3]初始化ivec

C++Primer笔记-----day02的更多相关文章

  1. C++ Primer笔记

    C++ Primer笔记 ch2 变量和基本类型 声明 extern int i; extern int i = 3.14;//定义 左值引用(绑定零一变量初始值,别名) 不能定义引用的引用:引用必须 ...

  2. C++ Primer 笔记(1)基础中的战斗机 输入输出 对输入不定数据处理

    今天打算再重新好好的看一遍C++ Primer这本很经典的书籍,笔记开始: 1.每个C++程序都包含一个或者多个函数,其中必须有一个main,操作系统通过调用main入手运行程序: 2.函数包括:返回 ...

  3. C++ Primer 笔记 第一章

    C++ Primer 学习笔记 第一章 快速入门 1.1 main函数 系统通过调用main函数来执行程序,并通过main函数的返回值确定程序是否成功执行完毕.通常返回0值表明程序成功执行完毕: ma ...

  4. C++primer笔记之顺序容器

    最近又重新拾起C++primer,发现每一次看都会有不同的体验,但每一次看后因为不常用,忘记得很快,所以记笔记是很关键的一环,咋一看是浪费时间,实际上是节省了很多时间.下面就把这一节的内容做一个简单的 ...

  5. c++ primer 笔记 (一)

    昨天开始看的<C++ Primer>,确实不错.希望这周抓紧看完,每天做下笔记,以便以后复习. main函数返回一个值给操作系统   操作系统通过main函数返回的值来确定程序是否成功执行 ...

  6. C++ Primer笔记(1)——连续读取数据、类型对应的尺寸、类型转换、字符串分行写法

    这次要看看C++ Primer,这本基本上就是必读书籍了.下面的内容就是一些之前没有学过的知识的笔记. 读取数量不定的输入数据 虽然很简单,但是还是记一下: #include <iostream ...

  7. C++Primer笔记(3)

    标准库类型string表示可变长的字符序列,使用前先包含string头文件.(哈哈,终于可以逃脱C语言中的str函数系列了.)因为是标准库的一部分,所以string被定义在命名空间std中.所以你懂该 ...

  8. C++ Primer 笔记 第三章

    C++ Primer 第三章 标准库类型 3.1using声明 例: using namespace atd; using std::cin; 3.2string类型 初始化方式 string s1 ...

  9. C++ Primer 笔记 第二章

    C++ Primer 第二章 变量和基本类型 2.1基本内置类型 有算数类型和void类型:算数类型储存空间大小依及其而定. 算数类型表: 类型 含义 最小储存空间 bool 布尔型 - char 字 ...

随机推荐

  1. Codeforces 914H Ember and Storm's Tree Game 【DP】*

    Codeforces 914H Ember and Storm's Tree Game 题目链接 ORZ佬 果然出了一套自闭题 这题让你算出第一个人有必胜策略的方案数 然后我们就发现必胜的条件就是树上 ...

  2. Codeforces 25E Test 【Hash】

    Codeforces 25E Test E. Test Sometimes it is hard to prepare tests for programming problems. Now Bob ...

  3. (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序

    每次使用 Visual Studio 的模板创建一个 UWP 程序,我们会在项目中发现大量的项目文件.配置.应用启动流程代码和界面代码.然而这些文件在 UWP 程序中到底是如何工作起来的? 我从零开始 ...

  4. 实现一个web服务器, 支持php

    暂时还很不完善, 不过框架已经写出来了. https://github.com/tw1996/studyHttpd/

  5. 《DSP using MATLAB》示例Example7.2

  6. java 并发时使用条件变量--Condition

    lock--unlock的方式在实际中使用较少,一般使用synchronized获取对象的内部锁替代,但是lock--unlock对了解synchronized有很大的帮助. 创建一个bank对象用于 ...

  7. Nchan 安装试用(openresty 同时支持)

    备注:        使用nginx最新的源码包(nginx-1.13.6),以及源码安装   1. 下载源码包(nginx+ Nchan) https://nginx.org/download/ng ...

  8. 开始创建一个 Vue 项目

    开始创建一个 Vue 项目 安装 nodejs 略 安装 npm 默认安装时自带了 npm 安装 cnpm 为了更快的下载组件,使用cnpm,cnpm 是淘宝前端的镜像. 使用 npm 安装 cnpm ...

  9. RK3288 error: undefined reference to 'LOGD'

    HAL层和JNI层中的打印都必须包含下面的宏和头文件. 比如:LOGD.LOGE等等. #define LOG_TAG "TEST_LED" #include <utils/ ...

  10. SQLServer中求两个字符串的交集(字符串以符号分隔)

    两个字符串,以特定符号分隔(例如‘,’号),求交集 第一种情况: declare @m varchar(100),@n varchar(100)select @m=',2,3,5,7,8,9,10,' ...