看书时的总结,时不时提醒自己
1.switch~case:case只是起到匹配符号作用,并不能起到判断作用,一旦switch(i)与case i 匹配就开始行,一直执行到有break语句,如果没有的话一直执行到最后,前面不匹配的不能开始执行,只能从开始的地方开始执行,defualt不能起到break语句的作用
2.ASCALL码 0~9:48~57 A~Z: 65~90 a~z:97~122
3.如果一个模块访问另一个模块的内部数据,修改另一个模块的内部数据,就发生了内容耦合,并不是数据耦合,数据耦合是一个模块访问另一个模块时,彼此之间只是通过简单的数据参数来进行数据的输入输出
4.堆与栈的区别:
1).管理方式不同,栈是有编译器分配,包括局部变量,函数变量等,堆是由程序员自己分配,使用new/malloc函数,
2).增长方向不同:栈是往地址减的方向增,堆是往地址高的地方增
3).空间大小不同:栈一般是2M,堆的大小与虚拟内存有关
4).分配方式不同: 堆是动态分配,栈是静态分配,就是编译器分配
在函数调用的时候,第一个进栈的是该函数的下一条指令的地址,下一个进栈的是参数,从右到左,接着是函数的参数,函数执行完后反向出栈。
5.new与malloc的区别:new的调用会调用类的构造函数,delete会调用析构函数,malloc只是个函数而free不会调用析构函数
6.全局变量与静态变量都是编译器编译是就分配内存,初始化的两种变量放在一块区域里,没有初始化的会放在相邻的两个区域里
7.printf("%d,%d",*p,*(++p));printf函数是从右往左压进栈的,所以先算*(++p),然后压入栈,后算*p,所以算出的两个数是相等的
8.(int &)a是把a的地址化成十进制,&a是求a的地址
9.大端小端模式:内存地址是从低往高的方向增长,小端模式是从小的开始存(eg:0x1234,小的部分是ox34,大的部分是0x12,小端模式就是先存0x34然后就是0x12,如果地址是0x12~0x13,即&(0x12)==0x34)
10.往一个地址写入数据,如0x1234写入78:*((unsignedint *)0x1234)=78;如 int a=0xfff7;
*(int *)&a就等于0xfff7;&a为一个指针
11.内存对齐:按照定义的顺序下来,以最大的数为标准(int ,short,long,则以int为标准,以为一般long都与int相等,为4,short为2还有如果是short与char,则以short为标准,就是以2字节对齐),如果对齐的字节个数够存数则继续存,不够存的话就以对齐的方式从新开始。(char a;int b;char c;short d;该数以4字节对齐,先存a一个字节,地址为0x0000,因为int为4字节,已经超出了剩下的3个字节,所以要以对齐的方式从新开始存,就是从地址0x0004开始存,存到0x0007;下一个存c,从地址0x0008开始存一个字节,最后是d,从地址0x0009~0x000A存,如果要sizeof(该结构体)=12)
12.const作用:定义常量,修饰函数参数,修饰函数的返回类型,还可以修饰函数的定义体;凡是被const修饰过的东西都防止被修改
13.#define 只是给变量起一个新的名字,const与define都可以定义常量,但是const定义,编译器编译时对会变量进行类型检查,但是define只是简单的字符替换。define定义是没有表明类型,const必须表明类型;c++中的const是内连接,C中的是外连接,c++要做C 的事情,必须改成extern const
变量名
14.构造函数析构函数都不占用内存,静态成员也不占,空类占1个字节,多继承的空类也是1个字节,继承虚类就4个字节,因为有虚指针,类中的所有虚函数共占4个字节,函数不占用字节(void max(int a)=0 )
15.int *p="abcdef";sizeof(p)=4;指针都是4,这里定义的是个指针,如果是int p[]="abcdef";sizeof(p)=7,注意要把'\0'算进去,但是strlen(p)就等于6因为是到'\0‘就结束了,strlen(char*)类型,必须到’\0'结束
16.函数体是否把值转换,函数传进来的是形参,拷贝一份进入函数体执行,执行完就会自动把该拷贝撤销,要把值相调换,必须改变形参调进来的地址所指向的内容,也就是改变内容1)即使在函数体内指针指向改变了,但是内容还是没有改变,函数撤销之后还是没有变2)只是简单传进两个int 型数,函数体内改变,运行完还是会撤销3)int *temp;*temp=4;这种写法错误,因为temp没有分配内存,无法指向
17.char*p="abcd";cout<<p///输出abcd;cout<<*p/输出a;;;;;;;;;;;;int a[3]={0,1,2};int *p=a;int*q=&a[2];cout<<a[q-p]<<endl;输出2,因为q-p是算(q-p)/sizeof(int)=2,字符串的首地址输出的就是整个字符,数组的首地址输出的就是该数组的第一个数
18.int(*A)[3]是数组指针,就是指向数组的指针,A相当与一个二级指针,(*A)[0]相当于一个二位数组的第一个数;;;;;int *A[3],是指针数组
存放指针的数组。int a[]={1,2,3,4,5};int *p=(int*)&a+1,则p是二维的指针,相当于二维数组,指向a的第六个数,虽然没有
19.int *p;*p=2;这两句话会导致程序崩溃,因为p指针指向的地址无法给定,即指向了不明地址,然后再赋值就导致程序崩溃;但是
int *p=new int;*p=2;这样就可以;迷途指针与空指针:迷途指针是申请了内存,然后delete后接着有使用该指针,这样相当于一个定时炸弹,会导致程序崩溃,空指针就没有所谓,所以一般delete后要把该指针等于NULL,且不要使用
20.new/delete与malloc/free区别:new/delete是运算符, malloc/free是函数,运算符会在编译器编译的时候自动识别,当对象创建和撤销时会导致相应的构造函数与析构函数作用,而函数就不会,所以C++用new /delete
21.memcpy复制的长度是根据最后一个数决定的,mencpy(p,q,20),无论q是否有20个字符,还是要复制20个为止,如果q带'\0'即结束符是21个,那么p复制到的也只能是20个字符,最后结束符无法复制,p最后要自己添加结束符,要不字符不知道读到哪里结束
22.深拷贝与浅拷贝:深拷贝是重写拷贝构造函数,浅拷贝是采取默认的构造函数,拷贝是指用相同的意思,但当有动态的内存分配是需要深拷贝,因为调用析构函数的原因,如果不重新给内存析构函数会两次delete该处,出现错误http://blog.csdn.net/bluescorpio/article/details/4322682,什么时候用到拷贝构造函数:当用对象赋值时,当函数的参数是对象是,当返回值是对象时,什么时候需要重写拷贝构造函数?当析构函数要释放的是动态内存时
23.初始化类成员变量时是按照申明的顺序的,如private :int a_y;int a_x; Rose(int x,int y):a_x(y),a_y(a_x){},因为先定义a_y,所以要先实现a_y的赋值,然后再实现a_x的,原来是想使两个数相等,但现在a_y是先赋值,得到一个不知道什么值的值,然后a_x是付一个y;要想得到相同的结果就应该调换为 private:int a_x;int a_y ...................
const int a=3;这种常量应该在构造函数里定义,或者有static表明,变成static const int a=3;
24.析构函数定义为virtual防止没有释放申请内存的其他子类的析构函数,virtual的父类的析构函数会使其他的子类的析构函数都会执行
25.static有什么作用:
1)函数体:函数体内static的变量的作用范围只属于该函数体,而且只分配一次内存,因此其值是援用上次的值,auto定义的话就自动变成等号后面的数 (static int a=3;auto intb=3;a+=2;b+=1;)每次调用这个函数的时候a就自动援用上面的保留下来的值,b就每次都变成3
2)类:类中的static成员只属于该类,对类的对象只是一份拷贝。static的函数只能调用static成员
3)模块:模块内定义的static成员只能供该模块内的所有函数访问,别的模块不能访问
26.const:
int b=100;
1) int*const a=&b;定义一个常量指针,就是指针不可变,值可变
intconst*a=&b;与上面的相同
2)const int *a=&b;定义一个常量,指针可变,内容不可变
3)const int *const a=&b;指针与内容都是常量
用const定义的函数表示,函数的成员不允许对数据成员进行修改,修改编译器就出错,不要轻易
把函数定义成const类型