C++Primer前十二章的一些笔记和总结

whilecin >> x)中会一直循环检测cin是否输入,始终无法跳出,如果while函数外有cout函数则按ctrl+C会输出cout中想要输出的前两个字符。

 

有时候没有编译成功看看是否有导入头文件

 

VS2015中指针不赋初值无法输出到屏幕

 

未赋值的string int类型变量在VS2015中无法编译通过,如果在定义变量之后再定义一个引用则编译可以通过。int类型在main()外定义得到结果为0,在main()中定义则显示结果是-858993460

 

C语言中经常使用NULL当做空指针,在C++中常使用nullptr来当做预处理变量,尽量避免使用NULL

 

关于void*指针,拿来和别的指针比较、作为函数的输入或输出,或者赋给另外一个void*指针。不能直接操作void*指针所指的对象,因为我们并不知道这个对象到底是什么类型,也就无法确定能在这个对象上做哪些操作(VS2015中可以声明定义,但是只能输出地址,无法输出地址中的值)

 

引用使用std::cout的时候直接输入变量值即可不用再前面加&

 

数据类型 *&变量名即生成了一个关于指针的引用

 

Const 类型 & a =  b,可以通过改变b来改变a,反之则不行。如果a b的类型不同则也不可以通过改变b来改变a。(类型不同涉及到临时量的问题)

一般引用无法直接赋值,在前面加上const基本数据类型就可以为常量引用绑定字面值。

 

constexpr把它所定义的对象置为了顶层const

 

一个constexpr指针的初始值必须是nullptr或者0,或者是存储于某个固定地址中的对象

 

函数体内定义的变量一般来说并非存放在固定地址中,因此constexpr指针不能指向这样的变量

 

std::cin>>int i;在输入中这样定义是无法编译成功的

 

直接用unsigned对变量赋值,变量的类型是无符号的整型数值

 

头文件一旦改变,相关的源文件必须重新编译以获取更新过的声明

 

定义指针之后赋值整数给它的地址无法通过编译

 

Auto一般会忽略掉顶层const

 

设置一个类型为auto的引用时,初始值中的顶层常量属性仍然保留

 

Auto * 变量名= 引用和auto 变量名 = 引用出来的效果类似

 

假使const inti  = 某整数,如auto a = i,a为整型,如果想利用auto生成整型常量的话只需要在auto之前加上const即可;而如果用auto &a = i,a为整型常量引用

 

auto一次性定义多个变量,必须使每个变量的类型都是同一种数据类型,否则编译无法通过

 

对于decltype类型指示符来说,如果表达式的内容是解引用操作,则decltype将得到引用类型

 

使用decltype初始化指针即decltype(x)y=&z;

 

decltype((variable))(注意是双层括号)的结果永远是引用,而decltype(variable)结果只有当variable本身就是一个引用时才是引用   

 

for循环中的第一个表达式中不能同时声明两个不同类型的变量

 

是否为为空字符串可利用字符串是否等于"\0"来判断

 

<标识>在理论上说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:stdio.h=_STDIO_H_

                     

getline只要一遇到换行符就结束读取操作并返回结果,哪怕输入的一开始就是换行符也是如此

getline函数的对象需要是string类型的

 

当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符(+)的两侧的运算对象至少有一个是string

 

字符串字面值与string是不同的类型

 

字符中的空格用' '表示即可

 

使用break可以从当前的forwhile循环中跳出

 

对逻辑运算符(&&)来说,C++语言规定只有当左侧对象为真时才会检查右侧运算对象的情况

 

如果循环体内部包含有向vector对象添加元素的语句,则不能使用范围for循环

 

范围for语句体内不应改变其所遍历序列的大小

 

vector对象(以及string对象)的下标运算符可用于访问已存在的元素,而不能用于添加元素

 

vector容器输出可以利用范围for循环和数组的方式输出

 

迭代器中因为end返回的迭代器并不实际指示某个元素,所以不能对其进行递增或解引用的操作

 

右侧的迭代器向前移动多少位置就能追上左侧的迭代器,其类型是名为difference_type的带符号整型数,因为这个距离可正可负

 

但凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素

 

如果利用字符串形式给字符数组赋值需要空出一个空间存放空字符

 

对数组声明定义的理解,由内向外阅读要比从右向左好多了

 

在使用数组下标的时候,通常将其定义为size_t类型

 

cstddef头文件中定义了size_t类型(无符号),这个文件是C标准看见stddef.h头文件的C++语言版本

 

关于autodecltype,例:inti[]={0,1,2,3,4,5};auto a(i);decltype(i) b={1,2,3,4,5,6};auto导出的类型是整型指针,decltype导出的是整型数组。

 

指向数组位置的begin函数和end函数定义在iterator头文件中

 

