热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

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

这篇文章主要介绍了C++Primer第一部分基本语言的相关资料,需要的朋友可以参考下

第1章 快速入门

1,介绍main函数的意义和其基本结构,return语句。不同平台下编译与执行程序。
2,两个类isrteam与otream与它们的实例对象cin,cout,cerr,clog。说明了程序中基本的输入与输出。“<<”与”>>”作为操作符,左操作符是一个iostream 对象,右操作符是一个变量。返回值仍为一个iostream对象,所以输入或输出可以这样 cout<<”a=”<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::const_iterator // an iterator that cannot write elements

const vector::iterator // an iterator whose value cannot change

5,bitset类型

几种bitset的构造函数:

bitset b;

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

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

bitset 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 ivec(ar);   // error

vector 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

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::iterator , vector::iterator ,bool(*)(int,int));
void iVectSort(vector::iterator, vector::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<

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

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

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

代码如下:

ifstream input;  // inPut是在循环外定义
vector 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 <}

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

代码如下:

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


推荐阅读
  • 本文介绍了在Mac上安装Xamarin并使用Windows上的VS开发iOS app的方法,包括所需的安装环境和软件,以及使用Xamarin.iOS进行开发的步骤。通过这种方法,即使没有Mac或者安装苹果系统,程序员们也能轻松开发iOS app。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 2022年的风口:你看不起的行业,真的很挣钱!
    本文介绍了2022年的风口,探讨了一份稳定的副业收入对于普通人增加收入的重要性,以及如何抓住风口来实现赚钱的目标。文章指出,拼命工作并不一定能让人有钱,而是需要顺应时代的方向。 ... [详细]
  • 处理docker容器时间和宿主机时间不一致问题的方法
    本文介绍了处理docker容器时间和宿主机时间不一致问题的方法,包括复制主机的localtime到容器、处理报错情况以及重启容器的步骤。通过这些方法,可以解决docker容器时间和宿主机时间不一致的问题。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • 本文介绍了Java的集合及其实现类,包括数据结构、抽象类和具体实现类的关系,详细介绍了List接口及其实现类ArrayList的基本操作和特点。文章通过提供相关参考文档和链接,帮助读者更好地理解和使用Java的集合类。 ... [详细]
  • 标题: ... [详细]
  • 从高级程序员到CTO的4次能力跃迁!如何选择适合的技术负责人?
    本文讲解了从高级程序员到CTO的4次能力跃迁,以及如何选择适合的技术负责人。在初创期、发展期、成熟期的每个阶段,创业公司需要不同级别的技术负责人来实现复杂功能、解决技术难题、提高交付效率和质量。高级程序员的职责是实现复杂功能、编写核心代码、处理线上bug、解决技术难题。而技术经理则需要提高交付效率和质量。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
  • GPT-3发布,动动手指就能自动生成代码的神器来了!
    近日,OpenAI发布了最新的NLP模型GPT-3,该模型在GitHub趋势榜上名列前茅。GPT-3使用的数据集容量达到45TB,参数个数高达1750亿,训练好的模型需要700G的硬盘空间来存储。一位开发者根据GPT-3模型上线了一个名为debuid的网站,用户只需用英语描述需求,前端代码就能自动生成。这个神奇的功能让许多程序员感到惊讶。去年,OpenAI在与世界冠军OG战队的表演赛中展示了他们的强化学习模型,在限定条件下以2:0完胜人类冠军。 ... [详细]
  • svnWebUI:一款现代化的svn服务端管理软件
    svnWebUI是一款图形化管理服务端Subversion的配置工具,适用于非程序员使用。它解决了svn用户和权限配置繁琐且不便的问题,提供了现代化的web界面,让svn服务端管理变得轻松。演示地址:http://svn.nginxwebui.cn:6060。 ... [详细]
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • Java和JavaScript是什么关系?java跟javaScript都是编程语言,只是java跟javaScript没有什么太大关系,一个是脚本语言(前端语言),一个是面向对象 ... [详细]
  • 本文讨论了读书的目的以及学习算法的重要性,并介绍了两个算法:除法速算和约瑟夫环的数学算法。同时,通过具体的例子和推理,解释了为什么x=x+k序列中的第一个人的位置为k,以及序列2和序列3的关系。通过学习算法,可以提高思维能力和解决问题的能力。 ... [详细]
author-avatar
握住每一缕光
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有