C++Primer笔记-----day02
====================================================================
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的更多相关文章
- C++ Primer笔记
C++ Primer笔记 ch2 变量和基本类型 声明 extern int i; extern int i = 3.14;//定义 左值引用(绑定零一变量初始值,别名) 不能定义引用的引用:引用必须 ...
- C++ Primer 笔记(1)基础中的战斗机 输入输出 对输入不定数据处理
今天打算再重新好好的看一遍C++ Primer这本很经典的书籍,笔记开始: 1.每个C++程序都包含一个或者多个函数,其中必须有一个main,操作系统通过调用main入手运行程序: 2.函数包括:返回 ...
- C++ Primer 笔记 第一章
C++ Primer 学习笔记 第一章 快速入门 1.1 main函数 系统通过调用main函数来执行程序,并通过main函数的返回值确定程序是否成功执行完毕.通常返回0值表明程序成功执行完毕: ma ...
- C++primer笔记之顺序容器
最近又重新拾起C++primer,发现每一次看都会有不同的体验,但每一次看后因为不常用,忘记得很快,所以记笔记是很关键的一环,咋一看是浪费时间,实际上是节省了很多时间.下面就把这一节的内容做一个简单的 ...
- c++ primer 笔记 (一)
昨天开始看的<C++ Primer>,确实不错.希望这周抓紧看完,每天做下笔记,以便以后复习. main函数返回一个值给操作系统 操作系统通过main函数返回的值来确定程序是否成功执行 ...
- C++ Primer笔记(1)——连续读取数据、类型对应的尺寸、类型转换、字符串分行写法
这次要看看C++ Primer,这本基本上就是必读书籍了.下面的内容就是一些之前没有学过的知识的笔记. 读取数量不定的输入数据 虽然很简单,但是还是记一下: #include <iostream ...
- C++Primer笔记(3)
标准库类型string表示可变长的字符序列,使用前先包含string头文件.(哈哈,终于可以逃脱C语言中的str函数系列了.)因为是标准库的一部分,所以string被定义在命名空间std中.所以你懂该 ...
- C++ Primer 笔记 第三章
C++ Primer 第三章 标准库类型 3.1using声明 例: using namespace atd; using std::cin; 3.2string类型 初始化方式 string s1 ...
- C++ Primer 笔记 第二章
C++ Primer 第二章 变量和基本类型 2.1基本内置类型 有算数类型和void类型:算数类型储存空间大小依及其而定. 算数类型表: 类型 含义 最小储存空间 bool 布尔型 - char 字 ...
随机推荐
- 值类型struct在foreach中的陷阱
最近踩了一个坑,为了优化代码,把class改为了struct,结果发现原来的初始化语句没有预期的运行,伪代码如下: public struct A { bool _isActive; public v ...
- BZOJ5125: [Lydsy1712月赛]小Q的书架(DP决策单调性)
题意:N个数,按顺序划分为K组,使得逆序对之和最小. 思路:之前能用四边形不等式写的,一般网上都还有DP单调性分治的做法,今天也尝试用后者写(抄)了一遍.即: 分成K组,我们进行K-1次分治,get( ...
- 优化 UWP 中图片的内存占用
跟图片打交道的 UWP 应用或多或少都会遇到图片带来的性能问题,就算不主要处理图片,做个论坛做个新闻客户端都涉及到大量图片.一个帖子.一篇文章里多半都是些高清大图,这些图片一张即可占用程序 1~2M ...
- 【java基础】java中String的注意点
[java的内存模型] 一.Java内存模型 按照官方的说法:Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配. JVM主要管理两种类型内存:堆和非堆,堆内存(Hea ...
- 在Eclipse中导入dtd和xsd文件,使XML自动提示
DTD 类型约束文件 1. Window->Preferences->XML->XML Catalog->User Specified Entries窗口中,选择Add ...
- 网络赛牡丹江赛区E ZOJ3813(线段树)
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5345 给定序列P,定义序列S为P反复重复得到的一个无穷长的序列: if P = ...
- logcat调试系统
日志存放位置:/dev/log shell@xxx:/ $ ls /dev/log -l crw-rw-rw- root log , -- : events crw-rw-rw- root log , ...
- DP 过河卒
棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为“马拦过河卒”. 棋盘用坐标 ...
- python set集合 以及 深浅拷贝
set集合 特点: 无序, 不重复, 元素必须可哈希(不可变) 作用: 去重复 本身是可变的数据类型. 有增删改查操作. frozenset()冻结的集合. 不可变的. 可hash的 深浅拷贝() 1 ...
- 【转】Jmeter测试报表相关参数说明
Jmeter测试报表相关参数说明 采用Jmeter测试工具对web系统作的负载测试,得出的响应报表,数据比较难懂,现作一具体说明. 以下是在一次具体负载测试中得出的具体数值,测试线程设置情况为:线程数 ...