C++ 类的内存布局

测试代码: #include <iostream> using namespace std; struct A{ long long a = 10; virtual void fa(){ cout << "A::fa()\n"; } virtual void faa(){ cout << "A::faa()\n"; } }; // 如果是虚继承,虚基类被放在了派生类的后面,每个基类都有自己的虚函数表指针存储单元,如果虚基类没有虚函数,则虚基类的虚函数表指针为 0 // 如果是非虚继承,基类在派生类的前面,每个基类都有自己的虚函数表指针存储单元,除了第一个基类(派生类与第一个基类共用一个存储单元) struct E: virtual A{ long long e = 2; virtual void fa(){ cout << "E::fa()\n"; } virtual void fe(){ cout << "E::fe()\n"; } }; int main() { typedef void(*FUNC)(); E e; cout << sizeof(e) << endl; long long* addr = (long long*)&e; long long* vfptre = (long long*)*(addr + 0); int eval = (int)*(addr + 1); cout << eval << endl; long long* vfptra = (long long*)*(addr + 2); int aval = (int)*(addr + 3); cout << aval << endl; cout << "---------------\n"; long long* faptr = (long long*)*(vfptre + 0); (FUNC(faptr))(); long long* feptr = (long long*)*(vfptre + 1); (FUNC(feptr))(); cout << "---------------\n"; long long* faptra = (long long*)*(vfptra + 0); // (FUNC(faptra))(); // 如果虚基类的虚函数被重写,此处则无法再如此执行 long long* faaptra = (long long*)*(vfptra + 1); (FUNC(faaptra))(); return 0; } 输出:...

May 18, 2024 · 4 min · Rick Cui

C++——统计代码行数

cloc 下载地址 加入到环境变量 执行命令 参考: 好用的源码行数统计工具——cloc Win10 代码行数统计工具CLOC的安装和使用

April 2, 2024 · 1 min · Rick Cui

C++——Function Style Cast 有歧义

#include <iostream>#include <string>using namespace std; struct Print { template<typename T> Print(T t){ cout<<(t+=10); } }; struct S { S(int a){ cout << a << endl; }; }; void foo(double a) { S w(int(a)); // function declaration // S x(int()); // function declaration S y((int(a))); // object declaration S yy((int)a); // object declaration S z = int(a); // object declaration } template <class T> struct X {}; template <int N> struct Y {}; X<int()> a; // type-id X<int(1)> b; // expression (ill-formed) Y<int()> c; // type-id (ill-formed) Y<int(1)> d; // expression void foo(signed char a) { sizeof(int()); // type-id (ill-formed) sizeof(int(a)); // expression sizeof(int(unsigned(a))); // type-id (ill-formed) (int())+1; // type-id (ill-formed) (int(a))+1; // expression (int(unsigned(a)))+1; // type-id (ill-formed) } int main() { // 这句为什么是一句函数声明而不是变量创建? double a = 3....

February 21, 2024 · 1 min · Rick Cui

C++——打印枚举常量字符串

#include <stdio.h>#define MY_INT 7777 #define STR(R) #R #define STR2(R) STR(R) enum MyType{ MyType_NULL, MyType_One, MyType_Two }; int main() { printf("%s\n", STR(MyType_One)); printf("%s\n", STR(HELLO_WORLD)); printf("%s\n", STR(MY_INT)); printf("%s\n", STR2(MY_INT)); const int arr[] = {1,2,3}; arr[1] = 4; // error: assignment of read-only location ‘arr[1]’ return 0; } 输出: MyType_One HELLO_WORLD MY_INT 7777 参考: c++中#与##的作用

April 12, 2023 · 1 min · Rick Cui

C++——malloc、calloc、realloc、指针杂记

void printArr(int *A, int size){ printf("Elements of array: "); for(int i = 0; i < size; ++i){ printf("%d\t", A[i]); } printf("\n"); } int main() { int C[3][2][2] = {{{1,2},{3,4}},{{5,6},{7,8}},{{9,10},{11,12}}}; // 虽然地址相同,但代表的意义却不相同 printf("%p\t%p\t%p\t%p\t%p\t%p \n", C, *C, C[0], C[0][0], &C[0][0], &C[0][0][0]); printf("%p\t%p\t%p\n", *C+1, C[0]+1, C[0][1]); printf("%p\t%p\n", C, C[0][0] + 1); printf("%p\t%p\n", C, &C[0][0] + 1); // 分配空间,但不会对元素进行初始化 int *A = (int*)malloc(3 * sizeof(int)); for(int i = 0; i < 3; ++i){ A[i] = i+1; } printArr(A, 3); // 分配空间,并将元素初始化为0 int *B = (int*)calloc(3, sizeof(int)); printArr(B, 3); // 重新分配一块空间(新空间可大可小) // 并把原来的数据拷贝过来 // 如果新空间首地址与原来空间地址不同,会将原来的内存空间释放 // ,注意:此时不能再继续访问原来的地址,虽然原来的指针并未置空 int *D = (int*)realloc(A, 10 * sizeof(int)); printf("%p\t%p\n", A, D); printArr(A, 3); // 此时不能访问 A 了,这是危险的行为 printArr(D, 10); // 等同于重新分配了空间 D = (int*)realloc(NULL, 3 * sizeof(int)); // int *D = (int*)malloc(3 * sizeof(int)); printf("%p\t%p\n", A, D); printArr(D, 3); // 等同于释放了内存空间并将指针置为空值 D = (int*)realloc(D, 0); // free(D);D = nullptr; printf("%p\n", D); return 0; } 输出:...

October 2, 2022 · 1 min · Rick Cui