C++ Primer 第一部分基本语言

第1章 快速入门

1,介绍main函数的意义和其基本结构,return语句。不同平台下编译与执行程序。
2,两个类isrteam与otream与它们的实例对象cin,cout,cerr,clog。说明了程序中基本的输入与输出。“<<”与”>>”作为操作符,左操作符是一个iostream 对象,右操作符是一个变量。返回值仍为一个iostream对象,所以输入或输出可以这样 cout<<”a=”<<a<<endl 连着写。
3,C++中的两种注释风格以及需要注意的问题。
4,控制结果:循环(while与for),选择(if…else…)。引入一个计算两个数之间所有整数的和例子。
5,C++最重要的特性:类。说明了在类上定义的一些操作,简单介绍成员函数,用“.”来调用成员函数。
6,书的开头引入的一个书店书目的问题,用一个完整的程序,进一步说明了C++程序中的一些基本元素。当然Scales_item并没有具体的实现代码。

第2章 变量和基本类型

1,执行算术运算时,数据类型的选择:short 一般很少使用,容易产生越界。char类型在一些实现中有时作为signed处理,而有时作为unsigned处理,所以只用char来表示字符是明智之举。所以在大多数的时候使用int就没有问题,在很多机器上int用4个字节存储,足够满足大部分计算的要求。浮点型的选择就很简单了,使用double类型基本不会有什么错误,而且有可能会比float计算代价低。

2,字面值常量。只有内置类型存在字面值。宽字符的类型wchar_t,其实字面值字符常量前面加一个“L”,如wchar_t c=L'A';多行字符串可以用‘\'进行连接,但是\后面不可以有任何空格或制表符,下一行字符串字面值前也不可以有任何空格和制表符。

3,介绍了变量的概念,变量名的命名规范:1)变量名一般用小写字母;2)标识符最好有意义;3)多个词之间用下划线或内嵌的单词第一个字母大写。另外,标识符不要以两个连续的下划线或下划线+大写字母命名。

4,定义对象(变量定义)。变量在定义的时候可以进行初始化,可以选择复制初始化(不要理解为了赋值),也可以选择直接初始化。

代码如下:

int ival(1024); // direct-initialization
int ival = 1024; // copy-intialization

5,定义与声明的区别;注意extern的使用。

6,const限定符的用法。const 定义的变量不能修改,所以必须在定义的时候进行初始化。const变量如果想在多文件中使用,必须在定义的时候就声明为外部变量,即用extern。

7,引入与const。

1)非cosnt引用只能绑定到与该引用同类型的对象。

2)const引用则可以绑定到不同但相关的类型的对象或绑定到右值。

8,枚举类型enum。

9,struct与class在创建类时的区别:struct的默认访问级别为public,而class的则为private。

10,说明了C++语言头文件的使用与编写,以及使用定义预处理器变量来避免头文件的重复包含。

第3章 标准库类型

1,命名空间的using声明

using std::string

2,标准库string类型

标准库string类型。string类型和字符串字面值不是同一种类型,注意几种string的构造函数。

用cin读取string类型时,读取并忽略开头所有的空白字符,直至再次遇到空白字符,读取终止。

getline可以读取输入流中的一行,但是不包括换行符。

在string对象比较时,小写字母都比大写字母要大,即大写字母排在前面。

string对象的下标是从0开始到s.size()-1为止。

3,标准库vector类型

C++程序员习惯于优先使用!=而不是<来编写循环判断条件。for(string::size_type i=0; i != s.size(); i++)

C++编译器遇到内联函数时,都是直接扩展相应的代码,而不是实际的函数调用,所以像size这样的小库函数在循环中调用它代价是很小的。

4,迭代器简介

每一种容器都定义了begin与end函数,begin返回容器的第一个元素,end函数返回vector的末端元素的下一个,通常称为超出末端迭代器,表明它指向了一个不存在的元素。如果vector为空,begin返回的迭代器与end返回的迭代器相同。end返回的迭代器实际上是一个“哨兵”。

注意区别:

vector<int>::const_iterator // an iterator that cannot write elements

const vector<int>::iterator // an iterator whose value cannot change

5,bitset类型

