




免费预览已结束,剩余8页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C和C+语言学习总结(资料来自 林锐博士 2001 年7 月24) 知识结构: 1、if,for,switch,goto 2、#define,const 3、文件拷贝的代码,动态生成内存,复合表达式,strcpy,memcpy,sizeof 4、函数参数传递,内存分配方式,内存错误表现,malloc与new区别 5、类重载、隐藏与覆盖区别,extern问题,函数参数的缺省值问题,宏代码与内联函数区别 6、构造和析构的次序,String函数定义 具体实现: 1、if,for,switch,goto if: bool int float pointer char 变量的使用方法 bool bParam; int iParam; float fParam; int* pParam; char cParam; if(bParam) ,if(!bParam); if(iParam = 0 ),if(iParam != 0 ); if(fParam= -0.00001 & fParam = 0.00001); if(pParam = NULL),if(pParam != NULL); if(cParam = 0),if(cParam != 0); if/else/return 的使用方法 if(condition) 可以等价为 return (condition?x:y); return x; else return y; for: 执行效率问题: int row,col,sum; int a1005; for(row=0;row 100;row+) 效率低于 for(col=0;col 5;col+) for(col=0;col 5;col+) for(row=0;row 100;row+) sum = sum+arowcol; sum = sum+arowcol; int i; for(i=0;i N;i+) 效率低于 if(condition) if(condition) for(i=0;i N;i+) DoSomething(); DoSomething(); else DoOtherthing(); else for(i=0;i N;i+) DoOtherthing(); for (int x=0;x =N-1;x+) 直观性差于 for (int x=0;x N;x+) switch: switch(variable) case value1: . break; case value2: . break; default: . break; switch(c)中的c的数据类型可以是int,char,long,unsigned int,bool. variable必须是整数或者强制为整数,由于char实际上是ASCII码,所以也可以. c不可以是double,float,char*. goto: goto主要用于 . . . goto error; error: . 2、#define,const #define和const区别 1、#define C语言 const C语言 C+语言 const常量有数据类型,编译器会进行类型安全检查,而#define没有数据类型, const的常量可以进行调试,但宏常量不能进行调试. 2、const的使用方法 在全局定义 const float PI=3.1415926 在类中定义 class A . A(int size); const int SIZE; ; A:A(int size):SIZE(size) . 对参数和函数的定义(const只能修饰输入参数,不能修饰输出参数) const int x=1; 表示x的值是1,在程序中不能改变; const int* x; 表示x代表的地址所指向的内容是不能改变得; int const* x; 与const int* x;的表示的意思一样; int * const x; 表示x代表的地址是不能改变的; 当是输入参数时,不需要是void Func(const int i),void Func(const int& i),可以是void Func(int i) 因为输入参数采用值传递(const int i),由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加const修饰; 不用const int& i的原因在于内部数据类型的参数不存在构造、析构的过程,而复制也非常快,值传递和引用传递的效率几乎相当. 当是输入参数时,不需要是void Func(const A a),void Func(A a),可以是void Func(A& a)或void Func(const A& a) 不用const A a,A a的原因是函数的效率比较低,因为函数体内将产生A类型的临时对象用于复制参数a,而临时对象的构造、复制和析构过程都需要消耗时间 最好用const A&a的原因是A&a中的a可以被改变,A&a和const A&a的好处在于都不会产生临时对象,效率高; const A Func(const A&a )const的好处 第一个const表示返回的是个内部产生的对象,它不能被修改 const A Func(.) . const A a=Func(.);/不能是A a=Func(.); 第二个const表示输入的参数是引用传递,函数内部不会产生临时对象,而且这个对象不能被内部修改 第三个const表示此函数内部的所涉及的数据成员不能修改 class Stack int m_num; int GetCount(void) const; int Pop(void); int Stack:GetCount(void) const m_num+;/编译错误,企图修改数据成员m_num; Pop();/编译错误,企图调用非const函数 3、文件拷贝的代码 #include int main(int argc, char* argv) printf(Hello World!n); FILE* in; FILE* out; in=fopen(d:1.txt,rb); out=fopen(d:2.txt,wb); char ch=fgetc(in); while(!feof(in) fputc(ch,out); ch=fgetc(in); fclose(in); fclose(out); return 0; 动态生成内存的代码 - 正确代码: void GetMemory(char *p, int num) *p = (char *)malloc(sizeof(char) * num); char* GetMemory2(int num) char* p = (char *)malloc(sizeof(char) * num); return p; - 错误的代码: void GetMemory3(char *p, int num) p = (char *)malloc(sizeof(char) * num); - void Test(void) char *str = NULL; GetMemory(&str, 100); / 注意参数是&str,而不是str strcpy(str, hello); cout str endl; free(str); str=NULL; str=GetMemory2(100); strcpy(str, hello); cout str endl; free(str); str=NULL; GetMemory3(str, 100); / str 仍然为NULL strcpy(str, hello); / 运行错误 cout str endl;/运行错误 free(str);/运行错误 strcpy代码 char* strcpy(char* strDest,const char* strSrc) if(strDest=NULL|strSrc=NULL) return NULL; char* pStr=strDest; while(*strDest+=*strSrc+)!=0) NULL; return pStr; 复合表达式 d = (a = b + c) + r ; 该表达式既求a 值又求d 值.应该拆分为两个独立的语句: a = b + c; d = a + r; if (a b c) / a b c 是数学表达式而不是程序表达式 并不表示 if (a b) & (b c) 而是成了令人费解的 if ( (a b) c ) memcpy代码 void* memcpy(char* strDest,const char* strSrc,size_t size) if(strDest=NULL|strSrc=NULL) return NULL; if(size 0) *strDest+=*strSrc+; return pStr; sizeof: i.在32位操作系统中,基本数据类型 类型 字节长度 char 1 short 2 short int 2 signed short 2 unsigned short 2 int 4 long int 4 signed int 4 unsigned int(unsigned) 4 long 4 unsigned long 4 float 4 double 8 void* 4 (所有指针类型长度都一样)(char*,int*,float*,double*) enum 4 ii.在32位操作系统中,定义或函数中的大小 char a=hello; char b100; char *p=a; 类型 字节长度 sizeof(a) 6 sizeof(b) 100 sizeof(p) 4 void Func(char a100) sizeof(a); /4 #pragma pack(1) struct A int i; char j; ; sizeof(A) /5 #pragma pack(1) struct A int o; int j; union int i10,j,k; ; ; sizeof(A) /48 #pragma pack(1) struct A enum daymonring, moon, aftermoon; ; sizeof(A) /1 sizeof(A:day) /44、函数参数传递 C+语言中,函数的参数和返回值的传递方式有三种:值传递、指针传递和引用传递. 值传递的示例程序.由于Func1 函数体内的x 是外部变量n 的一份拷贝, 改变x 的值不会影响n, 所以n 的值仍然是0. void Func1(int x) x = x + 10; int n = 0; Func1(n); cout n = n endl; / n = 0 指针传递的示例程序.由于Func2 函数体内的x 是指向外部变量n 的指 针,改变该指针的内容将导致n 的值改变,所以n 的值成为10. void Func2(int *x) (* x) = (* x) + 10; int n = 0; Func2(&n); cout n = n endl; / n = 10 引用传递的示例程序.由于Func3 函数体内的x 是外部变量n 的引用,x 和n 是同一个东西,改变x 等于改变n,所以n 的值成为10. void Func3(int &x) x = x + 10; int n = 0; Func3(n); cout n = n endl; / n = 10 内存分配方式 分配方式 变量类型 分配特点 静态存储区域分配 全局变量,static 变量 内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在. 栈分配 函数内局部变量 栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限. 堆分配(亦称动态内存分配) new ,malloc分配 用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存. 内存错误 内存分配未成功,却使用了它. 内存分配虽然成功,但是尚未初始化就引用它. 内存分配成功并且已经初始化,但操作越过了内存的边界. 例如在使用数组时经常发生下标多1或者少1的操作.特别是在for 循环语句中,循环次数很容易搞错,导致数组操作越界. 忘记了释放内存,造成内存泄露. 放了内存却继续使用它. 函数的return 语句写错了,注意不要返回指向栈内存的指针或者引用,因为该内存在函数体结束时被自动销毁. 程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面. 使用free 或delete 释放了内存后,没有将指针设置为NULL.导致产生野指针. malloc与new区别 malloc 与free 是C+/C 语言的标准库函数,new/delete 是C+的运算符.它们都可用于申请动态内存和释放内存. 对于非内部数据类型的对象而言,光用maloc/free 无法满足动态对象的要求.对象在创建的同时要自动执行构造函数, 对象在消亡之前要自动执行析构函数.由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free.因此C+语言需要一个能完成动态 内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete.注意new/delete 不是库函数. 5、类重载、隐藏与覆盖区别 成员函数被重载的特征: (1)相同的范围(在同一个类中); (2)函数名字相同; (3)参数不同; (4)virtual 关键字可有可无. 覆盖是指派生类函数覆盖基类函数,特征是: (1)不同的范围(分别位于派生类与基类); (2)函数名字相同; (3)参数相同; (4)基类函数必须有virtual 关键字. #include class Base public: void f(int x) cout Base:f(int) x endl; void f(float x) cout Base:f(float) x endl; virtual void g(void) cout Base:g(void) endl; void h(float x) cout Base:h(float) x endl; void k(float x) cout Base:k(float) x endl; ; class Derived : public Base public: virtual void g(void) cout Derived:g(void) endl; void h(int x) cout Derived:h(int) x endl; void k(float x) cout Derived:k(float) x f(42); / Base:f(int) 42 /重载 pb-f(3.14f); / Base:f(float) 3.14 /重载 pb-g(); / Derived:g(void) /覆盖 pd-g(); / Derived:g(void) /覆盖 pb-h(3.14f) / Base:h(float) 3.14 /隐藏 pd-h(3.14f) / Derived:h(int) 3 /隐藏 pb-k(3.14f) / Base:k(float) 3.14 /隐藏 pd-k(3.14f) / Derived:k(float) 3.14 /隐藏 extern问题 如果C+程序要调用已经被编译后的C 函数,该怎么办? 假设某个C 函数的声明如下: void foo(int x, int y); 该函数被C 编译器编译后在库中的名字为_foo,而C+编译器则会产生像_foo_int_int之类的名字用来支持函数重载和类型安全连接.由于编译后的名字不 同,C+程序不能直接调用C 函数.C+提供了一个C 连接交换指定符号externC来解决这个问题.例如: extern C void foo(int x, int y); / 其它函数 或者写成 extern C #include myheader.h / 其它C 头文件 这就告诉C+编译译器,函数foo 是个C 连接,应该到库中找名字_foo 而不是找_foo_int_int.C+编译器开发商已经对C 标准库的头文件作了externC处理,所以我们可以用include 直接引用这些头文件. 函数参数的缺省值问题 正确方法: void Foo(int x=0, int y=0); / 正确,缺省值出现在函数的声明中 void Foo(int x,int y) . 错误方法: void Foo(int x=0, int y=0) / 错误,缺省值出现在函数的定义体中 . 正确方法: void Foo(int x, int y=0, int z=0); 错误方法: void Foo(int x=0, int y, int z=0); 宏代码与内联函数区别 语言支持关系: C 宏代码 C+ 宏代码 内联函数 宏代码本身不是函数,但使用起来象函数.预处理器用复制宏代码的方式代替函数调用,省去了参数压栈、生成汇编语言的CALL调用、返回参数、执行 return 等过程,从而提高了速度.使用宏代码最大的缺点是容易出错,预处理器在复制宏代码时常常产生意想不到的边际效应. 对于任何内联函数,编译器在符号表里放入函数的声明(包括名字、参数类型、返回值类型).如果编译器没有发现内联函数存在错误,那么该函数的代码也被放入 符号表里.在调用一个内联函数时,编译器首先检查调用是否正确(进行类型安全检查,或者进行自动类型转换,当然对所有的函数都一样).如果正确,内联函数 的代码就会直接替换函数调用,于是省去了函数调用的开销.这个过程与预处理有显著的不同,因为预处理器不能进行类型安全检查,或者进行自动类型转换.假如 内联函数是成员函数,对象的地址(this)会被放在合适的地方,这也是预处理器办不到的. 内联函数使用方法: 关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用. 正确使用方法: void Foo(int x, int y); inline void Foo(int x, int y) / inline 与函数定义体放在一起 错误使用方法: inline void Foo(int x, int y); / inline 仅与函数声明放在一起 void Foo(int x, int y) 6、构造和析构的次序 构造从类层次的最根处开始,在每一层中,首先调用基类的构造函数,然后调用成员对象的构造函数.析构则严格按照与构造相反的次序执行,该次序是唯一的,否则编译器将无法自动执行析构过程. String函数定义 class String public: String(const char *str = NU
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- JJF 2312-2025FDR自动土壤水分观测仪校准规范
- 2025贵州台江县民族中医院第二次招聘备案制专业技术人员考前自测高频考点模拟试题完整答案详解
- 广清市质量安全培训课件
- 2025福建福州市鼓楼区拟任命人民陪审员模拟试卷及答案详解(名师系列)
- 安全培训教师介绍词简短课件
- 2025江苏泰州学院招聘专职辅导员和专任教师17人考前自测高频考点模拟试题及1套参考答案详解
- 2025年第十三届贵州人才博览会省委金融办所属事业单位人才引进1人模拟试卷及答案详解(名师系列)
- 2025年非金属矿物制品:耐火项目建议书
- 2025国网冀北电力有限公司第二批高校毕业生录用人选的模拟试卷及完整答案详解1套
- 2025江苏连云港市金灌投资发展集团有限公司、灌南城市发展集团有限公司等招聘34人模拟试卷及参考答案详解
- 植物的身体说课课件
- 2024年司法协理员招聘考试题库及答案
- 烧结工艺培训课件
- 公路局应急管理知识培训
- 质量保障方案文案(3篇)
- 1.4理解与感知1812序曲课件-高中音乐湘教版必修音乐鉴赏
- 产科分娩风险管理制度
- 洗车店卫生管理制度
- JG/T 375-2012金属屋面丙烯酸高弹防水涂料
- T/CCOA 62-2023大豆油生产技术规范
- 基础计算机知识常识试题及答案
评论
0/150
提交评论