两个指针相减的结果的类型是一种名为ptrdiff_t的标准库类型(带符号),和size_t一样,ptrdiff_t也是一种定义在cstddef头文件中的机器相关的类型

 

尾后指针不能执行解引用和递增操作

 

char a[]=[Hello]charb="Hello"的尾指针的元素值是不同的char b="Hello"是以空字符结束的

 

VS2015中应用strcat_s函数时需要知道其中一个具体的长度否则会报错,例:strcat_s(a,sizeof(a),b)

 

编程时如果直接声明数组未定义不能直接使用strcat_s函数

 

关于混用string对象和C风格字符串,允许以空字符结束的字符数组来初始化string对象或者为其赋值,反过来则不行。如果要使用string类型的值当右值的话需要使用.c_str()的成员函数

 

使用指针的迭代器begina)、enda)的时候需要声明在std空间内

 

严格来说C++语言中没有多维数组,通常说的多维数组其实是数组的数组

 

typedef取别名的范围只包括(intchar这些类型)而如果我们想为int[4]这样的类型取别名的话就只能使用using 例:typedef intwoshinidie;   using woshinibaba=int[4];

 

参与取余运算的对象必须是整数类型

 

因为执行sizeof运算能得到整个数组的大小,所以可以用数组的大小除以单个元素的大小得到数组中元素的个数

 

非零整数转换成布尔值都是true

 

求余:分母负即正,分母负必负

 

if(i<j<k)k>1该式必成立

 

If(a==true) 如果a不是布尔值,那么进行比较之前会首先把true转换成a的类型

 

case中不能初始化,初始化是非法行为。

 

Switch case中不能判定字符串

 

Case后面不能跟变量,不能加逗号

 

在范围for语句中,预存了end()的值。一旦在序列中添加(删除)元素,end函数的值就可能变得无效了

 

局部静态对象在程序的执行路径第一次经过对象定义语句时初始化,并且直到程序终止才被销毁,在此期间即使对象所在的函数结束执行也不会对它有什么影响

 

如果函数无须改变引用形参的值,最好将其声明为常量引用

 

C++中,建议使用引用类型的形参替代指针

 

如果函数无须改变引用形参的值,最好将其声明为常量引用

 

Initializer_list列表中的元素全部都是const

 

一个返回类型是void的函数也能使用return语句的第二种形式(returnexpression;),不过此时return语句中的expression必须是另一个返回void的函数。强行令void函数返回其他类型的表达式将产生编译错误

 

在含有return语句的循环后面应该也有一条return语句,如果没有的话该程序就是错误的。很多编译器都无法发现此类错误

 

不要返回局部对象的引用或指针

 

cstdlib头文件定义了两个预处理变量(EXIT_FAILUREEXIT_SUCCESS

 

因为数组不能被拷贝,所以函数不能返回数组

 

数组指针:Type*functionparameter_list))[dimension]

 

尾置返回类型:autofunc(int i)->int(*)[10]   //func接收一个int类型的实参,返回一个指针,该指针指向含有10个整数的数组

 

main函数不能重载

 

不允许两个函数除了返回类型外其他所有的要素都相同,假设有两个函数,它们的形参列表一样但是返回类型不同,则第二个函数的声明是错误的

 

重载函数无法区分是否顶层const但是可以区分底层const

 

当我们传递一个非常量对象或者指向非常量的对象的指针时,编译器会优先选用非常量版本的函数

 

C++语言中,名字查找发生在类型检查之前

 

一旦某个形参被赋予了默认值,它后面的所有形参都必须有默认值

 

关于形参赋予默认值,函数后续声明即在此声明只能为之前那些没有默认值的形参添加默认实参,而且该形参右侧的所有形参必须都有默认值

 

局部变量隐藏外层变量不能传递给函数的默认实参

 

内联说明只是向编译器发出的一个请求,编译器可以选择忽略这个请求

 

constexpr函数的返回类型及所有形参的类型都得是字面值类型,而且函数体中必须有且只有一条return语句

 

constexpr函数不一定返回常量表达式

 

在指向不同函数类型的指针间不存在转换规则

 

函数指针的返回类型需要跟函数的类型以及形参的类型一致才能进行赋值

 

decltype作用于某个函数时,它返回函数类型而非指针类型

 

类定义最后需要加上分号

 

定义在类内部的函数是隐式的inline函数

 

尽管所有成员都必须在类的内部声明,但是成员函数体可以定义在类内也可以定义在类外

 

this是一个常量指针

 

->类似于用在加入p是一个指针指向对象a,而a中存在变量b,则可以利用p->b来调用b,类似于(*p).b

 

默认情况下,this的类型是指向类类型非常量版本的常量指针

 

编译器分两步处理类:首先编译成员的声明,然后才轮到成员函数体(如果有的话)。

 