几种bitset的构造函数:

bitset<n> b;

bitset<n> b(u); // u是一个usigned long弄的数字,将换算成二进制数

bitset<n> b(s);  // b 是string对象s中含有位串的副本

bitset<n> b(s,pos,n); // b是s中从位置pos开始的n个位的副本

第4章 数组与指针

1,数组

没有所有元素都是引用的数组,数组中定义的类型可以是内置数据类型或类类型或任意的复合类型(引用除外)。

数组的维数只能用在编译阶段就能知道的常量值。const int arSize=num;   int ar[arSize];这样是不行的,因为num变量在运行阶段才会计算出。

如果没有给数组显式地初始化,则会像普通变量一样进行初始化:1)在函数体外定义,则初始化为0;2)在函数体内定义,则其元素无初始化;3)不管数组在哪,如果其元素为类类型,则自动调用该类的默认构造函数。如果该类没有默认的构造函数,则必须为数组的元素提供显式的初始化。

vector对象不能用同类型的数直接进行初始化。假设有如下数组:const int ar_size=5; ar[ar_size]={0,1,2,3,4}>

vector<int> ivec(ar);   // error

vector<int> ivec(ar,ar+ar_size);  // ok

2,指针的引入

不允许把int型的0赋给指针,但是可以把const修饰的0可以赋于指针

cosnt int c_ival=0;  int *p=c_ival;

C++提供了一种特殊类型的指针void*,void*只支持几种有限的操作:1)与另一个指针进行比较;2)向函数传递void*指针或从函数返回void*指针;给另一个void*指针赋值。不允许使用void*指针操纵它所指向的对象。

ptrdiff_t是标准库中定义的用于保存指向同一类型的指针之间减法的结果的类型。

const int* ptr;   // ptr可以指向他变量,但是在没有改变ptr之前,不能用ptr是改变它所指向的变量的值。

int* const ptr; // ptr不能指向其他变量,但是可以改变ptr所指向的变量的值。

注意:

typedef string *pstring;

const pstring cstr;

上面的cstr是一种const指针,指针指向字符串类型的变量。pstring const cstr是一样的。

3,C风格字符串

每一个程序在执行时都占用一块可用的内存空间,用于存放动态分配的对象,此内存空间称为程序的自由存储区或堆。

动态分配的数组不能像数组一样使用初始化列表,只能初始化为元素类型的默认值。int* ar=new int[10]();后面的空括号可以让数组元素都初始化为0。

用delete释放自由存储空间时,如果释放的是数组,则别忘了[]。delete [] ar;

注意string对象的成员函数c_str()可以返回字符串的首指针。但是应该加const。 const char* str=s.c_str();

int* ip[4]:一个指向int的指针数组。

int (*ip)[4]:一个指针4元素数组的指针。

第5章 表达式

1,区别i++与++i

后置操作符需要先保存原来的值,再将i+1,然后返回原来的值;而前置操作符,只需要在原来值上加1,然后返回。所以++i比i++效率更高,当然如果i为int类型时,编译器会对i++进行优化,但如果是其他类类型或指针时就不会了。

2,注意解除引用操作符与++操作符的优先级,在实际代码中为了简洁经常将*(i++)写为*i++。因为++的优先级高于解除引用操作符。

3,在使用条件操作符时,尽量避免写出深度嵌套的条件操作符。另外条件操作符的优先级非常低,在表示式中使用时要注意加括号,比如:cout<<(i<j?i:j);

4,关于sizeof运算符。sizeof的运算结果是编译时的常量,注意下面的代码的值:

代码如下:

int a[10];
int* p = a;
int n1 = sizeof(a) / sizeof(*a); // n1=10
int n2 = sizeof(p) / sizeof(*p); // n2=1

5,在复合表达式求值时,要特别注意运算符的优先级与结合性。特别地,!=与==的优先级小于<=,>=等关系运算符。

6,在使用new进行动态内存分配时,有以下几点值得注意:

1)动态创建的对象可以用括号进行初始化,比如:

代码如下:

int* p = new int();// 初始化为0
int* q = new int(1024);// 初始化为1024

