《C++Primer》复习——with C++11 [1]

1.头文件中不应包含using声明,因为头文件的内容会拷贝到所有引用到他的文件中去,如果头文件里有谋个using声明,那么每个使用了该头文件的文件就会有这个声明,由于不经意间包含了一些名字,反而可能产生始料未及的名字冲突。

2.string对象的拷贝初始化和直接初始化。string str1 = "Hello";是拷贝初始化,编译器吧等号右侧的初始值拷贝到新创建的对象中去。使用getline读取一行, getline(cin, line),函数从给定的输入流中读取内容,知道遇到换行符为止,但是换行符并没有被读入line中去。

1 string line;
2 while (getline(cin, line))
3     cout << line << endl; 

getline的empty和size操作,empty操作返回string对象是否为空,返回一个对应的布尔值,size返回string对象的长度,即string对象中字符的个数。

1 while (getline(cin, line))//如果串不空则输出
2     if (!line.empty())
3         cout << line << endl;
4 while (getline(cin, line))//输出字符数量大于30的串
5     if (line.size > 30)
6         cout << line << endl;

string对象的size_type类型是一个无符号整形,用于表示返回自防护大小的类型,允许通过auto来推断他的类型

auto len = line.size(); //len的类型就是size_type,不过使用的auto自动确定了类型而不需要事先了解size返回类型

同时string对象也顶一了比较的操作符 != , == , > , <, <= , >= 。string对象也允许对象间的相加,string1+string2。处理字符串中的每个字符,判断特定的字符,用函数库cctype定义了一组表尊库函数处理这些。例如

1 isalunm(c)//是字母或数字为真
2 isalpha(c)//是字母为真
3 iscntrl(c)//是控制字符为真
4 isdigit(c)//是数字为真
5 isgraph(c)  // 不是空格但可以打印
6 islower(c)  //是小写?
7 isprint(c)    //是否是可打印的字符
8 tolower(c)    //如果大写字母,转换小写,否则输出
9 toupper(c)    //如果小写字母,转换成对应的大写,否则原本输出

使用基于范围的for语句,用范围for把string对象中的字符每行一个输出。

1 string str("some stringA");
2 for (auto c : str)            //对于str中的每一个字符
3     cout << c << endl;    //输出当前字符    

如下代码使用范围for语句和ispunct函数来统计string对象中标点符号的个数。

1 string s("hello world!!");
2 decltype(s.size()) punct_cnt = 0;
3 for (auto c : s)
4     if (ispunct(c))
5         ++punct_cot;
6 cout << punct_cnt << "puncts in: " << s << endl;

string对象支持[]下标访问,想要编写一个吧0到15之间的数字转换成对应的十六进制形式,初始化一个字符串令其存放16个十六进制数字。

1 const string hexdigits = "0123456789ABCDEF";
2 string result;
3 string::size_type n;
4 while (cin >> n)
5     if (n < hexdigits.size())
6         result += hexdigits[n];
7 cout << "Your hex number is:" << result << endl;

3.vector是一个类模板,vecotr表示对象的集合,其中所有的对象类型一致。因为引用不是对象,所以不包含存在引用的vector,其他大多数非引用类型和类类型都可以构成vector对象,vector的初始化方法如下:

1 vector<T> v1;              //空
2 vector<T> v2 = v1;         //拷贝初始化
3 vector<T> v2(v1);          //默认初始化
4 vector<T> v3(n, val);      //v3含有n个val初始值
5 vector<T> v4(n);           //v4包含了n个重复执行了初始化的对象
6 vector<T> v5= {a, b, c, ...};//v5包含了初始值个数的原色
7 vector<T> v5 {a, b, c, ...};//等价于上面
vector<string> v1{"hello", "world", "!!!"};//列表初始化
vector<string> v2("hello", "world", "!!!");//错误

vector对象的添加元素,首先创建一个空对象,然后用push_back方法相其中添加元素。

1 vector<int> v2;                 //空vector对象
2 for (int i = 0; i != 100; ++i)
3     v2.push_back(i);        //一次把整数值放在v2的尾端
1 string word;
2 vector<string> text;    //空对象
3 while (cin >> word)
4     text.push_back(word);   //把word添加到text后面

通常的情况下都是先定义一个空的vector对象,然后在使用的时候添加值,而不开始时候直接复制,vector对象支持高效率的添加元素。vector的操作很多与string的操作类似或者相同,如empty、size、[]、!= == > < <= >= 等。可以使用范围for语句处理vector对象的所有元素