一般来说非成员函数时接口的组成部分,则这些函数的声明应该与类在同一个头文件内

 

IO类属于不能被拷贝的类型,所以我们只能通过引用来传递他们

 

执行输出任务的函数应该尽量减少对格式的控制

 

构造函数不能被声明成const的,当我们创建类的一个const对象时,直到构造函数完成初始化过程,对象才能真正取得其“常量”属性。因此,构造函数再const对象的构造过程中可以向其写值

 

如果类包含有内置类型或者复合类型的成员,则只有当这些成员全都被赋予了类内的初始值时,这个类才适合于使用合成的默认构造函数

 

当我们创建类的一个const对象时,直到构造函数完成初始化过程,对象才能真正取得其“常量”属性

 

如果=default在类的内部,则默认是内联的;如果它在类的外部,则该成员默认情况下不是内联的

 

构造函数不应该轻易覆盖掉类内的初始值,除非新赋的值与原值不同。如果你不能使用类内初始值,则所有构造函数都应该显示地初始化每个内置类型的成员

 

如果我们使用struct关键字,则定义在第一个访问说明符之前的成员是public的;相反,如果我们使用class关键字,则这些成员是private

 

使用classstruct定义类唯一的区别就是默认的访问权限

 

在类中,用来定义类型的成员必须先定义后使用,因此,类型成员通常出现在类开始的地方

 

类内初始值必须使用=的初始化形式或者花括号括起来的直接初始化形式

 

我们希望能修改类的某个数据成员,即使是在一个const成员函数内。可以通过在变量的声明中加入mutable关键字做到这一点P245

 

非常量版本的函数对于常量对象是不可用的

 

友元声明的作用使影响访问权限,它本身并非普通意义上的声明

 

在类中,如果成员使用了外层作用域中的某个名字,而该名字代表一种类型,则类不能再之后重新定义该名字,即使重新定义是一样的也是错误的

 

explicit关键字只允许出现在类内的构造函数声明出

 

不能将explicit构造函数用于拷贝形式的初始化过程(Sale_data A = null_book),即使用直接初始化(Sale_data Anull_book))

 

静态成员函数不能声明成const的,而且我们也不能在static函数体内使用this指针

 

当在类的外部定义静态成员时,不能重复static关键字,该关键字只出现在类内部的声明语句

 

静态数据成员定义在任何函数之外,一旦它被定义,就一直存在于程序的整个生命周期中

 

即使一个常量静态数据成员在类内部被初始化了,通常情况下也应该在类的外部定义一下该成员

 

不能通过类名来调用类的非静态成员函数

 

静态成员函数中不能引用非静态成员(因为静态成员函数属于整个类,在类实例化对象之前就已经分配空间了,而类的非静态成员必须在类实例化对象后才有内存空间)

 

类的静态成员变量必须先初始化再使用

 

std::flush刷新缓冲区;std::ends先输出一个空字符,然后刷新缓冲区

 

unitbuf操作符使接下来的每次写操作之后都进行一次flush操作(cout<<std::unitbuf),nounitbuf则是回到正常的缓冲方式

 

如果程序崩溃,输出缓冲区不会被刷新

 

保留被ofstream打开的文件中已有数据的唯一方法是显式指定appin模式

 

forward_list迭代器不支持递减运算符

 

assign操作不适用于关联容器

 

赋值相关运算会导致指向左边容器内部的迭代器、引用和指针失效。而swap操作将容器内容交换不会导致指向容器的迭代器、引用和指针失效(容器类型为arraystring的情况除外)

 

对一个string调用swap会导致迭代器、引用和指针失效

 

swap两个array会真正交换它们的元素。因此,交换两个array所需的时间与array中元素的数目成正比

 

向一个vectorstringdeque插入元素会使所有指向容器的迭代器、引用和指针失效

 

vector不支持push_front

 

at和下标操作只适用于stringvectordequearrayback不适用于forward_list

 

不能递减forward_list迭代器

 

对一个空容器调用frontback,就像使用一个越界的下标一样,是一种严重的程序设计错误

 

forward_list不支持pop_back;vectorstring不支持pop_front

 

删除deque中除首尾位置之外的任何元素都会使所有迭代器、引用和指针失效。指向vectorstring中删除点之后位置的迭代器、引用和指针都会失效

 

删除元素的成员函数并不检查其参数。在删除元素之前,程序员必须确保它是存在的

 

string搜索函数返回string::size_type值,该类型是一个unsigned类型。因此,用一个int或其他带符号类型来保存这些函数的返回值不是一个好主意

 

每一个适配器都定义两个构造函数

 

默认情况下,stackqueue是基于deque实现的,priority_uqeue是在vector之上实现的

 

所有适配器都要求容器具有添加和删除元素的能力

 

