1.缓冲
FILE * 类型的函数或者以此为返回值的都是有缓冲区的
1.全缓冲
2.行缓冲 例如:标准输出【stdout】
3.无缓冲 例如:标准出错【stderr】
说明:c语言的关于文件操作的函数,其实都是使用了unix 内核的函数,而这些内核的函数全都是没有缓冲区的,但是,c语言在调用这些内核函数生成库函数的时候都加了缓冲区
2.一般的系统,在进程启动是,默认打开三个文件,
stdin 标准输入
stdout 标准输出
stderr 标准出错
其中标准出错和标准输出都是输出到终端上面
3.stdout [标准输出]的刷新方法:
1.遇到\n
2.调用了fflush(stdout) fclose(stdout) 这些函数
3.调用了标准的输入函数: getchar() gets() 等等这些函数
4.当一个进程结束,也会自动的刷新缓冲区
4.函数:
1. FILE * fopen(const char * path, const char *mode);
path:打开的文件路径 【这里支持绝对路径也支持相对路径】
mode:打开的方式:
r 只读 r+ 读写 文件的读写位置在文件的开头
w 只写 w+ 读写 文件的读写位置在文件的开头
a 追加写 a+ 读写 文件的读写位置在文件的结尾
返回值,我们叫做文件的句柄
2. size_t fread(void * ptr, size_t size, size_t nmemb, FILE *stream);
ptr: 就是要把数据读到哪里,我们一般定义一个buf
size:一次要读多少字节
nmemb:读几次
stream:要读那个文件的句柄
3. size_t fwrite(void * ptr, size_t size, size_t nmemb, FILE *stream);
ptr: 我们要从哪里读数据
size:一次要读多少字节
nmemb:读几次
stream:要写入的那个文件的句柄
4. fclose(FILE * fd);
fd 要关闭的文件描述符。
5.int fseek(FILE *fd, long offset, int whence);
【说明】 此函数实现对文件的句柄进行定位,当我们打开一个文件的时候,文件的描述符默认
实在文件最开始,文件的描述符指向哪里,那么接下来的对文件的操作就是从这里开始的。
fd: 文件描述符
offset:偏移量 可以为正也可以为负 为正的话就是相对文件描述符往后偏移多少
为负的化就是相对文件描述副往前偏移多少
这个偏移量的单位是字节
whence :位置 三个值
SEEK_SET 在开始的位置
SEEK_CUR 当前位置
SEEK_END 文件的结尾
6. long ftell(FILE * fd);
返回值是文件描述符所在的位置相对于文件开始的偏移量
【往往使用这个函数来计算文件的大小,当然要想把描述副定位到文件的开始】
7. int fseeko (FILE * fd, off_t ooofset, int whence);
说明:关于文件操作,在书写的时候 fopen 和fcose 是成对出现的,有打开就有关闭。
在使用文件的打开的时候一定要有出错处理
前言:
1、拷贝构造函数和赋值拷贝赋值运算符
拷贝构造函数和赋值拷贝运算符之前的区别:
拷贝构造是使用已经存在的对象初始化一个新的对象
拷贝赋值就是使用同型的对象中拷贝其值到本对象
2、使用const/inline/enum 替代#define
1、由于#define是在编译阶段把程序中所有的相关的名字直接的替换成响应的数据,导致在当程序出现问题时出现魔数
2、常量指针的定义需要注意的格式问题,原则就是去掉类型符号,const离谁斤就是修饰谁的
3、类的专属常量的定义:
类的专属的常量使用const修饰在类的内部,为了该数据至此一份,使用static修饰,例如:
const static int aa;
需要注意的是,上面是该常量的声明而不是定义,你需要在源文件中给出他的定义,对其进行赋值:
const class tmp::aa =0;
3、尽可能使用const
1、const 可以声明基本上C++内部的所有的数据的类型、函数、类成员函数、类的数据成员
2、const修饰指针变量标识该指针变量不可以改变,也可以修饰指针指向的对象
3、const可以修饰迭代器,标识不可以对一个迭代器进行修改
4、const修饰函数的返回值,标识不可以对一个函数的返回值就行修改,赋值等操作
5、const修饰类的成员函数:
格式:在函数的声明和定义函数参数列表后面加上关键字const修饰
const修饰类的成员函数是保证其可以使用类中的const数据成员
6、类中的const数据成员不可以直接在类中初始化,只有static修饰的静态数据才能使用直接初始化
const修饰的数据成员只能通过类的构造函数的参数初始化列表初始化。
4、初始化
1、对于内置类型的数据对象记住最好是初始化。
2、对于自定义的数据类型,需要在构造函数内部对该类型内部的数据成员进行初始化。
3、
注意从下面开始都是简单的做些记录
5、构造函数、析构函数、拷贝构造函数、赋值运算符
6、如果不想使用系统默认生成的一些函数,就应该明确的声明
1、系统会为一个类默认的生成一些函数,包括构造函数、析构函数或者拷贝构造函数和拷贝运算符这些,如果不想让系统默认的生成的话
就自己定义,并且把他们声明为privated的
7、为基类声明virtual函数
1、如果一个类打算作为一个多态的基类,那么对于其中的函数,最好是声明为virual,如果一个基类有virtual声明的函数,那么则需要一个virtual的析构函数
2、
8、不要再析构函数中吐出异常:
1、析构函数中的异常尽量不要吐出,因为析构函数往往做的事情就是对内存中的数据进行释放,如果由于中间的某一个操作导致的程序异常,则必然造成内存的溢出
9、不要再构造函数中调用virtual 函数,由于在基类中调用virtual函数的时候派生类还没有生成,会导致许多不可预知的错误
10、让赋值运算符返回一个指向当前对象的引用
1、赋值运算符是可以实现连续赋值的,为了实现这个目标,在运算符重载的时候需要范围指向操作符左侧的数据的引用
11、拷贝构造函数的重写需要注意的问题:
1、确保对所有的当前类的所有的数据成员都进行了拷贝,包括所有的基类的数据成员也进行了拷贝
2、不要尝试使用一个拷贝构造函数去实现另外一个拷贝构造函数,因为如果真的这样做了,你不能保证,后面的那个拷贝构造函数永远都是前一个的子集,
最好的办法就是把他们共同的技能都放在同一个函数中,由这两个拷贝构造函数调用。
12、使用对象管理内存:
1、C++允许用户自己申请和管理处于堆中的内存空间,由new创建、使用delete删除
2、用户自己管理内存的危险就在于,时长会出现忘记释放的情况
3、使用对象管理内存的关键就是:1、申请到的内存立即放进对象 2、使用对象的析构函数自动的释放内存
4、比较常用的是:std::auto_ptr 和std::tr1::shared_ptr
格式: std::auto_ptr<类型> 指针名 = 所指对象的地址
13、接口的设计需要考虑的是容易容,并且不会被勿用
1、接口说明
2、接口名形象化
14、
16、成对的new 和delete需要使用相同的方式
17、用独立的语句把new出来的对象至于只能指针中
18、函数的参数传递尽量不要使用引用或者是指针传递代替直接的船体对象,避免内存开销和提升效率
19、把数据成员声明为privated
封装性
23、使用非成员函数代替成员函数
1、如果一件事情,增加一个成员函数或者是增加一个非成员函数都可以达到要求,尽量去新加一个非成员函数
愿意就是,新加一个成员函数只会导致类的封装性降低,然而非成员函数并不会
另外,新加一个成员函数也会导致类的拓展性降低,我们尽量保证类内的数据成员有单一的接口,尽量少的接口访问他,这样对于后期的拓展的工作量是有好处的。
24、尽量延后变量的实际的定义出现的时间,可以避免不必要的构造和结构所带来的开销以及花费的时间。
后续、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、