1     vector<int> v{1,2,3,4,5,6,7,8,9};
2     for (auto &i : v)
3         i *= i;
4     for (auto i: v)
5         cout << i << " ";
6     cout << endl;
1 vector<unsigned> scores(11, 0);
2 unsigned grade;
3 while (cin >> grade)
4 {
5     if (grade <= 100)
6         ++scores[grade/10];  //很好的体现了C++代码的简洁性
7 }

使用下表的时候确认了他的合法性,属于0 到 scores.size() - 1的才是有效的范围。切记不可使用下标的形式添加元素,例如有100个元素,我们使用 v[100]来添加第101个元素,这是错误的,如果要添加元素,应该使用push_back方法。

4.迭代器是一个对象,它同指针一样,可以通过它来访问容器中的元素,也可以指向其他元素。获取迭代器不是通过取地址符,而是通过容器对象的一些方法返回之,比如begin、end分别返回了指向第一个元素和最后一个元素的下一个为止的迭代器,下一个位置的迭代器意味着并不是指向最后一个位置,这个位置的迭代器没有实际意义,仅仅作为一个标记。如果容器为空,则begin和end返回的是同一个迭代器,都是韦后迭代器。通过 ==  、!=符号来比较迭代器是否相同。

1 string s("some string");
2 if (s.begin() != s.end())
3 {
4     auto it = s.begin();
5     *it = toupper(*it);
6 }

通过++运算符我们将迭代器从原来的元素移动到下一个元素,因为end返回的迭代器并不实际指向谋个元素,所以不能对它进行递增或者递减以及解引用的操作。

1 for (auto it = s.begin(); it != s.end() && !isspace(*it); ++it)
2     *it = toupper(*it);

如果对象是敞亮,begin和end返回的迭代器类型是 const_iterator,如果不是敞亮,返回的是iterator类型。为了专门的带const_iterator类型,C++11引入了两个函数分别是cbegin和cend泳衣返回const_iterator类型的迭代器。书上特别的声明了:凡是使用了迭代器的循环体,都不要想迭代器所属的容器添加元素。迭代器相关的操作也有 >/</!=/==之类。下面是使用迭代器写的二分搜索。

1 auto beg = text.begin(), end = text.end();
2 auto mid = text.begin() + (end - beg)/ 2;
3 while (mid != end && *mid != sought){
4     if (sought < *mid)
5         end = mid;
6     else
7         beg = mid + 1;
8     mid = beg + (end - beg) / 2;
9 }

对于数组,使用迭代器的函数begin和end也可以获取指向数组首元素和为元素下以位置的指针。

5.try语句块和异常处理。throw表达式引发一个异常,throw表达式包含关键字和紧随其后的一个表达式,其中表达式的类型就是抛出的异常类型,throw表达式后面通常紧跟一个分好,从而构成一条表达式语句。

 1 #include <iostream>
 2 #include <stdexcept>
 3 using namespace std;
 4 void fun(int a, int b)
 5 {
 6     if (a == b)
 7         throw runtime_error("A == B");
 8     else
 9         throw runtime_error("A != B");
10 }
11 int main()
12 {
13     int x = 1, y = 1;
14     try{
15         fun(x, y);
16     }catch(runtime_error err){
17         cout << err.what();
18     }
19     return 0;
20 }

这段代码很明白的演示了throw、try、catch的用法,runtime_error在标准函数库头文件stdexcept中定义。当异常抛出时候,首先搜索抛出该异常的函数,如果没有找到匹配的catch字语句,种植该函数,病在调用该函数中继续寻找,如果还是没有找到匹配的catch语句,这个新的函数也将被种植,继续搜索调用它的函数,以此类推,沿着程序的执行路径逐层回退,知道找到适当的类型catch语句为止。如果最终没有找到catch,程序转到名为terminate的标准库函数,该函数的行为与系统有关,一般情况下,执行该函数将导致程序非正常退出。

栈展开过程沿着乔涛函数的调用莲不断查找,知道找到了与异常匹配的catch为止,或者没有找到而退出。栈展开过程时,局部对象被销毁,栈展开过程中如果退出了谋个块,编译器将负责确保在这个块中创建的对象能被正确的销毁,如果谋个局部对象是类类型,那么会调用析构函数。如果异常发生在构造函数中,则当前的对象可能只构造了一部分,有的成员已经初始化了,而另外一些成员没有初始化,也保证对象能够正常的销毁。如果析构函数也要抛出异常,那么就在析构函数自身内部try、catch和throw,不能留给别人处理,要在析构函数内部处理完成。更多继承类型的异常在复习了继承以后再来讲述。

时间: 2024-10-12 19:02:15

《C++Primer》复习——with C++11 [1]的相关文章

0801-----C++Primer听课笔记----------C++11新特性 function 和 bind 的简单使用

