C和C++语言学习总结.docx

上传人:b****5 文档编号:29476643 上传时间:2023-07-23 格式:DOCX 页数:16 大小:21.96KB
下载 相关 举报
C和C++语言学习总结.docx_第1页
第1页 / 共16页
C和C++语言学习总结.docx_第2页
第2页 / 共16页
C和C++语言学习总结.docx_第3页
第3页 / 共16页
C和C++语言学习总结.docx_第4页
第4页 / 共16页
C和C++语言学习总结.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

C和C++语言学习总结.docx

《C和C++语言学习总结.docx》由会员分享,可在线阅读,更多相关《C和C++语言学习总结.docx(16页珍藏版)》请在冰豆网上搜索。

C和C++语言学习总结.docx

C和C++语言学习总结

C和C++语言学习总结(资料来自<高质量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:

boolintfloatpointerchar变量的使用方法

bool bParam;

int iParam;

floatfParam;

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);

{

 returnx;

}

else

{

 returny;

}

for:

执行效率问题:

introw,col,sum;

inta[100][5];

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+a[row][col];          sum=sum+a[row][col];

 }                     }

}                    }

inti;

for(i=0;i

{                    {

  if(condition)              for(i=0;i

   DoSomething();              DoSomething();

  else                 }

   DoOtherthing();          else

}                    {

                      for(i=0;i

                        DoOtherthing();

                     }

for(intx=0;x<=N-1;x++) 直观性差于  for(intx=0;x

switch:

switch(variable)

{

  casevalue1:

...

        break;

  casevalue2:

...

        break;

  default:

  ...

        break;

}

switch(c)中的c的数据类型可以是int,char,long,unsignedint,bool.

variable必须是整数或者强制为整数,由于char实际上是ASCII码,所以也可以.

c不可以是double,float,char*.

goto:

goto主要用于

{...

 {...

   {....

    gotoerror;

   }

 }

}

error:

  ...

2、#define,const

#define和const区别

1、#defineC语言

 const C语言C++语言

 const常量有数据类型,编译器会进行类型安全检查,而#define没有数据类型,

 const的常量可以进行调试,但宏常量不能进行调试.

2、const的使用方法

在全局定义constfloatPI=3.1415926

在类中定义

classA

{...

  A(intsize);

  constintSIZE;

};

A:

:

A(intsize):

SIZE(size)

{

 ...

}

对参数和函数的定义(const只能修饰输入参数,不能修饰输出参数)

constintx=1; 表示x的值是1,在程序中不能改变;

constint*x; 表示x代表的地址所指向的内容是不能改变得;

intconst*x; 与constint*x;的表示的意思一样;

int*constx; 表示x代表的地址是不能改变的;

当是输入参数时,不需要是voidFunc(constinti),voidFunc(constint&i),可以是voidFunc(inti)

因为输入参数采用"值传递"(constinti),由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加const修饰;

不用constint&i的原因在于内部数据类型的参数不存在构造、析构的过程,而复制也非常快,"值传递"和"引用传递"的效率几乎相当.

当是输入参数时,不需要是voidFunc(constAa),voidFunc(Aa),可以是voidFunc(A&a)或voidFunc(constA&a)

不用constAa,Aa的原因是函数的效率比较低,因为函数体内将产生A类型的临时对象用于复制参数a,而临时对象的构造、复制和析构过程都需要消耗时间

最好用constA&a的原因是A&a中的a可以被改变,A&a和constA&a的好处在于都不会产生临时对象,效率高;

constAFunc(constA&a)const的好处

第一个const表示返回的是个内部产生的对象,它不能被修改

constAFunc(...)

{...}

constAa=Func(...);//不能是Aa=Func(...);

第二个const表示输入的参数是引用传递,函数内部不会产生临时对象,而且这个对象不能被内部修改

第三个const表示此函数内部的所涉及的数据成员不能修改

classStack

{

 intm_num;

 intGetCount(void)const;

 intPop(void);

}

intStack:

:

GetCount(void)const

{

 m_num++;//编译错误,企图修改数据成员m_num;

 Pop();//编译错误,企图调用非const函数

}

3、文件拷贝的代码

#include

intmain(intargc,char*argv[])

{

printf("HelloWorld!

\n");

FILE*in;

FILE*out;

in=fopen("d:

\\1.txt","rb");

out=fopen("d:

\\2.txt","wb");

charch=fgetc(in);

while(!

feof(in))

{

 fputc(ch,out);

 ch=fgetc(in);

}

fclose(in);

fclose(out);

return0;

}

动态生成内存的代码

------------------------------------------

正确代码:

voidGetMemory(char**p,intnum)

{

 *p=(char*)malloc(sizeof(char)*num);

}

char*GetMemory2(intnum)

{

 char*p=(char*)malloc(sizeof(char)*num);

 returnp;

}

------------------------------------------

错误的代码:

voidGetMemory3(char*p,intnum)

{

 p=(char*)malloc(sizeof(char)*num);

}

------------------------------------------

voidTest(void)

{

 char*str=NULL;

 GetMemory(&str,100);//注意参数是&str,而不是str

 strcpy(str,"hello");

 cout<

 free(str);

 str=NULL;

 str=GetMemory2(100);

 strcpy(str,"hello");

 cout<

 free(str);

 str=NULL;

 GetMemory3(str,100);//str仍然为NULL

 strcpy(str,"hello");//运行错误

 cout<

 free(str);//运行错误

}

strcpy代码

char*strcpy(char*strDest,constchar*strSrc)

{

  if(strDest==NULL||strSrc==NULL)returnNULL;

  char*pStr=strDest;

  while((*strDest++=*strSrc++)!

='\0)

     NULL;

  returnpStr; 

}

复合表达式

d=(a=b+c)+r;

该表达式既求a值又求d值.应该拆分为两个独立的语句:

a=b+c;

d=a+r;

if(a

并不表示

if((a

而是成了令人费解的

if((a

memcpy代码

void*memcpy(char*strDest,constchar*strSrc,size_tsize)

{

  if(strDest==NULL||strSrc==NULL)returnNULL;

  if(size<=0)returnNULL;  

  char*pStr=strDest;

  while(size-->0)

    *strDest++=*strSrc++;

  returnpStr;  

}

sizeof:

i.在32位操作系统中,基本数据类型

类型         字节长度

char          1

short          2

short  int      2

signedshort      2

unsignedshort     2

int           4

long  int      4

signed int      4

unsignedint(unsigned) 4

long          4

unsignedlong      4

float          4

double         8

void*          4(所有指针类型长度都一样)(char*,int*,float*,double*)

enum          4

ii.在32位操作系统中,定义或函数中的大小

chara[]="hello";

charb[100];

char*p=a;

类型         字节长度

sizeof(a)        6

sizeof(b)        100

sizeof(p)        4

voidFunc(chara[100])

{

  sizeof(a);    //4

}

#pragmapack

(1)

structA

{

  inti;

  charj;

};

sizeof(A)       //5

#pragmapack

(1)

structA

{

into;

intj;

union

{

inti[10],j,k;

};

};

sizeof(A)       //48

#pragmapack

(1)

structA

{

  enum day{monring, moon, aftermoon}; 

};

sizeof(A)       //1

sizeof(A:

:

day)    //4

4、函数参数传递

C++语言中,函数的参数和返回值的传递方式有三种:

值传递、指针传递和引用传递.

"值传递"的示例程序.由于Func1函数体内的x是外部变量n的一份拷贝,

改变x的值不会影响n,所以n的值仍然是0.

voidFunc1(intx)

{

x=x+10;

}

intn=0;

Func1(n);

cout<<"n="<

"指针传递"的示例程序.由于Func2函数体内的x是指向外部变量n的指

针,改变该指针的内容将导致n的值改变,所以n的值成为10.

voidFunc2(int*x)

{

(*x)=(*x)+10;

}

intn=0;

Func2(&n);

cout<<"n="<

"引用传递"的示例程序.由于Func3函数体内的x是外部变量n的引用,x

和n是同一个东西,改变x等于改变n,所以n的值成为10.

voidFunc3(int&x)

{

x=x+10;

}

intn=0;

Func3(n);

cout<<"n="<

内存分配方式

分配方式          变量类型        分配特点

静态存储区域分配      全局变量,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

classBase

{

public:

     voidf(intx) {cout<<"Base:

:

f(int)"<

     voidf(floatx){cout<<"Base:

:

f(float)"<

 virtualvoidg(void)  {cout<<"Base:

:

g(void)"<

     voidh(floatx){cout<<"Base:

:

h(float)"<

     voidk(floatx){cout<<"Base:

:

k(float)"<

};

classDerived:

publicBase

{

public:

 virtualvoidg(void)  {cout<<"Derived:

:

g(void)"<

     voidh(intx) {cout<<"Derived:

:

h(int)"<

     voidk(floatx){cout<<"Derived:

:

k(float)"<

};

voidmain(void)

{

 Derivedd;

 Base*pb=&d;

 Derived*pd=&d;

 pb->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函数的声明如下:

voidfoo(intx,inty);

该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字用来支持函数重载和类型安全连接.由于编译后的名字不同,C++程序不能直接调用C函数.C++提供了一个C连接交换指定符号extern"C"来解决这个问题.例如:

extern"C"

{

voidfoo(intx,inty);

…//其它函数

}

或者写成

extern

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 学科竞赛

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1