C++ Primer 知识点学习(一)

第一部分

1、快速入门
IDE:集成开发环境
编译器:GNU、VS
编译器输出一个可执行文件。执行程序后获取状态: echo $?(echo %ERRORLEVEL%)
endl:输出换行,并 刷新设备相关联的缓冲区,使得用户可立即看到写入到流中的输出。
初始化变量
注释//、注释对/**/

2、变量和基本类型
整型表示整数、字符和布尔值的算术类型
只有内置类型存在字面值,没有类类型的字面值,也没有任何标准库类型的字面值。
字面值常量:诸如数、字符或字符串的值,该值不能修改。
①整型字面值规则
int、long。可在数值后面加L或者l【小写】指定常量为long类型;可通过在数值后面加U或u定义unsigned类型。【128u、1L、1024UL、8Lu】没有 short类型的字面值常量
②浮点字面值规则
十进制或者科学计数法。使用科学计数法时,指数用E或者e表示。默认的浮点字面值常量为double类型,在数值的后面加上F或f表示单精度。L或者l可以扩展精度。
③布尔字面值和字符字面值
可打印字符型字面值通常用一对 单引号【''】来定义,这些字面值都是char类型的,在字符字面值前加L就能够得到 wchar_t类型的宽字符字面值
④非打印字符的转义序列
不可打印字符是不可显示的字符【退格、控制符】。还有一些在语言中有特殊意义的字符【单引号、双引号、反斜线符号】。
⑤字符串字面值
双引号括起来的零个或者多个字符表示

c++是一门静态类型语言,在编译时会作类型检查。
初始化。复制初始化语法用等号,直接初始化则是把初始化放在括号中。对内置类型来说,复制初始化和直接初始化几乎没有差别;对类类型的对象来说,有些初始化仅能用直接初始化完成。
内置类型变量的初始化:在函数体外定义的变量都初始化成0,在函数体里定义的内置类型变量不进行自动初始化。
类类型变量的初始化:构造函数、默认构造函数
声明和定义:程序中变量可以声明多次,但只能定义一次。只有定义才分配存储空间
extern】可以通过使用extern关键字声明变量名而不定义它。extern声明不是定义也不分配存储空间,它只是说明变量定义在程序的其他地方。如果声明有初始化式,那么它可被当作是定义,即使声明标记为extern。【eg:extern double pi = 3.1416;虽然使用了extern,但这条语句还是定义了pi,分配并初始化了存储空间。】只有当extern声明位于函数外部时,才可以含有初始化式。
作用域
全局作用域//名字定义在任何其他作用域外
局部作用域//函数内定义
语句作用域【for(int i = 0; i < 10 ;i++)】//语句的条件内定义
类作用域
命名空间作用域
魔数(magic number):程序中意义重要但又不明显的字面值数字,好像这个数是魔术般地从空中出现的】

const限定符
1、定义const对象。把一个对象转换成一个常量,因为常量在定义后就不能被修改,所以定义时必须初始化。
2、const对象默认为文件的局部变量。 非const变量默认为extern。
要使const变量能够在其他的文件中访问,必须显示地指定它为extern。

typedef与define
枚举:【 enum{,,};】枚举成员是一个 常量表达式,所以不能改变枚举成员的值。枚举类型的对象的 初始化或赋值,只能通过其枚举成员或同一枚举类型的其他对象来进行。
头文件和预处理器
因为头文件包含在多个源文件中,所以不应该含有变量或函数的定义。而对于头文件不应该含有定义这一规则,有三个例外。 头文件可以定义①类;②值在编译时就已经知道的const对象;③inline函数
如果const变量不是用常量表达式初始化,那么它就不应该在头文件中定义,应在一个源文件中定义并初始化,并在头文件中为它添加extern声明,以使其能被多个文件共享。
预处理器处理程序的源代码,在编译器之前运行。
头文件保护符:预处理器变量 ,用于避免在已经见到头文件的情况下重新处理该头文件的内容, 避免多重包含
#ifndef 预处理器变量(常用全大写字母来表示)
#define 预处理器变量
//
#endif


