c和c++的知识总结

c中的print计算参数的时候是右往左压栈的


==判断一般将常量放在左边,因为如果写成了=号,编译器会识别出来


所有的指针都是4字节


c++语言支持函数重载,c不支持函数重载,函数被c++编译后在库中的名字与c语言不同.c++提供c连接交换制定符号extern "C"解决名字匹配问题.


用宏的时候要小心,懂得使用括号


const修饰指针一般分为4种情况:
1.const int* a;这种情况const在*的左侧,那么指针所指向的为常量.
2.int const *a;跟上面一样
3.int* const a;指针本身是常量,这种情况不能对指针本身进行修改操作.故定义时必须初始化.
4.const int* const a;情况是上面结合.


const成员函数的使用,成员函数一些是不改变类的数据成员,一些是要改变数据成员的值,如果把不改变的都加上const显然可以提高可读性和可靠性.用法如下:
int Gety() const;
如果想在const函数里面修改数据成员,则必须让该数据成员前面加关键字mutable.
如果把const 放在函数前,则说明返回值是常量.


一个const变量是不能随意转换成非const变量.


const和define的区别:
const有数据类型而define没有,前者可以进行类型安全检查而后者没有.在c++中只使用const不用define


当结构体内的元素的长度都小于处理器的位数时,便以结构体里面最长的数据元素为对齐单位,也就是说,结构体的长度一定是最长的数据元素的整数倍.
反之则用处理机的位数为对齐单位.若要禁止对齐可以用pack指令:#pragma pack()


静态变量是存放在全局数据区的,sizeof计算栈中分配的大小.


sizeof和strlen的区别
sizeof的类型是unsigned int
sizeof是运算符,strlen是函数
sizeof可以用类型做参数,strlen只能用char*做参数而且必须以\0结尾.


sizeof()括号中的内容是不会被编译的,而是被类型代替,如sizeof(a=6),a=6并不会执行
对函数使用sizeof(),在编译阶段会被返回值所代替.
sizeof(string)==4,因为其内部实现是指针动态分配内存,故大小为一个指针大小4.


空类所占的空间为1,单一继承的空类空间也为1,多重继承的空类空间还是1.但是虚继承涉及虚表(虚指针)所以大小为4


内联函数与宏的区别:
内联函数比普通函数要快,因为不需要中断调用,在编译的时候内联函数直接镶嵌到目标代码当中,而宏只是简单的替换.
内联函数要做参数类型检查,这是内联函数跟宏相比的优势.
inline是镶嵌代码,在调用函数的地方不是跳转,而是把代码直接写到那里去,这样消耗了更多空间换来了效率提高.
inline一般用于:
1.一个函数不断地被重复调用.
2.函数只有几行,不包含for while switch语句.
inline必须与函数定义体放在一起才能成为内联.
若函数的执行的效率太低,其大部分时间都在实现函数代码上,那么这时候就不要用inline了,如果函数的开销大部分在调用上,那么使用inline是个很好的选择.
类的构造和析构函数不一定使用内联比较好,要看是否调用了基类的构造函数.


指针和引用的区别:
1.非空区别.指针可以为空,引用不能为空.
2.合法性区别,引用在使用前不需要检测,而指针经常被检测是否为空.
3.可修改区别,指针与引用的另一个重要的区别是指针可以被重复赋值以指向另一个不同的对象.
4.应用区别,如需要指向空对象或者需要在不同时刻指向不同的对象则使用指针,否则应该使用引用.


函数指针:void (*f)()
函数返回指针:void *f()
const指针:const int*
指向const的指针:int* const
指向const的const指针:const int* const


函数指针的用法如下:
int max(int,int);
int (*p)(int,int)=&max;
(*p)(a,b);


指针数组:*p[10]
数组指针:(*p)[10]


迷途指针的产生是指针delete后没有设置为空.


malloc/free和new/delete的区别:
malloc和free是标准库函数,new/delete是c++的运算符.他们都可以用于申请动态内存和释放内存.
对于非内部对象而言,你在创建的时候需要调用构造函数,消亡时需要调用析构函数,故产生了new和delete函数


句柄和指针的区别和联系:
句柄用来标记系统资源,隐藏系统信息,是32位的,而指针是标记某个物理内存地址.


