C\C++小知识汇总

来源:互联网 发布:淘宝子账号售后权限 编辑:程序博客网 时间:2024/06/08 05:39

类的大小

  • 空类(不含成员变量和虚函数):因为对象不可能不占内存,否则这个对象怎么存在,所以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));}

    输出结果:
    14

  • 虚类(包含虚函数的类):因为声明虚函数后,类需要管理虚函数,所以创建了虚函数指针,所以类的对象大小还要计算这个虚表指针的大小。
  • 普通类:一般考虑像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)],eax  
BEG到END部分的代码就是用来判断该静态变量是否已经初始化了的,此处用的是该字节的最低一个BIT

内存对齐

所谓内存对齐,就是为了方便系统寻址,高效地处理数据,它要求成员变量的地址n字节对齐,n字节边界对齐的意思是说,一个成员的地址必须安排在成员的尺寸的整数倍地址上或者是n的整数倍地址上,取它们中的最小值,也就是:min ( sizeof ( member ),  n)。n的值可由对齐预处理指令#pragma pack(n)指定,也可根据结构体内最大的基本数据类型的大小确定。

struct __t1{chara;intb;shortc;};sizeof(struct __t1) = 4+4+4 = 12;


调用函数获取数组大小信息

一般而言,如果需要把数组以参数的形式传给其他函数的时候是需要传入数组的长度的,因为被传入的函数比较难(或者说我们不知道)获取数组的长度。但是,实际上我们是可以通过技术手段在被传入的函数里面获取数组的大小的,而不需要额外传入数组的长度。实现的函数如下所示:

template <typename T, int N>void ShowArrayInfo(T (&ppArray)[N]){    printf("size = %ld\n", sizeof(ppArray));    printf("length = %d\n", N);}
调用的地方很简单,和往常的方法一致的,比如:
long c[13] = {0};ShowArrayInfo(c);

0 0
原创粉丝点击