类的大小
- 空类(不含成员变量和虚函数):因为对象不可能不占内存,否则这个对象怎么存在,所以C++规定空类对象内存大小为1。
class EC { public: EC(){} ~EC(){}; void EC1() { printf("EC1\n"); } }; class EVC { public: EVC(){} ~EVC(){}; void EVC1() { printf("EVC1\n"); } virtual void VEVC1() { printf("EVC1\n"); } }; int main(int argc, char*argv[]) { printf("%d\n", sizeof(EC)); printf("%d\n", sizeof(EVC)); }
输出结果:
1 4
- 虚类(包含虚函数的类):因为声明虚函数后,类需要管理虚函数,所以创建了虚函数指针,所以类的对象大小还要计算这个虚表指针的大小。
- 普通类:一般考虑像C的结构体那样即可(考虑数据对齐)。
函数调用方式
- _cdecl : C\C++的默认调用方式,函数调用负责管理函数调用堆栈,支持不定参数。
- _stdcall : WINAPI的调用方式,函数本身负责管理函数调用堆栈,不支持不定参数。
- _fastcall : 寄存器方式传参,函数本身负责管理函数调用堆栈,不支持不定参数,VC默认在参数个数小于等于3的情况下使用这种方式。
;--- e:\code\win32\dre\helloworld\main.cpp -------------------------------------- #include <stdio.h> int _cdecl Test(int a, int b) { 009E13A0 push ebp 009E13A1 mov ebp,esp 009E13A3 sub esp,0C0h 009E13A9 push ebx 009E13AA push esi 009E13AB push edi 009E13AC lea edi,[ebp-0C0h] 009E13B2 mov ecx,30h 009E13B7 mov eax,0CCCCCCCCh 009E13BC rep stos dword ptr es:[edi] return a+b; 009E13BE mov eax,dword ptr [a] 009E13C1 add eax,dword ptr [b] } 009E13C4 pop edi 009E13C5 pop esi 009E13C6 pop ebx 009E13C7 mov esp,ebp 009E13C9 pop ebp 009E13CA ret ;无平衡堆栈,这类调用方式不用处理函数堆栈帧 ;--- 无源文件 ----------------------------------------------------------------------- ;--- e:\code\win32\dre\helloworld\main.cpp -------------------------------------- int _stdcall Test1(int a, int b) { 009E13F0 push ebp 009E13F1 mov ebp,esp 009E13F3 sub esp,0C0h 009E13F9 push ebx 009E13FA push esi 009E13FB push edi 009E13FC lea edi,[ebp-0C0h] 009E1402 mov ecx,30h 009E1407 mov eax,0CCCCCCCCh 009E140C rep stos dword ptr es:[edi] return a+b; 009E140E mov eax,dword ptr [a] 009E1411 add eax,dword ptr [b] } 009E1414 pop edi 009E1415 pop esi 009E1416 pop ebx 009E1417 mov esp,ebp 009E1419 pop ebp 009E141A ret 8 ;平衡堆栈,这类调用方式需要处理函数堆栈帧 ;--- 无源文件 ----------------------------------------------------------------------- ;main ;{ Test(1,2); 009E145E push 2 009E1460 push 1 009E1462 call Test (9E100Ah) 009E1467 add esp,8 ;平衡堆栈,调用者需要处理函数堆栈帧 Test1(1,2); 009E146A push 2 009E146C push 1 009E146E call Test1 (9E107Dh) ;无平衡堆栈,被调用者已处理函数堆栈帧 ;}
静态局部变量初始化
问:C\C++中如何实现静态变量多次调用但是只初始化一次 呢?
答:一定有方法的,编程语言能搞定他的!
问:到底是啥呢?
答:....
其实,如果不是看到相关的问题或者资料,这个问题想得人还真不多。其实这个问题实现的方法也简单,弄一个东西记录该静态变量是否初始化即可,编译器的一般做法是选取该变量附近的一个字节来记录该静态变量是否初始化了,但是因为记录该状态只需要一个Bit即可,而一字节有8Bit,所以这个字节可以被其他静态变量共享使用的。
static int nSa = a; 000C143E mov eax,dword ptr [$S1 (0C713Ch)] ; ===========BEG============== 000C1443 and eax,1 000C1446 jne TestStaticVar+3Dh (0C145Dh) 000C1448 mov eax,dword ptr [$S1 (0C713Ch)] 000C144D or eax,1 ; ===========END============== 000C1450 mov dword ptr [$S1 (0C713Ch)],eax 000C1455 mov eax,dword ptr [a] 000C1458 mov dword ptr [nSa (0C7138h)],eaxBEG到END部分的代码就是用来判断该静态变量是否已经初始化了的,此处用的是该字节的最低一个BIT
C++备忘录
时间: 2024-09-30 11:07:44