2)可以delete删除0指针,而且delete删除的是分配到的内存区域,并没有删除指针变量p,p依然指向原来的地址,只是原来的内存已经不存在了。这时p称为悬垂指针,应该将p设为0.

3)避免对同一内存空间使用两次delete。、

第6章 语句

1,在使用块状语句时注意,在块状语句内定义的变量作用域只在块状区域内。特别地,在控制语句,比如if或for语句中,初始化或定义的变量,都只有块区域的作用域。

2,switch语句的使用。case标号必须是整形常量表达式,不允许在switch语句内定义变量如果在它下面还有case或default语句,因为这样会在某些情况下,在没有执行变量定义的case分支的情况下,执行变量定义下面case分支。除非把变量定义在代码块内。

3,在for循环中,如果有continue语句,会跳下continue后面的语句,但是不会跳变for语句中的计数器变化语句。

4,可以使用预处理器进行调试。

代码如下:

#ifndef NDEBUG
    cout << "some useful information!";
#endif // !NDEBUG

在编译时加上参数就可以决定是否打印那些调试信息。

第7章 函数

1,函数可以看作是程序员自己定义的操作符,与操作符一样函数也可以进行重载。

2,下面是用辗转相除法求最大公约数的函数,说明了函数定义的基本结构。

代码如下:

int gcd(int v1, int v2)
{
    // 辗转相除法求最大公约数
    while (v2)
    {
        int temp = v2;
        v2 = v1%v2;
        v1 = temp;
    }
    return v1;
}

5,没有返回值的函数(返回值为void)里一般是不能有return语句,但是可以用return返回一个返回值为void的函数表达式。

代码如下:

void fun1()
{
    void fun2();
    return fun2();
}

6,函数允许提供默认的实参,在调用时,这一项参数可以省略,而让程序使用默认值。一般应在函数声明中指定默认实参,并将该声明放在合适的头文件中。

7,在函数体内定义的变量具有块区域的作用域,可分为两种一种为自动对象,如:形参。这类对象在每次函数调用时都会创建,在函数执行完时销毁。还有一种对象为静态局部对象,这种对象只有在程序结束时才会撤销。不然一直在内存中保留。

8,对于那种经常需要调用且短小的函数,可以设置为内联函数,这种函数在编译时,编译器会在函数调用处对函数进行展开,进行代码替换。这样就避免了函数调用中的开销。定义内联函数是在函数定义前加inline。一般需要将inline函数放在头文件中。

9,在类的成员函数中有一类函数在后面加上const限定符,用来说明为常量成员函数,在对象使用时,只能读取不能改变对象的数据成员。

10,不要把this指针写在了成员函数的形参表中。

11,在定义类时,如果没有定义默认的构造函数,那么编译器将为类创建一个合成的默认构造函数。这个函数将类的成员变量按对应变量类型初始化方法进行初始化:类类型的将调用该类的默认构造函数,内置类型则依赖于所处的环境是全局或静态局部对象还是局部对象。合成的默认构造函数只适用仅包含类类型成员的类。

12,函数不能仅仅基于不同的返回类型而实现重载。

13,const在函数重载中值得注意的问题:

代码如下:

void fun(int num);
void fun(const int num);  // 重复声明

void fun(int& num);
void fun(const int& num); // 可以重载

void fun(int* num);
void fun(const int* num); // 可以重载

14,局部声明的函数将会屏蔽将全局定义的重载函数。

代码如下:

void fun(int x, int y = 1);
int main()
{
    void fun(double x);
    fun(2,4);  //error
    return EXIT_SUCCESS;
}

15,指向函数的指针

函数指针指向函数而并非指向对象。bool (*pf) (int,int*); 其中pf是一个函数指针,该指针的类型为“指向返回bool类型并带int与int*形参的函数的指针”。

1)可以用typedef来给指定函数的指针简单定义:

代码如下:

typedef bool(*cmpFcn) (int,int*);
cmpFcn f1, f2;

上面代码中定义了一种指针函数的类型,并用typedef提供了别名。f1与f2都是这种类型的指针。

2)给指向函数的指针初始化与赋值

对于定义好的函数,其函数名没有被调用时,都被解释为指向函数的指针,可以给同类型的指针赋值。