3、标准库类型
如果在头文件中放置using声明,就相当于在包含该头文件的每个程序中都放置了同一using声明,不论该程序是否需要using声明。所以通常在头文件中应该只定义确实必要的东西。
【标准库string类型】
初始化string对象的方式。
cin【string类型的输入操作符】:读取并 忽略开头所有的空白字符(如空格、换行符、制表符);读取字符直至再次遇到空白字符,读取终止。
getline【读取整行文本】:getline(输入流对象,string对象); 并不忽略行开头的换行符;只要遇到换行符就会停止读入并返回。
string对象的操作
配套类型使得库类型的使用与机器无关。如 string::size_type类型,size()成员函数的返回类型,它的定义与unsigned型具有相同含义。可以保证足够大能够存储任意string对象的长度。不要把size的返回值赋给一个int变量,size_type存储的string长度是int所能存储的两倍。【 for(string::size_type i = 0; i !=  str.size();++i)】在索引时,虽然任何整数值都可作为索引,但索引的实际数据类型却是unsigned类型string::size_type。
当进行string对象和字符串字面值混合连接操作时, +操作符的左右操作数必须至少有一个是string类型的
头文件cctype中字符操作函数【字母(isalpha(c))、数字(isdigit(c))、小写字母(islower(c)) 、大写字母(isupper(c)) 、大写变小写(tolower(c))、小写变大写(toupper(c)) 】(( 采用C标准库头文件的C++版本,cctype是利用了c标准库函数,这些库函数就定义在ctype.h头文件中。cctype与ctype.h文件内容是一样的,只是采用了更适合c++程序的形式。在c++中少了后缀.h,加了c, 其中c表示这个头文件源自C标准库
【标准库vector类型】
初始化vector对象的方式。
vector对象的操作(empty、size)
同样地,size返回相应vector类定义的size_type值。例:vector<int>::size_type
安全的 泛型编程(循环判断条件选用!=而不是<=)
必须是已存在的元素才能用下标操作符进行索引。通过下标操作进行赋值时,不会添加任何元素。
【迭代器简介】
begin返回的迭代器指向第一个元素,end操作返回的迭代器指向末端元素的下一个。
const_iterator类型:该类型只能用于读取容器内元素,不能改变其值。区分const iterator,声明一个const迭代器时,必须初始化迭代器。并且一旦被初始化后就不能改变它的值
difference_type:类似于size_type,是signed类型。
任何改变vector长度的操作都会使得已存在的迭代器失效
【标准bitset类型】
二进制位的有序集。保存位集,并提供对各个位的测试和置位操作。
初始化bitset对象
bitset对象上的操作
b.count()//b中置为1的二进制位的个数,返回类型是 size_t,该类型定义在 cstddef头文件中,是C标准库头文件stddef.h的C++版本,是一个与机器相关的unsigned类型,其大小足以保证存储内存中对象的大小。
访问bitset对象中的位
to_ulong()//返回一个unsigned long值,仅当bitset类型的长度小于或等于unsigned long的长度时,才可以使用to_ulong操作。该函数主要用于把bitset对象转到C风格或标准C++之前风格的程序上。

4、数组和指针
类似于vector和迭代器类型的低级复合类型。设计良好的程序只有在 强调速度时才在类实现的内部使用数组和指针。
【数组】
与vector类型相比,数组的显著缺陷在于数组的长度是固定的,而且程序员无法知道一个给定数组的长度。
数组的定义和初始化
int size = 27;
double Data[size];//error。 size是一个非const对象
当使用字符串字面值来初始化创建的新数组时,将在新数组中加入空字符。(字符串字面值包含一个额外的空字符用于结束字符串
数组的下标类型是 size_t
【指针】
指针具有两个属性: 指向变量(对象)的地址长度,但是指针只存储地址,长度则取决于指针的类型。编译器根据指针的类型从指针指向的地址向后寻址,指针类型不同则寻址范围也不同。

保存对象的地址
现代C++程序采用vector类型和迭代器取代一般的数组,采用string类型取代C风格字符串。
避免使用未初始化的指针。【把int型变量赋给指针是非法的,尽管此int型变量的值可能为0.但允许把数值0或在编译时可获得0值的const量赋给指针。int p = 0; //不能赋给指针const int p = 0;//可以赋给指针
除此之外还可使用预处理器 变量NULL赋给指针,进行初始化。
由于指针的类型用于确定指针所指对象的类型,因此初始化或赋值时必须保证类型匹配。
【void*指针】:可以保存 任何类型对象的地址。只支持几种有限操作:①与另一个指针进行比较;②向函数传递void*指针或从函数返回void*指针;③给另一个void*指针赋值。
void指针没有类型也就不能判断出指向对象的长度。如果要将其赋给其他类型指针,则需要强制类型转换 。并且void指针不能解引用(void指针只知道指向变量/对象的起始地址,而不知道指向变量/对象的大小,所以无法正确接引用。)而void**指针却可以进行解引用

指向指针的指针: **ppi
两个指针减法操作的结果是标准库类型 ptrdiff_t的数据。ptrdiff_t是一种与机器相关,在cstddef头文件中定义,signed整型。
只要指针指向数组元素,就可以对它进行下标操作:
int *p = &a[2];
int j = p[1];    //j = a[3]
int k = p[-2]; //k = a[0]
【指向const对象的指针】
eg:const double *cptr;// 允许给cptr重新赋值,使其指向另一个const对象,但不能通过对cptr修改其所指对象的值。
const对象只能使用指向const对象的指针,而非const对象既能使用指向const对象的指针,又能使用一般指针。
【const指针】
eg:int a = 0;
int *const p = &a;// 指针本身值不能修改,即不能指向其他对象。与任何const量一样,const指针也必须在定义时初始化。
指针所指对象的值能否修改完全取决于该对象的类型。
【指向const对象的const指针】
eg:const int a = 3;
const int *const p = &a;/ /既不能修改所指对象的值又不允许修改该指针的指向。
【指针和typedef】
eg:typedef string *pstring;
const pstring cstr;// 此处const修饰的是pstring的类型,即该声明语句应该是把cstr定义为指向string对象的const指针。等价于string *const cstr
const限定符既可以放在类型前也可以放在类型后。
string const s1; const string s2;//s1和s2类型一样
string s; typedef string *pstring; const pstring cstr1 = &s;  pstring const cstr2 = &s; string * const cstr3 = &s;//三种写法一样
【C风格字符串
C风格字符串是 以空字符null结束的字符数组。【char】在C++中,字符串字面值就是C风格字符串。
C风格字符串的标准库函数(#include<cstring>
strlen【 返回字符串的长度,不包括字符串结束符null】、strcmp、strcat、strcpy、strncat、strncpy//传递的参数指针必须具有非零值,并且指向 以null结束的字符数组中的元素。
使用 strn函数处理C风格字符串,可以适当地控制复制字符的个数。
【动态数组
自由存储区(堆):每一个程序在执行时用于存放动态分配对象占用的内存空间。 C语言使用malloc和free,而C++使用new和delete 在自由分配存储区中分配存储空间。
动态分配数组时, 只需指定类型和数组长度,不必为数组对象命名。 eg: int *pia = new int[10];
动态分配数组时,如果数组元素具有 类类型,将使用该类的 默认构造函数实现初始化;如果数组元素是 内置类型则无初始化,但可在数组长度后面 添加一对空圆括号,对数组元素做值初始化, eg:int *pia = new int[10]( );
动态分配的内存最后必须进行释放,否则内存最终将会逐渐耗尽。 delete [  ] pia;
string类提供了一个名为 c_str的成员函数,能够 返回C风格字符串。【char *str = st. c_str( );】 //返回指向字符数组首地址的指针,该数组存放了与string对象相同的内容,并且以结束符null结束。
使用数组初始化vector对象,必须指出用于初始化式的第一个元素以及数组 最后一个元素的下一位置的地址
【多维数组
数组的数组。 数组中的元素是一个数组。
int ia[3][4];//ia指向第一个元素,该元素为有四个值的数组。
int (*ip) [4] = ia; //*ip是int[4]类型,即ip指向含有4个元素的数组的指针。
int *ip[4];//int型指针的数组
使用 typedef简化指向多维数组的指针。
typedef int int_array[4];
int_array *ip = ia;//*ip是int[4]类型,即ip指向含有4个元素的数组的指针。
对ip解引用获得一个有4个int型元素的数组,通常,使用该数组时,系统会自动将它转换为指向该数组第一个元素的指针。//int *iq = *ip;//此时iq指向ip所指数组中的第一个元素

5、表达式
如果只有一个操作数为负数,除法(/)和求模(%)的结果取决于机器。
如果操作数为负数,则位操作符如何处理操作数的符合依赖于机器。
移位操作的右操作数必须是严格小于左操作数位数的值
&、|、~【位操作】
&&、||、!【逻辑操作】
逗号表达式:一组由逗号分隔的表达式,这些表达式从左向右计算。逗号表达式的结果是其最右边表达式的值。
自增有前置【++i】和后置【i++】两种形式,前置使得操作数加1,操作结果是修改后的操作数的值;后置使得操作数加1,但操作结果是原来的、未修改的操作数值。
int i = 0, j;
j = ++i;//i = 1,j = 1
j = i++;//i =2,j = 1
只有在必要时才使用后置操作符,使用前置操作,不必操心性能差异的问题。
【*iter++】//++优先级高于*
等价于
*iter;
++iter;
sizeof 返回值类型为size_t,长度单位是字节。
如果指针指向不是用new分配的内存地址,则在该指针上使用delete是不合法的。【delete可删除0值指针
在delete之后,应该重设指针值。【删除指针后,该指针变成悬垂指针,悬垂指针指向曾经存放对象的内存,但该对象已经不再存在了,所以一旦删除了指针所指向的对象,立即将指针置为0,这样就非常清楚地表明指针不再指向任何对象。 (可避免读写已删除的对象
【内存泄漏】
指删除动态分配内存失败。内存泄漏很难发现,一般需等应用程序运行一段时间后,耗尽了所有内存空间时,内存泄漏才会显露出来。
【隐式类型转换】
编译器在必要时将类型转换规则应用到内置类型和类类型的对象上。
【算术转换】
整型提升:对于所有比int小的整型,会被提升为int型,或者unsigned int型。
若表达式中使用了无符号数值,所定义的转换规则则需保护操作数的精度。unsigned操作数的转换依赖于机器中整型的相对大小,因此,这类转换本质上依赖于机器。
【显示转换】强制类型转换//强制类型转换关闭或挂起了正常的类型检查,程序中应避免使用强制类型转换。
dynamic_cast
支持运行时识别指针或引用所指向的对象
const_cast
转换掉表达式的const性质(添加或删除const特性
static_cast
编译器隐式执行的任何类型转换都可以由其显示完成
reinterpret_cast
为操作数的位模式提供较低层次的重新解释。本质上依赖于机器。在引入命名的强制类型转换操作符之前,显示强制转换用圆括号将类型括起来实现的效果与使用reinterpret_cast符合相同,但其可视性比较差。

6、语句
case标号必须时整型常量表达式。
【*dest++ = *sourc++;】//数组复制
等价于
{
     *dest = *sourc;
     ++dest;
     ++source;
}
当break出现在嵌套的switch或者循环语句中时,将会终止里层的switch或循环语句,而外层的switch或者循环不受影响。
goto语句提供了函数内部的无条件跳转,实现从goto语句跳转到 同一函数内某个带标号的语句。
向前跳:不能跨越属于同一域的变量的定义语句。防止变量可能在没有定义的情况下使用。
goto label;
……
label: ;
向后跳:向后跳回到一个变量定义之前,则会使系统撤销这个变量,然后再重新创建它。
label: ;
goto label;
【异常处理】
throw表达式:错误检测部分使用这种表达式来说明遇到了不可处理的错误。
【throw 表达式;】
try块:错误处理部分使用它来处理异常。
catch子句(处理代码):处理在try块中执行的代码所抛出的异常
【try块通用语法形式】
try
{
     program-statements//语句序列块
}
catch(exception - specifier//单个类型或者单个对象的声明即异常说明符)
{
     handler-statements//语句块
}
catch(exception - specifier)
{
     handler-statements
}//……
如果不存在处理该异常的catch子句,程序的运行就要跳转到名为 terminate地标准库函数来终止程序的执行。
【标准异常】
标准库异常类定义在四个头文件中:
1、 exception头文件定义了最常见的异常类,它的类名使exception。该类只通知异常的产生,但不会提供更多的信息。
2、 stdexcept头文件定义了几种常见的异常类。【eg:   exception、runtime_error、range_error、logic_error、out_of_range……
3、 new头文件定义了bad_alloc异常类型,提供因无法分配内存而由new抛出的异常。
4、 type_info头文件定义了bad_cast异常类型。
【注】
exception、bad_alloc以及bad_cast类型只定义了默认构造函数,无法在创建这些对象时为它们提供初值,其他异常类型则只定义了一个使用string初始化式的构造函数。
异常类型只定义了一个名为what的操作。这个函数不需要任何参数,并且返回const char*类型的值,即返回的指针指向一个C风格字符串。
【使用预处理器进行调试】
预处理变量:
NDEBUG
预处理器还定义了其余四种在调试时非常有用的 常量_ _FILE_ _文件名   _ _LINE_ _当前行号  _ _TIME_ _文件被编译的时间    _ _DATE_ _文件被编译的日期
       使用NDEBUG预处理变量以及 assert(断言)预处理宏进行调试。assert宏是在 cassert头文件中定义的。 【assert(expr)】只要NDEBUG未定义,assert宏就求解条件表达式expr,如果为false,assert输出信息并且终止程序的执行。如果该表达式有一个非零值,则assert不做任何操作。 assert仅用于检查确实不可能的条件,这只对程序的调试有帮助,但不能用来代替运行时的逻辑检查,也不能代替对程序可能产生的错误检测。

7、函数
【参数传递】
【非引用形参】
普通的非引用形参通过复制对应的实参实现初始化,因此不会修改实参的值。复制形参时并不考虑形参是否为const,因为函数操纵的只是副本,函数无法修改实参。
1、指针形参:被复制的指针只影响对指针的赋值,即影响指针所指向对象的值。形参复制的是这个指针的值,而不是指针所指元素本身。函数操纵的是指针的副本,因此不会修改实参指针的值,然而可通过该指针改变它所指向的元素的值。
2、const形参:函数形参若为 非引用的非const形参则既可给该函数传递const实参也可传递非const实参(由于是复制的副本,所以若实参是const也是可以进行传递更改的;如果形参为 非引用的const类型,则在函数中,不可以改变实参的 局部副本。并且由于实参仍然是以 副本的形式传递,因此传递给函数的实参既可以是const对象也可以是非const对象。(初始化复制了初始化式的值,所以可以用const对象初始化非const对象,反之亦然。
在C语言中,具有const形参或非const形参的函数并无区别。
复制实参的局限性:
①当需要在函数中修改实参的值时。
②当需要以大型对象作为实参传递时。对实际的应用而言,复制对象所付出的时间和存储空间代价往往过大。
③当没有办法实现对象的复制时。
由此,可将形参定义为引用或指针类型。
【引用形参】
引用形参直接关联到其所绑定的对象,而并非这些对象的副本。
1、使用引用形参返回额外的信息:即传递进去的参数是能够被改变的,调用函数后,这些实参得到改变,可以当作返回的结果。
2、利用const引用避免复制:传递 大型对象时,使用引用形参,函数可以直接访问实参对象,而无需复制它,提高效率。 如果引用形参的唯一目的是避免复制实参,则应将形参定义为const引用。
3、更灵活的指向const的引用:如果函数具有普通的 非const引用形参,则显然不能通过 const对象进行调用。(此时函数可以修改传递进来的对象,此时违背了实参的const特性,与非引用的非const形参不同
即非const引用形参只能与完全同类型的非const对象关联。所以应该 将不修改相应实参的形参定义为const引用,以便既能传递const实参也能传递一般实参
4、传递指向指针的引用:int *&v; 从右到左理解,v是一个引用,与指向int型对象的指针相关联。
注:在传递内置类型时,其复制效率高于寻址解引

【vector和其他容器类型的形参】
一般传递迭代器
【数组形参】
数组不能复制,所以无法编写使用数组类型形参的函数。
数组形参可定义为 引用或非引用类型。大部分情况下,数组以普通的非引用类型传递,此时数组会悄悄地转换为指针。一般来说,非引用类型的形参会1初始化为其相应实参的副本。
形参是数组的引用时, 数组大小成为形参和实参类型的一部分。编译器检查数组实参的大小与形参的大小是否匹配。

【传递给函数的数组的处理】
非引用数组形参的类型检查只是确保实参是和数组元素具有同样类型的指针,而不会检查实参实际上是否指定大小的数组。为了确保函数的操作不超出数组实参的边界,一般有三种方法:
1、在数组本身放置一个标记来检测数组的结束。eg:C风格字符串,以空字符null作为结束的标记
2、使用标准库规范。即传递指向数组第一个和最后一个元素的下一个位置的指针。
3、将第二个形参定义为表示数组的大小。
【main:处理命令行选项】
int main(){……}
int main(int argc,char *argv[ ]){……}或int main(int argc,char **argv){……}  // argv是一个C风格字符串数组,argc是传递该数组中字符串的个数。第一个实参argv[0]是命令名。
//在命令行运行该程序,以便argv参数传入。
【含有可变形参的函数】
使用省略符形参【...】,省略符暂停了类型检查机制。

【return语句】
结束当前正在执行的函数。
不带返回值的return语句只能用于返回类型为void的函数。返回类型为void的函数可以返回另一个返回类型同样是void的函数的调用结果。
【具有返回值的函数】
1、主函数main的返回值
允许主函数main没有返回值就可结束。编译器会隐式地插入返回0的语句。
2、返回非引用类型
函数返回值复制给临时对象
3、返回引用
当函数返回引用类型时,没有复制返回值。相反,返回的是对象本身。
千万不能返回局部变量的引用。(当函数执行完毕时,将释放分配给局部对象的存储空间。
4、引用返回左值
即可以给函数返回值赋值。
千万不要返回指向局部对象的指针。
【函数声明】
默认实参
如果有一个形参具有默认实参,那么,它后面所有的形参都必须有默认实参。函数调用的实参按位置解析,默认实参只能用来替换函数调用缺少的 尾部实参。所以一般地,使最少使用默认实参的形参排在最前。最可能使用默认实参的形参排在最后。
【局部对象】
1、 自动对象:只有当定义它的函数被调用时才存在的对象
2、 静态局部对象:在该函数被多次调用的过程中,静态局部对象会持续存在并保持它的值。
【内联函数】
在函数返回类型前加上关键字 inline。一般地,内联机制适用于优化小的、只有几行的而且经常被调用的函数。大多数编译器都不支持递归函数的内联。 内联函数应该在头文件中定义,以便编译器能够在调用点内联 展开该函数的代码,避免函数调用的开销。
【类的成员函数】
编译器隐式地将在类内定义的成员函数当作 内联函数
每个成员函数(除了static成员函数外),都有一个额外的、隐含的形参this。在调用成员函数时,形参this初始化为调用函数的对象的地址。
语句:total.same_isbn(trans);编译器可重写为Sales_item::same_isbn(&total,trans)// this形参的实参为&total。
const成员函数(常量成员函数)形参表后面添加const。改变了隐含的this形参的类型,在调用函数时, 隐含的this形参将是一个指向调用函数的对象的const类型指针。由于this是指向const对象的指针,所以const成员函数不能修改调用该函数的对象
因而const对象、指向const对象的指针或引用只能用于调用其const成员函数。
构造函数的初始化列表:为类的一个或多个数据成员指定初值。它跟在构造函数的形参表之后,以冒号开头,多个成员的初始化用逗号隔开,每个成员后面是括在圆括号中的初始值。
合成的默认构造函数:由编译器创建的默认构造函数。
【重载函数】
函数不能仅仅基于不同的返回类型而实现重载。
在函数中局部声明的名字将屏蔽在全局作用内声明的同名名字。
为了确定最佳匹配, 编译器将实参类型到相应形参类型的转换划分为等级。转换等级以降序排列如下:
1、精确匹配。实参与形参类型相同
2、通过类型提升实现的匹配
3、通过标准转换实现的匹配
4、通过类类型转换实现的匹配
由于不同 枚举类型的枚举常量值不相同,在函数重载确定过程中,不同的枚举类型会具有完全不同的行为。其枚举成员决定了它们提升的类型,而所提升的类型依赖于机器。
当形参以副本传递时,不能基于形参是否为const来实现重载。// 复制形参时并不考虑形参是否为const,因为函数操纵的只是副本,函数无法修改实参。
【指向函数的指针】
函数类型由其返回类型以及形参表确定,而与函数名无关。eg:【bool *pf(const string &,const string &);//pf为函数指针】
1、用typedef简化函数指针的定义
typedef bool (*cmpFcn)(const string &,const string &);//cmpFcn是一种指向函数指针类型的名字。
2、指向函数的指针的初始化和赋值
在引用函数名但又没有调用该函数时, 函数名将被自动解释为指向函数的指针。此时,直接引用函数名等效于在函数名上应用取地址操作符。函数指针只能通过同类型的函数或函数指针或0值常量表达式进行初始化或赋值。
3、通过指针调用函数
指向函数的指针可以不需要使用解引用操作符,直接通过指针调用函数。pf(“hi”,“bye”)或(*pf)(“hi”,“bye”)
4、函数指针作为形参
void use(const string &,const string & , bool(const string &,const string & ));或void use(const string &,const string & , bool (*)(const string &,const string & ));
5、返回指向函数的指针
int (*ff(int))(int *,int);
等效于
typedef int (*PF)(int *,int)
PF ff(int);
ff()函数返回类型是指向函数的指针。
一个函数的形参可以定义为函数类型,但一个函数的返回类型则必须是指向函数的指针,而不能是函数。因为函数类型作为形参时,其所对应的实参将被自动转换为指向相应函数类型的指针,但是当返回的是函数类型时,同样地转换操作则无法实现。
6、指向重载函数的指针
指针的类型必须与重载函数的一个版本精确匹配。

7、标准IO库
【iostream】:读写 控制窗口的类型
【fstream】:读写 已命名文件的类型
【sstream】:读写 已存储在内存中的string对象
wchar_t类型的标准输入对象·是wcin、标准输出是wcout、标准错误则是wcerr。
IO对象不可复制或赋值形参或返回类型也不能为流类型(使用指针和引用,避免对象的复制。一般情况下,如果要传递IO对象以便对它进行读写,可用非const引用的方式传递该流对象,对IO对象的读写会改变它的状态,因此引用必须是非const的。
【标准库的条件状态】
clear、setstate操作管理。

每一个IO对象管理一个 缓冲区,用于存储程序读写的数据。缓冲区内容刷新,写入到真实的输出设备或文件方法:
1、程序正常结束。作为main返回工作的一部分,将清空所有输出缓冲区。
2、在一些不确定的时候,缓冲区已满,此时缓冲区将会在下一个值之前刷新
3、使用操纵符显示地刷新缓冲区,例如结束符 endl(换行符)、flush(不在输出中添加任何字符)、ends(插入空字符null)
4、在每次输出操作执行完后,用 unitbuf操纵符设置流的内部状态,从而清空缓冲区。【 刷新所有输出
5、可将输出流与输入流关联起来。在这种情况下,在读输入流时将刷新其关联的输出缓冲区。( tie函数,一个ostream对象每次只能与一个istream对象绑在一起。如果在调用tie函数时传递实参0,则打破该流上已存在的捆绑

由于历史原因,IO标准库使用C风格字符串而不是C++ string类型的字符串作为文件名。若文件名保存在string对象中,则可调用c_str成员获取C风格字符串。
如果程序员需要重用文件流读写多个文件,必须在读另一个文件之前调用clear清除该流的状态。
默认情况下,fstream对象以in和out模式同时打开,此时文件不请空,并定位于文件开头处。只使用out模式,则文件会清空已存在的数据。若指定了trunc模式,则文件一定会被清空。
【字符串流】
创建:stringstream strm;    stringstream strm(s);
strm.str()\\返回strm中存储的string对象        strm.str(s)\\将string类型的s复制给strm
一般情况下,使用输入操作符读string时,空白符将会被忽略。

















































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值