算法用于不会改变底层容器大小

 

谓词是一个可调用的表达式,其返回结果是一个能用作条件的值

 

 

分别用sortstable_sort排序x,你会发现sort之后,相等的x的顺序和原始顺序可能发生变化,而stable_sort保证相同的一定是原始顺序

 

使用类形参的时候申明成const

 

如果要对类使用==或者<>得使用operator对类函数进行重载(例:bool operator==(Person const &p1,Person const &p2)

 

一个almbda只有在其捕获列表中捕获一个它所在函数中的局部变量,才能在函数体中使用该变量

 

捕获列表只用于局部非static变量,lambda可以直接使用局部static变量和在它所在函数之外声明的名字

 

lambda中采用值捕获的前提是变量可以拷贝

 

被捕获的变量的值是在lambda创建时拷贝,而不是调用时拷贝

 

由于被捕获变量的值是在lambda创建时拷贝,因此随后对其修改不会影响到lambda内对应的值

 

当以引用方式捕获一个变量时,必须保证在lambda执行时变量时存在的

 

如果可能的话,应该避免捕获指针或引用

 

&告诉编译器采用捕获引用方式,=则表示采用值捕获方式

 

当我们混合使用隐式捕获和显式捕获时,捕获列表中的第一个元素必须是一个&=

 

当混合使用隐式捕获和显式捕获时,显式捕获的变量必须使用与隐式捕获不同的方式。

 

如果我们希望能改变一个被捕获的变量的值,就必须在参数列表首加上关键字mutable

 

名字_n都定义在一个placeholders的命名空间中(例:using namespace std::placeholders

 

使用bind遇到引用或者const类型的可以使用refcref函数(P357

 

使用bind的形参都是使用的拷贝,若遇到引用则需要用到函数ref,函数ref返回一个对象,包含给定的引用,此对象是可以拷贝的,还有一个cref函数,生成一个保存const引用的类。

 

unique函数支持剔除相邻之间字符重复的

 

 

除了forward_list之外的标准库容器都有反向迭代器

 

对于一个绑定到流的迭代器,一旦其关联的流遇到文件尾或遇到IO错误,迭代器的值就与尾后迭代器相等

 

accumulate函数中序列的迭代器类型需要是const类型的

 

流迭代器不支持递减运算

 

将反向迭代器转换成正向迭代器使用reverse_iterator中的base成员函数

 

一个高层类别的迭代器支持底层类别迭代器的所有操作

 

对于向一个算法传递错误类别的迭代器的问题,很多编译器不会给出任何警告或提示

 

向输入迭代器写入数据的算法都假定目标空间足够容纳写入的数据

 

关联容器不支持顺序容器的位置先关的操作,关联容器也不支持构造函数或插入操作这些接受一个元素值和一个数量值的操作

 

关联容器的迭代器都是双向的

 

pair的构造函数对数据成员进行值初始化

 

当解引用一个关联容器迭代器时,我们会得到一个类型为容器的value_type的值的引用

 

一个mapvalue_type是一个pair,我们可以改变pair的值,但不能改变关键字成员的值

 

通常不对关联容器使用泛型算法

 

当对一个map进行下标操作时,会获得一个mapped_type对象;但当解引用一个map迭代器时,会得到一个value_type对象

 

对动态分配的对象进行值初始化,只需在类型名之后跟一对空括号

 

如果我们提供了一个括号包围的初始化器,就可以使用auto,只有当括号中仅有单一初始化器时才可以使用auto

 

默认情况下,如果new不能分配所要求的内存空间,它会抛出一个类型为bad_alloc的异常,如果要阻止异常的发生->int *p2 = new( nothrow ) int ; //如果分配失败,new返回一个空指针)

 

空悬指针:指向一块曾经保存数据对象但现在已经无效的内存的指针

 

使用一个内置指针来访问一个智能指针所负责的对象是很危险的,因为我们无法知道对象何时会被销毁

 

永远不要用get初始化另一个智能指针或者为另一个智能指针赋值(P414

 

当我们定义一个unique_ptr时,需要将其绑定到一个new返回的指针上,初始化unique_ptr必须采用直接初始化形式

 

unique_ptr不支持普通的拷贝或赋值操作

 

auto_ptr具有unique_ptr的部分特性,我们不能再容器中保存auto_ptr,也不能从函数中返回auto_ptr

 

动态数组并不是数组类型

 

关于动态数组,如果我们在delete一个数组指针时忘记了方括号,或者在delete一个单一对象的指针时使用了方括号,编译器很可能不会给出警告。我们的程序可能在执行过程中再没有任何警告的情况下行为异常。

 

vector接收单一大小参数的构造函数是explicit

 

拷贝构造函数的第一个参数必须是一个引用类型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值