给指向函数的指针赋值为0,表明不指向任何函数。

在进行指向函数的指针赋值时,不存在任何类型的转换。

3)通过指针调用函数

可以不用解除引用符号,如:f1(1,2)、(*f1)(1,2)。

4)指向函数的指针可以作为函数的形参:

代码如下:

void iVectSort(vector<int>::iterator , vector<int>::iterator ,bool(*)(int,int));
void iVectSort(vector<int>::iterator, vector<int>::iterator, bool (int, int));

上面两个函数的声明中上式第3个参数为一个指向函数指针类型,下式的第3个参数为一个函数类型,它会自动转换为一个指针类型。

5)函数类型可以作为函数的形参,但是不能作为函数的返回类型。

6)在指向函数的指针指向重载函数时,类型必须一致。

第8章 标准IO库

1,标准库类型不允许做复制和赋值操作。因为只有支持复制的元素类型可以存储在vector中,所以流对象不能存储在vector或容器中,另外函数的形参与返回类型也不能为流类型,如果需要则必须传递或返回指向该对象的引用或指针。一般来说,如果要传递IO对象以便对它进行读 写,可以用非const引用方式传递这个流对象。对IO对象的读写会改变它的状态,所以必须是非const的。

2,每个IO对象都管理着一个缓冲区,有以下几种方式可以刷新缓冲区(将缓冲区内容写到设备上)。

1)输出缓冲区的刷新:flush刷新流但不添加任何字符;ends这个操作符在缓冲区中插入空字符NULL,然后刷新它。endl换行并刷新。

2)unitbuf操作符:cout<<unitbuf<<”first”<<”second”<<nounitbuf;nounitbuf操作符将流恢复为正常的,由系统管理的缓冲区刷新方式。

3)程序崩溃时,不会刷新缓冲区。这一点在调试已崩溃的程序时需要特别注意。

4)可以用tie函数将istream与ostream捆绑在一起,当使用任何IO操作时都会刷会实参所关联的缓冲区。

3,注意清除文件流的状态,下面程序从一个vector中读文件的名字,并对每个文件内的内容进行处理,如果开始的流是定义在循环外的,则需要在循环结束时清除文件流的状态。

代码如下:

ifstream input;  // inPut是在循环外定义
vector < string::const_iterator it = files.begin();
while (it != files.end())
{
    input.open(it->c_str());
    if (!input)
        break;
    while (input >> s)
        process(s);
    input.close();
    input.clear();   // 清除文件流的状态
    ++it;
}

上面程序中,每一次读文件,都会以遇到文件结束符或其他错误终止,这个点上input处于错误状态。如果关闭该流前没有调用clear消除流的状态,接着在input上做的任何输入运算都会失败。

4,stringstream由iostream派生而来,提供读写string的功能。可以将一个字符串转化为流用于输入或输出。这个类主要有两种常见的用处:

1)将一定格式的变量值组成一个字符串。 假设在一个循环内,我们要保存中间数据到硬盘,那么需要文件名,且需要将循环的索引写入文件名,避免文件名的重复。

代码如下:

ostringstream filename;
string prefix = "file_";
string suffix = ".jpg";
for (int i = 0; i < 100; i++)
{
    filename << prefix << i << suffix;
}

2)将一串有格式的字符串,按格式解析为一些基本类型数据。比如,需要将一行日志文件内容中的字符串与整数分别提取出来:

代码如下:

string logContent = "20140225  C++Primer  42";
istringstream input(logContent.c_str());
string dump;
int price;
input >> dump >> dump >> price;

(0)

