首页 > 代码库 > 《C++ Primer》学习笔记【第一部分 基本语言】

《C++ Primer》学习笔记【第一部分 基本语言】

 

第2章

 

整型的赋值:当我们试着把一个超出其范围的值赋给一个指定类型的对象时,结果如何?答案取决于类型是signed还是unsigned的。对于unsigned,编译器会将该值对unsigned类型的可能取值数目求模然后取所得值;对于signed类型,未定义行为,很多处理器处理方式和unsigned类似。

 

字符串字面值的连接:std::cout << "multi-line" L"literal " << std::endl;结果未定义,即连接不同类型的行为标准未定义。

 

const:全局作用域声明的const对象默认为文件的局部变量,非const变量默认为extern,要使const变量能够在其他文件访问,必须显示指定为extern。

顶层const,规定某对象的值不能变;底层const,类型如果由底层常量定义,则不能忽略。

引用:一般引用为左值引用,即只能绑定到对象上。const引用可以绑定到非常量的对象或一般表达式。右值引用必须绑定到右值表达式。

double d = 1.0;

const int &x = d;//ok

const int &y = 4; //ok

int &z = 4;//error

int &&zz = 4;//右值引用,ok

指向指针的引用:int *p; int *&r = p;//从右往左读,r是一个引用,引用一个指针,这个指针指向int

类型别名:typedef 

注意,typedef char *pstring; const pstring cstr = 0;const pstring是一个指向char的常量指针。

头文件:头文件用于声明而不是用于定义,但有三个例外:1.可以定义类 2.可以定义const对象 3.可以定义inline函数。

(在头文件中加入或修改内联函数时,使用了该头文件的所有源文件都必须重新编译)

auto说明符:auto定义的变量必须有初始值,由编译器通过初始值来推断类型。一条声明语句中,只能有一个基本类型。

auto i = 0, *p = &i;//ok

auto sz = 0, pi = 3.14;//error, 类型不同 

 

第3章

命名空间的using声明:有一种情况下,必须总是使用完全限定的标准库名字:在头文件中。即头文件中,不该用“using namespace std; cout << endl; ”,而该用"std::cout << std::endl;"

理由是头文件的内容会被预处理器复制到程序中,会造成包含该头文件的每个程序中都放置了同一using声明,不论该程序是否需要using声明。

:: operator操作符 : 作用域操作符。在其左操作数的作用域内找到其右操作数的名字。用于访问某个命名空间的名字,如std::cout,同样地,可用于从某个类取名字,如string::size_type。

指针和const限定符:

const int a 等价于int const a。

const int *p 等价于 int const *p, 表示一个指针,指向int类型的const对象。

int * const p表示一个const指针

多维数组和引用,指针

int ia[3][4];

int (&row)[4] = ia[1];//即*(ia+1)

int (*p)[4] = ia+1;//从右往左读,p是一个指针,指向一个维度是4的数组,数组的元素类型是int型。

*(*p+2) = 233;//ia[1][2] = 233

 用typedef简化指向多维数组的指针:

typedef int int_array[4];

int_array *ip = ia;

 

第6章

使用预处理器进行调试

#ifndef NDEBUG

...

#endif

预处理器还定义了其余4种在调试时非常有用的常量

__FILE__:文件名

__LINE__:当前行号

__TIME__:文件被编译的时间

__DATE__:文件被编译的日期

另一个常见的调试技术是使用NDEBUG预处理变量以及assert断言预处理宏,assert宏在cassert头文件中定义,只要NDEBUG未定义,assert就求解表达式,为false时终止程序。

 

第7章 函数

引用形参:应该将不需要修改的引用形参定义为const引用。普通的非const引用形参在使用时不灵活,这样的形参既不能用const对象初始化,也不能用字面值或产生右值的表达式初始化。

通过引用传递数组:f(int (&arr)[10])    //OK, 是维度为10的int数组的引用

         f(int &arr[10])    //error

多维数组的传递:int *arr[10]; //维度为10的int型指针数组

        int(*arr)[10];//arr是一个指针,指向维度为10的int型数组

函数声明

