C/C++
一、函数输入参数
对于只做输入的参数:
a) 始终用const限制所有指向只输入参数的指针和引用。
b) 优先通过值来取得原始类型和复制开销比较低的值的对象。
c) 优先按const的引用取得其他用户定义类型的输入,
d) 如果函数需要其他参数的副本,则可以考虑通过值传递代替通过引用传递。这在概念上等同于通过const引用传递加上一次复制,能够帮助编译器更好的优化掉临时变量。
二、|和||,&和&&的区别
我们将||和&&定义为逻辑运算符,而|和&定义为位运算符。
&&如果两个操作数都非零,则条件为真;
||如果两个操作数中有任意一个非零,则条件为真。
&按位与操作,按二进制位进行“与”运算:(有0则为0)
0&0=0;
0&1=0;
1&0=0;
1&1=1;
|按位或运算符,按二进制位进行“或”运算。运算规则:(有1则为1)
0|0=0;
0|1=1;
1|0=1;
1|1=1;
那么,问题来了,在判断语句中,用|还是||,&还是&&?
判断语句中为布尔类型,只有true和false(如果变量值为0就是false,否则为true)
举个例子,a=1 b=2
所以 a>0 这个值为true b>1 这个值为true b>2 这个值为 false
如 if(a>0&b>1) 我们可以得出 if(true&true),条件成立(true不为0,所以true&true不为0)
如 if(a>0&&b>1) 我们可以得出 if(true&&true),条件成立(&&两边操作数都非零,所以条件成立)
如 if(b>2&a>0) 我们可以得出 if(false&true),条件不成立(false为0,false&true为0,条件不成立)
如 if(b>2&&a>0) 我们可以得出 if(false&&a>0),条件不成立(&&左侧为false,&&运算到此结束,条件不成立)
可以看出&和&&在判断语句中都可以实现“和”这个功能,不过区别在于&两边都运算,而&&先算&&左边,若左边为false,那么右边就不运算了。因此从效率上来讲,判断语句推荐使用&&。
而|和||同理,则不再论述。
三、运算符优先级
口诀:淡云一笔安洛三赋
(单目>算术运算符>移位运算符>比较>按位>逻辑>三目>赋值>逗号)
!逻辑非运算符;
~按位取反运算符;
四、模板类型匹配时的类型转换
1、 如果使用模板参数类型自动判断,那么参数类型转换只支持非const到const以及数组和函数指针到指针的抓换。
2、 如果显示指定参数类型,即fun<int>(1.3,2),可以进行相应的类型转换。
3、 如果模板参数为非模板参数,即template<typename T>void test(const T&,int i),参数i可以进行类型转换。
十一、 fseek函数
int fseek(FILE *stream, long offest, int fromwhere);函数设置文件指针stream的位置。
如果执行成功,stream将指向以fromwhere为基准,偏移offset(指针偏移量)个字节的位置,函数返回0.如果执行失败(比如offset的取值大于等于2*1024*1024*1024,即long的整数范围2G),则不改变stream指向的位置,函数返回一个非0值。
fseeek函数和lseek函数类似,但lseek返回的是一个off_t数值,而fseek返回的是一个整型。
功能:
重定位流(数据流/文件)上的文件内部位置指针
注意:文件指针指向文件/流。位置指针指向文件内部的字节位置,随着文件的读取会移动,文件指针如果不重新赋值将不会改变或指向别的文件。
头文件:#include <stdio.h>
用法:int fseek(FILE *stream, long offset, int fromwhere);
int fseek( FILE *stream, long offset, int origin );
第一个参数stream为文件指针
第二个参数offset为偏移量,正数表示正向偏移,负数表示负向偏移
第三个参数origin设定从文件的哪里开始偏移,可能取值为:SEEK_CUR、 SEEK_END 或 SEEK_SET
SEEK_SET: 文件开头
SEEK_CUR: 当前位置
SEEK_END: 文件结尾
其中SEEK_SET,SEEK_CUR和SEEK_END依次为0,1和2.
简言之:
fseek(fp,100L,0);把stream指针移动到离文件开头100字节处;
fseek(fp,100L,1);把stream指针移动到离文件当前位置100字节处;
fseek(fp,-100L,2);把stream指针退回到离文件结尾100字节处。
十二、 析构函数
析构函数与构造函数相反,当对象结束其生命周期,如对象所在的函数以调用完毕时,系统自动执行析构函数。析构函数往往用来做“清理善后”的工作(例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。
十三、 重载函数
重载函数是函数的一种特殊情况,为方便使用,C++允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或顺序)必须不同,也就是指说用同一个函数完成不同的功能。这就是重载函数。重载函数常用来实现功能类似而所处理的数据类型不同的问题。不能只有函数返回值不同。
十四、 动态内存分配
在c/c++语言中,编写程序有时不能确定数组应该定义为多大,因此这时在程序运行时要根据需要从系统中动态多地获得内存空间。所谓动态内存分配,就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不像数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。
C语言允许建立内存动态分配区域,以存放一些临时用的数据,这些数据不必在程序的声明部分定义,也不必等到函数结束时才释放,而是需要时随时开辟,不需要时随时释放。C语言中,内存的动态分配是通过系统提供的库函数来实现的,主要有malloc、calloc和 free 函数。
malloc 函数
其函数原型为
void *malloc(unsigned int size);
其作用是在内存的动态存储区中分配一个长度为size的连续空间。此函数的返回值是分配区域的起始地址,或者说,此函数是一个指针型函数,返回的指针指向该分配域的开头位置。如:
malloc(100);/*开辟 100 个字节的临时分配域,返回值为其第一个字节的地址*/
注意指针的基类型为 void,即不指向任何类型的数据,只提供一个地址。如果此函数未能成功的执行(例如内存空间不足),则返回空指针(NULL)。
calloc函数
函数原型为
void *calloc(unsigned n, unsigned size)
其作用是在内存的动态存储区中分配n个长度为 size 的连续空间。函数返回一个指向分配区域的起始位置的指针;如果分配不成功,则返回NULL。
采用 calloc 函数可以为一维数组开辟动态存储空间,n 为数组元素个数,每个元素长度为 size,这就是动态数组。如:
p = calloc(50,4) /*开辟 50*4个字节的临时分配域,把起始地址赋给指针变量p */
free 函数
函数原型为
void free(void*p);
其作用是释放指针 p 所指向的动态空间,使这部分空间能被其他变量使用。p 是最近一次调用 calloc 或malloc 函数时的返回值。free函数无返回值。如:
free(p); /*释放指针变量p指向的已分配的动态空间*/
上述三个函数在头文件malloc.h和 stdlib.h 中定义。若要使用,必须在程序的开始将头文件用文件包含命令放到本文件中来。
函数运算符
new
运算符new用于向系统申请动态存储空间,并把首地址作为运算结果,它的使用形式为:
指针变量=new 数据类型;
例如:
int *p=new int
该语句的作用是会用new从内存中申请了一个int型变量(4个字节),并将该变量的首地址赋给指针变量p。
new所建立的变量的初始值是任意的,也可在用new分配内存的同时进行初始化。使用形式为:
指针变量=new 数据类型(初始值)。
delete
堆内存可按照要求进行分配,程序对内存的需求量随时会发生变化,有时程序在运行种可能会不再需要由new分配的内存空间,而且程序还未运行结束,这时就需要把先前占用的内存空间释放给堆内存,以后重新分配,供程序的其他部分使用。运算符delete用于释放new分配的内存空间,删除建立的对象,它的使用形式为:
delete 指针变量;
其中的指针变量中保存着new分配的内存的首地址。 [2]
十五、 C++文件打开方式
文件打开方式选项
ios::in = 0x01, //供读,文件必须已经存在(ifstream默认的打开方式)
ios::out = 0x02, //供写,文件不存在则创建,若文件已存在则清空原内容(ofstream默认的打开方式)
ios::ate = 0x04, //文件不存在时,生成空文件;文件不存在,清空原文件(ofstream打开方式)。如果没有文件,打开失败;如果有文件,定位到文件尾,但是不能写文件(ifstream打开方式)。
ios::app = 0x08, //供写,文件不存在则创建,若文件已存在则在原文件内容后写入新的内容,指针位置总在最后
ios::trunc = 0x10, //在读写前先将文件长度截断为0(默认)
ios::nocreate = 0x20, //文件不存在时产生错误,常和in或app联合使用
ios::noreplace = 0x40, //文件存在时产生错误,常和out联合使用
ios::binary = 0x80 //二进制格式文件