相关推荐

  • 《C++ primer plus》读书笔记(一)

    第一章 1.预处理器--#include<iostream>将iostream文件内容添加到程序中.老式C头文件保留了扩展名.h,而C++头文件没有扩展名. (有些C头文件被转换为C++头文件,去掉扩展名,并在前面加c,如cmath) 2.名称空间--相当于Java中的package,using编译指令相当于Java中的import.头文件没有.h前缀时,类.函数和变量是C++编译器的标准组件,被放置在名称空间std中. 3.类的本质--类是用户定义的一种数据类型.类定义描述的是数据格式及其用

  • 《C++ primer plus》读书笔记(二)

    第五章 1.for循环--for(initialization; test-expression; update-expression) body // test-expression 会被转换为bool,0为false,非零为true 2.表达式--表达式是值或值与运算符的组合.赋值表达式的值为其左侧成员的值,而赋值运算符是从右到左结合的. 3.a++和++a-- (1)对于内置类型,两种执行效率相同. (2)若重载运算符,对于类而言,前缀将值加1,返回结果:后缀会复制一个副本,加1后返回副本

  • C++Primer笔记之顺序容器的使用详解

    顺序容器,它将单一类型元素聚集起来成为容器,然后根据位置来存储和访问这些元素,这就是顺序容器.标准库里定义了三种类型:vector(支持快速随机访问).list(支持快速插入.删除).deque(双端队列)容器只定义了少量操作,大多数额外的操作由算法库提供.容器内元素的类型约束:1.元素类型必须支持赋值运算:2.元素类型的对象必须可以复制.这是容器元素类型的最低要求,如果想支持一些其他特殊要求,则必须具备相关的性质. 可以定义容器的容器vector< vector<int> > l

  • 《C++ primer plus》读书笔记(三)

     第九章 1.C++程序的组成-- (1).头文件: 包含结构声明和使用这些结构的原型. (2).源代码文件: 包含与结构有关的函数的代码. (3).源代码文件: 包含调用与结构有关的函数的代码. 2.头文件-- (1).常包含的内容: 函数原型:#define或const定义的符号常量:结构声明:类声明:模板声明:内联函数. (2).若文件名包含在尖括号中,编译器将在存储标准头文件的主机系统的文件系统中查找. (3).若文件名包含在双引号中,编译器首先查找当前的工作目录或源代码目录,再在标准位

  • C++Primer笔记之关联容器的使用详解

    关联容器 关联容器支持通过键来高效地查找和读取元素.两个基本的关联容器类型是map和set.map的元素以键-值对的形式组织:键用作元素在map的索引,而值则表示所存储和读取的数据.set仅包含一个键,并有效地支持关于某个键是否存在的查询.set和map类型的对象不允许为同一个键添加第二个元素.如果一个键必须对应多个实例,则需使用multimap或mutiset类型,这两种类型允许多个元素拥有相同的键. pair类型:在头文件utility中定义. pair的创建和使用: 复制代码 代码如下:

  • C++ Primer 第一部分基本语言

    第1章 快速入门 1,介绍main函数的意义和其基本结构,return语句.不同平台下编译与执行程序.2,两个类isrteam与otream与它们的实例对象cin,cout,cerr,clog.说明了程序中基本的输入与输出."<<"与">>"作为操作符,左操作符是一个iostream 对象,右操作符是一个变量.返回值仍为一个iostream对象,所以输入或输出可以这样 cout<<"a="<<a&l

  • Go语言并发技术详解

    有人把Go比作21世纪的C语言,第一是因为Go语言设计简单,第二,21世纪最重要的就是并行程序设计,而Go从语言层面就支持了并行. goroutine goroutine是Go并行设计的核心.goroutine说到底其实就是线程,但是它比线程更小,十几个goroutine可能体现在底层就是五六个线程,Go语言内部帮你实现了这些goroutine之间的内存共享.执行goroutine只需极少的栈内存(大概是4~5KB),当然会根据相应的数据伸缩.也正因为如此,可同时运行成千上万个并发任务.goro

  • 详解易语言使用方法步骤

    易语言作为一门全中文可视化的编程语言,已经受到越来越多人的重视.而它简单的操作,也使编程变得简单.这篇经验将告诉你如何用易语言做你的第一个程序. 安装完成后,双击易语言图标打开易语言.这里弹出了一个对话框. 双击中间的"windows窗口程序"新建一个程序.界面如图所示. 菜单栏:程序的各种操作及设置. 窗口编辑区:绘制界面 属性设置区:设置组件.窗口的各种属性 组件框:选择各种组件 提示区:显示当前程序的运行.编译情况.显示对于某一命令的帮助提示. 在右侧组件框找到"标签&

  • Javascript 面向对象特性

    1. JavaScript中的类型 -------- 虽然JavaScript是一个基于对象的语言,但对象(Object)在JavaScript中不是第一型的.JS 是以函数(Function)为第一型的语言.这样说,不但是因为JS中的函数具有高级语言中的函 数的各种特性,而且也因为在JS中,Object也是由函数来实现的.--关于这一点,可以在 后文中"构造与析构"部分看到更进一步的说明. JS中是弱类型的,他的内置类型简单而且清晰: ------------------------

  • AJAX 简介及入门实例

    对于一个像我一样刚刚接触Web开发且无多少实际项目经验的新手而言,AJAX技术显得复杂而又深奥.经过两天的baidu.google,我对AJAX的基本原理有了一个大致的认识,在此总结一下. 1. 什么是AJAX? AJAX全称是异步的JavaScript和XML,是Asynchronous JavaScript and XML的缩写.AJAX技术用于创建交互式网页应用的网站开发,至于何为异步,后文会有解释. 1.1 桌面应用程序和Web应用程序 在详细讨论AJAX技术之前,需要先知道AJAX技术

  • 24种编程语言的Hello World程序

    Hello,World,几乎是程序猿学习各种语言的第一个程序,心血来潮,有空拿主流开发语言如何实现,汇总并整理了下.包括大致快速了解下这门语言,开发,编译,环境搭建,运行,简单语言等.其实很多语言是由关联的,在当下,只掌握一门语言是不够的,比如说Python,语言简洁,开发快是其最大优点.但缺点是速度相对较慢,但C/C++/Java开发比较慢,程序运行速度比较快,如果想兼具两者的优点,就要写Python的扩展,这就涉及到(C,C++,Java,Fortan...)等语言,Python的GUI中T

  • 从汇编看c++中变量类型的深入分析

    全局变量的生命期和可见性是整个程序的运行期间,下面就来用汇编来看一下实际情况: c++源码: 复制代码 代码如下: int i = 2;//全局变量 int main() {    int j = i;} 下面是汇编代码: 复制代码 代码如下: PUBLIC    ?i@@3HA                        ; i_DATA    SEGMENT?i@@3HA    DD    02H                    ; 全局变量i内存空间_DATA    ENDSPUB

  • Linux系列教程之虚拟机中安装Centos7.0

    本次教程的前提条件是您得安装好VM软件和Xshell.对应软件的下载请自行百度!如果exe都不会安装,请关闭本页面! 第一步.下载镜像 阿里云开源镜像站:http://mirrors.aliyun.com/ 选择centos进入 如下图: 再选择isos(镜像目录) 继续下一步,只有一个目录,进入即可 进去以后如图: 对于初学者来说,这么多的镜像着实不好分辨. 其中,Centos-7-x86_64 表示这个是镜像叫centos,版本号为7,支持64位(附上百科链接:http://dwz.cn/3

  • 经典的PHPer为什么被认为是草根?

    PHPer是草根吗? 从PHP诞生之日起,PHP就开始在Web应用方面为广大的程序员服务.同时,作为针对Web开发量身定制的脚本语言,PHP一直秉承简单.开源的思想,这也使得PHP得以快速的发展,并且大力地推动Web2.0的出现与发展.但是,长期以来,PHPer(PHP Programmers)被认为是处于草根阶层的程序员,被认为是技术含量少,层次低的程序员.这点在国内尤其突出. 记得一个技术主管说过这样一个事情.他给一个程序员分配了PHP的开发任务,没想到那个程序员居然说:"我是学Java出身

  • Java14发布了,再也不怕NullPointerException了

    2020年3月17日发布,Java正式发布了JDK 14 ,目前已经可以开放下载.在JDK 14中,共有16个新特性,本文主要来介绍其中的一个特性:JEP 358: Helpful NullPointerExceptions null何错之有? 对于Java程序员来说,null是令人头痛的东西.时常会受到空指针异常(NullPointerException)的骚扰.相信很多程序员都特别害怕出现程序中出现NPE,因为这种异常往往伴随着代码的非预期运行. 在编程语言中,空引用(Null Refere

随机推荐