auto_ptr是安全指针,它是一个模板类,用法:
auto_ptr<T> pt(new T)
auto_ptr不能拷贝,拷贝后原来那份会被删除.


关于this指针:
1.this指针本质是一个函数参数,只是编译器隐藏了起来.this只能在成员函数中使用.
2.this在成员函数的开始前构造,结束后删除.
3.this指针并不占用对象空间.


map和set底层实现都是红黑树,因为红黑树插入和删除时旋转最多只需要3次,比起其他的平衡树来说更便于统计.比起hash的优势是有序而且更省空间,复杂度更稳定


面向对象的三大原则:封装 继承 多态.


多态是一个接口多种方法,c++通过虚函数来实现多态.


对于一个空类,编译器默认生成构造 析构 拷贝 赋值函数


struct和class是一样的,只是struct默认访问是public而class默认是private


静态成员函数可以只能访问静态成员.


const标识的常量必须在构造函数里面初始化.或者设置为static.


析构函数若有派生类的情况必须声明是virtual.构造函数不能为virtuali.


构造函数冒泡后面的是成员变量初始化列表.


RAND_MAX是随机数能取的最大值.


dynamic_cast将一个基类对象指针(或引用)cast到继承类指针,dynamic_cast会根据基类指针是否真正指向继承类指针来做相应处


static_cast相当于c的强制类型转换


union里的所有数据都是同一个地址.可以用来测试内存存储方式是大端还是小端.


在C语言中,static关键字至少有下列几个作用:
函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分
配一次,因此其值在下次调用时仍维持上次的值。
在模块内的static全局变量可以被模块内所有函数访问,但不能被模块外其他函数访
问。
在模块内的static函数只可被这一模块内的其他函数调用,这个函数的使用范围被限
制在声明它的模块内。
在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝。
在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问
类的static成员变量。


栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等。
其操作方式类似于数据结构中的栈。
堆区(heap):一般由程序员分配和释放,若程序员不释放,程序节束时可能由操
作系统回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的
全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一
块区域。程序节束后由系统释放。
文字常量区:常量字符串就是放在这里的。程序节束后由系统释放。
程序代码区:存放函数体的二进制代码。

进程虚拟内存分布从低到高是这样的: text代码段——data数据段——bss段——heap——memory map——stack

内核在最高的地址。

堆和栈的区别:

从内存分布上讲,堆从低地址向高地址扩展,栈从高地址向低地址扩展。

从分配效率上讲,堆的分配效率较低,但是可控,栈的分配效率较高,但是不可控。

从空间大小上讲,栈的空间比较小,堆的空间比较大。

排序的稳定性指的是排序前的系列存在a[i]==a[j]且i<j,那么如果排序后他们的相对次序不变证明是稳定的.

c的编译过程:

预处理:替换掉带#的东西,如#include,#define

编译:C源码翻译成汇编

汇编:汇编翻译成机器代码

链接:符号解析和重定位,将程序每一个全局变量和全局函数的引用和符号表里的一个符号对应起来,重定位确定每一个模板模块的全局变量和函数在可执行文件内存空间的位置

重载重写和重定义:

重载是指函数名一样但是返回值或参数不一样,发生在同一个作用域。

重写是指派生类覆盖基类的方法,要求返回值参数函数名完全一样,且是虚函数。

重定义是指派生类通过定义一个与父类同名的函数进行对父类函数的隐藏。返回值和参数可以不一样但必须同名。

左值和右值:

左值可以简单理解为有变量名,有地址的值。其他的例如临时变量都是右值。

STL六大组件:stl有容器,空间配置器,适配器,迭代器,仿函数以及算法这6个组件,它们六者关系大概如下:容器通过配置器取得数据存储空间,算法通过迭代器获取容器内容,仿函数可以协助算法完成不同的策略变化,配接器可以修饰或套界仿函数。

空间配置器分配:大于128byte直接malloc,小于128byte则申请8byte倍数的空间.8bytes的原因是为了提高效率,同时对于64位的机器而言,地址大小为8bytes

cdecl调用者清除堆栈,stdcall被调用者清除堆栈。

RTTI:即运行时用基类的指针引用派生类对象,它提供两种操作符,typeid操作符,dynamic_cast操作符,typeid检测对象类型,dynamic_cast用于基类和派生类之间的类型转换。

猜你喜欢

转载自blog.csdn.net/qq_34262582/article/details/79595754