在头文件中提供函数声明,定义函数的源文件应包含该函数的声明。函数声明中的形参名会被忽略。既可以在声明中也可以在定义中指定默认形参,但一个文件中只能为一个形参指定默认实参一次。

类的成员函数:含有额外的、隐含的形参; const成员函数使隐含的this形参改为const类型, 即不能修改this的数据成员; const对象、指向const对象的指针或引用只能调用其const成员函数。

 函数指针:bool (*pf) (const string &, const string &);//pf是一个指向函数的指针,该函数带两个const string&类型的形参和bool类型的返回值。

用typedef简化函数指针的定义, typedef bool (*cmpFcn) (const string &, const string &);

bool lengthCompare(const string &, const string &);

cmpFcn pf1 = lengthCompare;

lengthCompare("hi", "bye");

pf1("hi", "bye");    //ok

(*pf1)("hi", "bye");  //ok

指向重载函数的指针:.....(此坑待填)

 

第8章 标准IO库

IO对象不能复制,即1.IO对象不能存储在vector或其他容器中   2.如果需要传递或返回IO对象,必须传递或返回指向该对象的指针或引用。

一般情况下,如果要传递IO对象以便对它进行读写,用非const引用的方式传递这个流对象。(因为要对IO对象进行读写)

条件状态:IO标准库管理一系列条件状态成员,用来标记给定的IO对象是否处于可用状态,或碰到了哪种特定的错误。流的状态由bad、fail、eof和good操作揭示;clear和setstate操作用于改变条件成员的状态。

输出缓冲区的管理:以下几种情况将导致缓冲区的内容被刷新。

1.程序正常结束时,清空所有输出缓冲区。

2.在一些不确定的时候,缓冲区可能已经满了,缓冲区会在下一个值之前刷新。

3.用操作符显示刷新缓冲区,如endl。

4.每次输出操作执行完后,用unitbuf操纵符设置流的内部状态,清空缓冲区。

5.将输出流和输入流关联(用tie函数)起来。在此情况下,在读输入流时刷新其关联的输出缓冲区。标准库将cin和cout绑在一起。

(如果程序崩溃,则不会刷新缓冲区,最好的方法是保证所有的输出操作都显式地调用了flush或endl; 交互式系统通常应确保它们的输入和输出流是绑在一起的)

文件的输入与输出:

如果要把fstream对象与另一个不同的文件关联,则必须先close现在的文件,再open另一个文件。

考虑如何使用循环语句打开一些文件?

 1 //files是一个vector对象,包含一些要打开并读取的文件名
 2 //每次循环构造一个名为input的ifstream的对象
 3 while(it != files.end()){
 4     ifstream input(it->c_str());
 5     if(!input) break;
 6     while(input >> s) process(s);
 7     ++it;
 8 }
 9 //也可将input定义移到while外,那么需要更仔细地管理流对象。
10 //每次需要打开新文件,故要关闭当前的文件流
11 //关闭流不能改变流的内部状态,如果读写操作失败,状态将保持为错误模式,故需要调用clear
12 ifstream input;
13 vector<string>::const_iterator it = files.begin();
14 while(it != files.end()){
15     input.open(it->c_str());
16     if(!input) break;
17     while(input >> s) process(s);
18     input.close();
19     input.clear();
20     ++it;
21 }

文件模式:....(此坑待填)

字符串流:

 1 //1.如何每次读入一行,并分别处理每行中的每个单词
 2 string line, word;
 3 while(getline(cin, line)){
 4     istringstream stream(line);
 5     while(stream >> word){
 6         // do sth
 7     }
 8 }
 9 //2.stringstream提供的转换和/或格式化
10 //一般情况下,使用输入操作符读取string时,空白符会忽略。
11 int val1 = 512, val2 = 1024;
12 ostringstream format_message;
13 format_message << "val1: " << val1 << "\n" 
14                << "val2: " << val2 << "\n";
15 istringstream input_istring(format_message.str());
16 string dump;
17 input_istring >> dump >> val1 >> dump >> val2;
18 cout << val1 << " " << val2 << endl;

 

《C++ Primer》学习笔记【第一部分 基本语言】