类内存布局与虚函数表
类内存布局 + 虚函数表
sizeof(C)的数值是()
12345678910class C{public: char a; static char b; void *p; static int *c; virtual void func1(); virtual void func2();};
类的内存布局:
类中static修饰的变量不占用类大小,因为修饰后存储在静态区域。
sizeof是用来计算栈大小,不涉及全局区,故类的静态成员大小sizeof不涉及。
对于new或malloc开辟的区域,sizeof计算的也只能是其指针的大小,无法得到开辟的内存大小!
类与结构一样,都有字节对齐的问题。
含有虚函数的类中,类起始地址会放置一个指向虚函数表的指针,也占类的内存。
类中的枚举也不会占用内存。
结构体对齐
结构体对齐
在上下文及头文件均正常的情况下,以下代码打印的结果是(假设运行在 64 位计算机上):
12345678struct st_t { int status; short *pdata; char errstr[32]; };st_t st[16];char *p = (char *)(st[2].errstr + 32);printf("%d", (p - (char *)(st)));
A. 32 B. 120 C. 114 D. 144
结构体对齐:
内部对齐:结构体成员之间会留有空隙。
外部对齐:在结构体数组中,结构体之间也可能留有空隙。
对齐规则:
1.第一个成员在与结构体变量偏移量为0的地址
2.其他成员变量要对齐到对齐数的整数倍的地址处(对齐数 = 编译器默认的对齐数(VS中为8) 与 成员变量大小的较小值),即 内部对齐 。
3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数,取所以成员变量中对齐数最大的)的整数倍,即外部对齐
4. 如果嵌套结构体,嵌套的结构体对齐到自己的最大对齐 ...
模板的继承
模板的继承
下面有关函数模板和类模板的说法正确的有?
A. 函数模板的实例化是由编译程序在处理函数调用时自动完成的
B. 类模板的实例化必须由程序员在程序中显式地指定
C. 函数模板的模板参数仅针对参数类型
D. 类模板的模板参数仅针对数据成员和成员函数类型
C: 函数模版还可以将 函数返回值类型 作为模版参数。
D: 类模板还可以针对 继承的基类类型 作为模板参数
类模板和类模板之间、类模板和类之间可以互相继承。它们之间的派生关系有以下四种情况:
类模板继承类模板
类模板继承模板类
类模板继承普通类
普通类继承模板类
123456789101112131415161718192021222324252627282930313233343536373839//==============================================1、类模板继承类模板template <typename T1, typename T2>class A{ T1 x; T2 y;};template <typename T1, t ...
虚函数+内联
虚函数 inline
关于虚函数的说法,哪些是正确的( )
A. 构造函数中调用该类的虚函数,动态绑定机制会生效
B. 静态函数不可以是虚函数
C. 虚函数可以声明为inline
D. 构造函数和析构函数都可以声明为虚函数
函数绑定: 找到函数名对应的地址,然后将函数调用处用该地址替换,这称为函数绑定。
静态绑定: 在编译期间(包括链接期间)就能找到函数名对应的地址,完成函数的绑定,程序运行后直接使用这个地址即可。
动态绑定: 编译期间想尽所有办法都不能确定使用哪个函数,必须要等到程序运行后根据具体的环境或者用户操作才能决定。
构造函数中调用虚函数问题:
在构造或析构函数中调用虚函数会执行与之所属类型相对应的虚函数版本。
所以当构造函数中有虚函数时,编译期间就可以确定此虚函数为本类中的函数,不需要再动态绑定。
虚函数内联问题:
虚函数可以是内联函数,但是当虚函数表现多态性的时候不能内联
理由如下:内联是在发生在编译期间,编译器会自主选择内联,而虚函数的多态性在运行期,编译器无法知道运行期调用哪个代码,因此虚函数表现为多态性时(运行期)不可以内联。 inline virtual ...
转型+继承链
2. 转型 + 继承链
有如下代码:
1234567891011121314151617181920212223class A{protected: virtual show(){}};class B : public A{protected: virtual show(){}};class C : public B{protected: virtual show(){}}int main(){ A* p1 = new C; B* p2 = dynamic_cast<B*>(p1); //L1 A* p3 = new A; B* p2 = dynamic_cast<B*>(p3); //L2 return 0;}
A. L 1语句编译失败,L 2语句编译通过 B. L1语句编译通过,L2语句编译失败 C. L 1,L 2都编译失败 D. L 1,L 2都编译通过
四种类型转换 ...
构造函数&虚函数
以下程序输出结果是____
123456789101112131415161718192021class A{ public: A ():m_iVal(0){test();} virtual void func() { std::cout<<m_iVal<<' ';} void test(){func();} public: int m_iVal;};class B : public A{ public: B(){test();} virtual void func(){ ++m_iVal; std::cout << m_iVal << ' '; }};int main(int argc ,char* argv[]){ A*p = new B; p->test(); ...
可变长参数列表
可变长参数列表
该段代码输出()
1234567int main(){ int arr[]={1,2,3,4,5,6,7}; int *p=arr; printf("%d,%d\n",*p,*(++p)); return 0;}
A. 3,3 B. 2,2 C. 2,3 D. 3,2
参数入栈顺序:
通常情况下c/c++默认入栈方式为__cdecl。
关键字
堆栈清理
参数传递
__cdecl
Caller
以相反的顺序(从右到左)将参数压入堆栈
__clrcall
n/a
按顺序(从左到右)将参数加载到 CLR 表达式堆栈
__stdcall
Callee
以相反的顺序(从右到左)将参数压入堆栈
__fastcall
Callee
存储在寄存器中,然后压入堆栈
__thiscall
Callee
压入堆栈;此指针存储在 ECX 中
__vectorcall
Callee
存储在寄存器中,然后以相反的顺序(从右到左)压入堆栈
为什么要从右往左入栈? 因为 ...
memcpy与memmove的区别
memcpy与memmove的区别
这两个函数都是将s2指向位置的n字节数据拷贝到s1指向的位置。memcpy 假定两块内存区域没有数据重叠,而 memmove 没有这个前提条件。如果复制的两个区域存在重叠时使用memcpy,其结果是不可预知的( 未定义的 ),有可能成功也有可能失败。原因如下:
当src地址大于dest地址时,即使有重叠,也可以正常复制。
当src地址小于dest地址时,若重叠,则复制发生异常。
这种情况下,src的地址小于dest的地址,拷贝前3个字节没问题,但是拷贝第4,5个字节时,原有的内容已经被src拷贝过来的字符覆盖了,所以已经丢失原来src的内容。
然而,vs2019下进行试验,发现即使是在第二种情况下,memcpy与memmove的结果相同,都正确,原因可能是 memcpy 目前也采用了 memmove 的方式。
memmove的实现:
123456789101112void *memmove(void *dest, const void *src, size_t n){ unsigned char *pd = de ...
二叉排序树的操作
直接上代码,有简单注释:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157#include<iostream>#include<array>#define DataType intusing namespace std;struct BST_node{ DataType data; BS ...
easyx坦克大战
效果图如下:
特色:
基于像素移动,自由度更高。对地图的破坏基于单元格进行。
地图编辑器:使玩家能够进行再创作,游戏更加灵活。
酷酷的音效。实话,这游戏很无聊,最吸引我的是它的bgm。
这个项目是本人在 01星球 与小伙伴们合作写的小游戏,也是我的第一个有图形界面的程序(之前都是黑压压的控制台小游戏)。可玩性不高,没有参考意义,仅留做纪念。有兴趣的读者可下载源码:
链接:https://pan.baidu.com/s/17PI4mMjW-RfygXp1yS5IjQ?pwd=gzwb
提取码:gzwb