1.function 和 函数指针 1.1 function有函数指针的功能,但是使用起来明显比函数指针更加灵活和方便. 1.2 函数指针和function的用法实例. 1.2.1 函数指针首先要清楚函数指针的类型,如void (*)(int, char)等,然后声明一函数指针变量直接调用即可. #include <iostream> using namespace std; /* * 函数指针的用法 */ void test(int i,double j){ cout << i

《C++Primer》复习——with C++11 [3]

1.我们的程序经常使用很多IO库,用来输入输出例如:istream(输入流)类型,提供输入操作. ostream(输出流)类型, 提供输出操作. cin, 一个istream对象,从标准输入读取数据. cout,一个ostream对象,向标准输出写数据. cerr, 一个ostream对象,通常用于输出程序错误消息,写入到标准错误. >>/<<运算符,用来从一个istream/ostream对象输入输出数据. 不能对IO对象拷贝和赋值,由于不能拷贝IO对象,因此不能将形参或返回类型

《C++Primer》复习——with C++11 [2]

1.数组引用形参,C++允许将变量定义成数组的引用,给予同样的道理,形参也可以是数组的引用,此时引用形参绑定到对应的实参上,也就是绑定到数组上 1 void print(int (&arr)[10]) 2 { 3 for (auto elem : arr) 4 cout << elem << endl; 5 } 包含有可变形参 的函数,C++11提供了两种主要的方法:如果所有的实参类型相同,可以传递一个名为initializer_list的标准库类型:如果实参的类型不同,可

2019年造价工程师考试复习必备之11项费用速记顺口溜

日子一天天在过,不知道考生们是否有坚持每天学习,每天提升自己,备考造价要经过好几个月的时间,千万不要懈怠,备考状态在线,也要找到科学的学习方法,让复习变得轻松起来.小编特搜集整理了11项费用速记顺口溜,报考2019年一级造价工程师的小伙伴们快来学习吧! (1)特殊--特殊设备安全监督检验费:注意是按项目所在省规定标准取费,不是在按企业所在省取费. (2)环境--环境影响评价费:在工程项目投资决策阶段,由建设单位承担. (3)建--建设管理费:建设单位采用工程总承包方式,其总包管理费从建设管理费中

c++primer复习(六)—面向对象编程

1 C++中,通过基类的引用(或指针)调用虚函数时,发生动态绑定,两个条件(基类引用或指针.虚函数)缺一不可 虚函数的默认实参将发生静态绑定 2 继承层次的根类一般都需要定义虚析构函数 3 任意非static成员都可以是虚析构函数,static成员函数不能是虚析构函数(应为static成员不是属于某个对象的,而是属于整个类的) 4 protected成员:派生类只能通过派生类对象访问基类的protected成员,派生类对其基类类型对象的protected成员没有特殊的访问权限 private成员

《C++primer》v5 第11章 关联容器 读书笔记 习题答案

11.1 map是关联容器,vector是顺序容器 11.2 略 11.3 int main() { map<string,int> word; string s; while(cin>>s) word[s]++; for(auto i:word) cout<<i.first<<" "<<i.second<<endl; return 0; } 11.4 void convers(string &s) { s

【C语言学习】《C Primer Plus》第11章 字符串和字符串函数

学习总结 1.字符串(character String)是以空字符串(\o)结尾的char数组. 2.gets()方法代表get String,它从系统的标准输入设备(通常是键盘)获取一个字符串,当字符串遇到换行符(\n)时就结束输入,丢弃\n符号,然后在字符串后添加空字符(\0)然后把这个字符串交给调用它的程序.Gets方法的构造原型是 char *gets(char *s){ … If(EOF) return NULL;//伪代码,说明用 … return s; } 从函数原型可以看,get

C++ Primer学习总结 第11章 关联容器

第11章 关联容器 1.    使用map的简单例子: 运行结果为: 2.    初始化map和set: 3.    set与multiset的区别: 4.    使用map和set时,其元素类型必须是定义了严格弱序的(即定义了<号比较的),如果元素类型没有定义<号操作也可以通过外部函数来比较: 5.    pair类型:pair是一个用来生成特定类型的模板. pair的默认构造函数对数据成员进行值初始化. 6.    遍历map和set关联容器: 7.    如何往set和map中添加指定元

c++primer复习(一)

1 const对象默认为文件的局部变量(P50) a.cpp const int a = 1; b.cpp extern int a;//undefined reference to "a" a.cpp int a = 1; b.cpp extern int a;//OK a.cpp extern const int a = 1; b.cpp extern int a;//OK 即非const变量默认为extern,const变量要在其他文件中被访问,必须显式指定为extern 2 c