【C++基础】面试题——Day4 📅 2026/7/12 5:53:41 大家好我是Halcyon.平安欢迎文末添加好友交流共同进步目录C 中 struct 和 class 的区别?C 中 struct 和 union 的区别如何使用 union 做优化?C 中 using 和 typedef 的区别?C 中 enum 和 enum class 的区别?C 中 new 和 malloc 的区别delete 和 free 的区别?C 中类定义中 delete 关键字和 default 关键字的作用?C 中 this 指针的作用?C 中可以使用 delete this 吗?C 中 vector 的原理resize 和 reserve 的区别size 和 capacity 的区别?C 中 deque 的原理它内部是如何实现的?目录C 中 struct 和 class 的区别?从语法上看只有一处区别其余都是使用习惯默认访问权限class默认成员是privatestruct默认是public。继承时同理——class B : A默认私有继承struct B : A默认公有继承。使用习惯不是语法规定struct常用于plain old dataPOD/ 简单数据聚合成员基本公开少量或没有成员函数。class常用于封装良好的复杂类型成员私有 提供接口。一句话语法上只差一个默认 public/private习惯上 struct 装数据、class 装逻辑。C 中 struct 和 union 的区别如何使用 union 做优化?struct每个成员各自独立占用一块内存对象大小 ≈ 各成员大小之和考虑内存对齐。同一时刻可以访问任意成员。union所有成员共享同一块首地址的内存大小 最大成员的大小。同一时刻只能有效地保存一个成员写一个会覆盖另一个。struct S { int a; double b; }; // a 和 b 各占各的sizeof ≈ 16 union U { int a; double b; }; // a 和 b 共用一块sizeof 8 U u; u.a 1; u.b 3.14; // 写 b 之后 a 已经被覆盖不能再读 aunion 的优化场景嵌入式/底层节省内存多个字段在同一时刻只会用到其中一个时用 union 把它们挤进同一块内存。类型双关type punning安全地按不同类型解读同一段比特位比如拆解一个float的符号/阶码/尾数比reinterpret_cast更合规。C17 后推荐用std::variant替代手写 union更安全。C 中 using 和 typedef 的区别?两者都是给类型起别名但using更强大typedef只能给已有类型起别名语法是typedef 旧类型 新名字;using语法是using 新名字 旧类型;更直观并且支持模板别名typedef做不到。typedef unsigned int uint_t; // 旧写法 using uint_t unsigned int; // 新写法顺序更自然 // 模板别名 —— using 的杀手锏typedef 写不出 templatetypename T using Vec std::vectorT; // 现在 Vecint std::vectorint一句话能用 using 就用 using只有给模板起别名这一条 typedef 就被秒杀了。C 中 enum 和 enum class 的区别?enum无作用域枚举 / 弱类型枚举枚举值直接暴露在外层作用域可以直接写Red。会隐式转换为整型容易引发意外比较/赋值。不同 enum 之间名字会冲突。enum class强类型枚举C11 引入枚举值必须带作用域Color::Red不会污染外层。不会隐式转 int要转必须显式static_castint(Color::Red)更安全。可以指定底层类型enum class Color : uint8_t { ... };enum Color { Red, Green }; // Red 直接可见能隐式转 int enum class Fruit { Apple, Banana }; // 必须写 Fruit::Apple不能隐式转 int x Red; // OK弱枚举 int y Fruit::Apple; // 编译报错强枚举一句话enum 弱、会隐式转换、名字会冲突enum class 强、要带作用域、显式转换更安全。C 中 new 和 malloc 的区别delete 和 free 的区别?对比项new / deletemalloc / free本质运算符可重载库函数内存 构造分配内存并调用构造函数只分配内存不构造释放 析构调用析构函数再释放内存只释放内存不析构返回类型返回对应类型指针类型安全返回void*需要强转失败行为抛异常std::bad_alloc返回nullptr是否可重载可以在类级别自定义 operator new不能重载⚠️必须搭配使用new 配 delete、malloc 配 free混用是未定义行为new 出来的对象用 free 会导致析构函数不执行。一句话new/delete 会调构造/析构malloc/free 只搬内存。C 中类定义中 delete 关键字和 default 关键字的作用?C11 引入用来显式控制编译器自动生成的特殊成员函数构造/析构/拷贝/移动等default显式告诉编译器用默认实现生成这个函数。常用于你自定义了某个构造函数后编译器就不再生成默认构造了这时手写A() default;把它要回来。让代码意图更清晰。delete禁用某个函数任何调用都会编译报错。常用于禁止拷贝A(const A) delete; A operator(const A) delete;单例、不可复制的资源类常用。禁止某些危险参数类型比如禁止指针隐式转换。class A { public: A() default; // 用默认实现 A(const A) delete; // 禁拷贝构造 A operator(const A) delete; // 禁拷贝赋值 A(int) {} A(long) delete; // 禁止 long 隐式转换构造 };一句话default 要默认实现delete 直接禁用。C 中 this 指针的作用?this是编译器偷偷给每个非静态成员函数加的一个隐藏形参类型是ClassName* const指向调用该函数的那个对象。作用指代当前对象函数体内访问成员时本质是this-成员。区分同名形参和成员this-name name;实现链式调用成员函数返回*this返回引用就能obj.f1().f2().f3();。多态的基石虚函数靠this指向的对象的 vptr 完成动态绑定。class Builder { int val_ 0; public: Builder add(int x) { val_ x; return *this; } // 返回 *this 支持链式 }; Builder b; b.add(1).add(2).add(3); // 链式调用静态成员函数没有 this 指针所以只能访问静态成员。C 中可以使用 delete this 吗?语法上可以但强烈不建议。要安全使用必须同时满足对象是通过new在堆上分配的不能是栈对象、不能是数组的一部分。调用delete this;之后绝对不能再访问该对象的任何成员、虚函数、this包括函数返回后继续用对象本身。不能在析构函数里调用delete this会无限递归。调用它的成员函数本身不能是delete this之后还继续访问成员的。class Ref { public: void release() { delete this; // 自杀 // 这里之后绝不能再碰任何成员 } };实际工程里几乎都用智能指针shared_ptr/ 自定义 deleter替代delete this。C 中 vector 的原理resize 和 reserve 的区别size 和 capacity 的区别?vector 原理本质是三根指针管理一块连续的动态数组——start头、finish已用尾、end_of_storage容量尾。当finish end_of_storage还要 push_back 时触发扩容申请一块更大的新内存通常是1.5 倍或 2 倍→ 把旧元素**搬过去能 move 就 move**→ 释放旧内存 → 更新三根指针。resize vs reserveresize(n)reserve(n)改变 size✅是❌否改变 capacity可能✅是初始化/构造元素✅会默认值或指定值❌不会缩小会删掉多余的元素无效capacity 不会缩小size vs capacitysize()当前实际存了多少个元素finish - start。capacity()当前已分配的容量即最多能存多少个元素end_of_storage - start。当size capacity时触发扩容。std::vectorint v; v.reserve(100); // capacity100, size0不构造任何元素 v.resize(10); // size10多出来的 10 个被初始化为 0 v.resize(5); // size5后面的元素被销毁capacity 不变一句话resize 动有效元素数reserve 只动容量上限。C 中 deque 的原理它内部是如何实现的?deque双端队列支持头插/头删、尾插/尾删都是 O(1)并且支持[]随机访问。内部实现关键考点不是一整块连续内存而是分段连续底层是一组固定大小的小块连续内存chunk / buffer每个 chunk 都能存若干元素。中间用一个**“中控 map”——本质是一个指针数组**T**每个元素指向一个 chunk。这个 map 本身也是一段连续空间两边不够时也会扩容。头部 push往前一个 chunk 的末尾塞尾部 push往后一个 chunk 的头部塞——所以两端都是 O(1)。随机访问通过map[i / chunk_size]定位到第几个 chunk再[i % chunk_size]取元素所以是 O(1)比 vector 稍慢多了一次解引用。map: [chunk0*][chunk1*][chunk2*]... ↓ ↓ ↓ [....] [....] [....] ← 每个是一段连续内存一句话deque 分段连续数组 一个指针数组map当索引两端 O(1)随机访问也 O(1)。