====================================================================
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. HDU2473 Junk-Mail Filter 【可删除的并查集】

    HDU2473 Junk-Mail Filter Problem Description Recognizing junk mails is a tough task. The method used ...

  2. BZOJ3489 A simple rmq problem 【可持久化树套树】*

    BZOJ3489 A simple rmq problem Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一 ...

  3. 《DSP using MATLAB》示例Example 8.4

    代码: %% ------------------------------------------------------------------------ %% Output Info about ...

  4. 《DSP using MATLAB》示例 Example 6.25

    代码: % x = [-0.9, 0.81]; [y, L, B] = QCoeff(x, 3) % Unquantized parameters r = 0.9; theta = pi/3; a1 ...

  5. php基础语法(控制语句、数组、函数)

    流程控制 if -else if -else语句: switch语句: while循环: do while循环 for循环: 控制脚本执行进度 die(“输出内容”) exit是die的同义词. sl ...

  6. bzoj 3779 重组病毒——LCT维护子树信息

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3779 调了很久……已经懒得写题解了.https://www.cnblogs.com/Zinn ...

  7. (转)[Android实例] 关于使用ContentObserver监听不到删除短信会话的解决方案

    最近做通讯录的项目,需要实时监听短信的删除,就用到了观察者ContentObserver,怪异的事情就此发生,当我删除一条短信的时候,可以监听到,但是,当我删除整条短信的时候,就无法监听到,查了很多资 ...

  8. JavaFX 之窗口跳转(一)

    一.前言 笔者此处不讲JavaFX的基础API,只针对笔者工作时遇到的问题进行记录与总结. 零基础的网友可以访问 http://www.javafxchina.net/blog/docs/tutori ...

  9. 亚马逊MWS开发套路演示

    MWS是商城网络服务的缩写,具体介绍看这里http://docs.developer.amazonservices.com/zh_CN/dev_guide/DG_IfNew.html.MWS就是一组A ...

  10. outlook2013插件 VSTO开发与部署

    一.背景 最近因为项目需要对outlook开发一个插件,功能是将outlook的邮件作导出功能,需要使用VSTO开发一个插件将邮件进行导出的操作.于是,开始学习VSTO outlook的开发了,折腾了 ...