C++面试八股文:指针占用多少个字节?

某日小二参加XXX科技公司的C++工程师开发岗位3面:

面试官:指针占用多少个字节?

小二:8个字节。

面试官:确定吗?

小二:额。。(我记得sizeof(void*) =8的呀。。)

面试官:在32位操作系统下呢?

小二:4个字节?

面试官:还有要补充的吗?

小二:好像没有了。

面试官:好的,回去等通知吧。

在C/C++中,指针的大小取决于编译器和操作系统的位数。在32位系统中,指针通常占用4个字节,而在64位系统中,指针通常占用8个字节。这是因为在32位系统中,内存地址可以用32位二进制数表示,而在64位系统中,内存地址可以用64位二进制数表示。因此,指针的大小也随之增加。需要注意的是,这只是一般情况,具体的实现可能会有所不同。

需要注意的是,操作系统的位宽对应内存的寻址能力。32位操作系统的位宽是32位,那么其寻找范围是0x000000000xffffffff,总共4GB。64位操作系统的理论寻址范围在0x00000000000000000xffffffffffffffff,但实际上并没有用到64位,而只用了48位。

指针在C语言中应用普遍,但是随着现代C++的普及,RAII、智能指针、容器的普遍运用,裸指针在C++项目中被使用的却越来越少。但是指针是一个非常基础的概念,是C和C++的基石之一,必须掌握它的所有特性。如果指针的长度和操作系统的位宽不同,那么这个指针可能会被截断或者扩展,导致程序出现错误。因此,在编写程序时,需要注意指针的大小和操作系统的位宽,以确保程序的正确性。

关注我,带你21天“精通”C++!(狗头)

<think>嗯,用户要求汇总C/C++面试常见问题,这是典型的求职准备需求。从引用内容看,用户可能正在收集技术面试高频考点,特别是内存管理、函数重载、虚函数等底层机制。需要覆盖语言特性、内存模型、面向对象等核心领域。 首先考虑基础概念:指针和引用的区别是必考题,用户提供的引用[1]涉及malloc(0)的边界情况,说明面试官喜欢考察异常处理能力。引用[2]展示名字修饰机制,这是解释函数重载原理的关键。引用[3]的虚函数表内容正好切入面向对象核心。 内存管理部分要突出实践性。结合引用[1]的malloc案例,可以设计内存分配相关陷阱题。引用[4]提到的拷贝构造场景和内存对齐原则,都是实际开发中容易出错的知识点。 面向对象设计需深入底层。虚函数表、纯虚函数等概念要关联实现机制,引用[3]提到构造函数不能虚化的原因就很典型。多态性部分需要区分静态绑定和动态绑定的应用场景。 模板和STL部分侧重应用。引用[2]隐含的名字修饰问题,在模板实例化时同样存在,可以引申出模板编译机制。智能指针的循环引用问题也是高频考点。 最后是编译和调试。引用[2][3]都涉及编译器行为,说明用户需要理解从代码到可执行文件的转换过程。预处理指令、静态断言等实用技巧能提升回答深度。 准备用分类结构组织答案,每类包含理论要点和典型例题。用户引用的四个例子正好对应内存管理、编译机制、多态实现三个维度,可以在相关小节重点展开。问题设计要模拟真实面试场景,比如引用[1]的malloc(0)就能延伸出堆内存分配的深度讨论。</think>以下是C/C++面试常见问题分类汇总,涵盖核心概念和实际应用场景: --- ### **一、基础概念** 1. **指针与引用的区别** - 指针是变量,存储地址;引用是别名,必须初始化且不可变 - 引用更安全(无空引用),指针支持算术运算 *例:`int a=5; int *p=&a;` vs `int &r=a;`* 2. **`const` 关键字的用法** - `const int* p`(指向常量的指针) vs `int* const p`(常量指针) - `const` 成员函数:禁止修改对象成员(如 `void func() const;`) --- ### **二、内存管理** 1. **堆与栈的区别** | **特性** | **栈** | **堆** | |----------------|----------------------------|----------------------------| | 管理方式 | 编译器自动分配释放 | 手动分配释放(`new`/`delete`) | | 大小限制 | 系统限定(通常几MB) | 受虚拟内存限制 | | 碎片问题 | 无 | 可能产生内存碎片 | 2. **内存泄漏场景与检测** - 常见原因:忘记释放堆内存、循环引用(智能指针未正确处理) - 工具:Valgrind、AddressSanitizer 3. **`malloc`/`free` vs `new`/`delete`** ```c++ int* p1 = (int*)malloc(sizeof(int)); // C风格,不调用构造函数 free(p1); int* p2 = new int(10); // C++风格,调用构造函数 delete p2; // 调用析构函数 ``` --- ### **三、面向对象** 1. **虚函数实现原理** - 通过虚函数表(vtable)实现动态绑定,每个类维护虚函数地址数组[^3] - 构造函数不能为虚函数(虚表在构造期间未初始化)[^3] 2. **继承中的访问控制** ```c++ class Base { protected: int data; }; class Derived : public Base { void access() { data = 10; } // 合法访问 }; ``` 3. **纯虚函数与抽象类** ```c++ class Shape { public: virtual void draw() = 0; // 纯虚函数 }; ``` --- ### **四、模板与STL** 1. **模板特化与偏特化** ```c++ template <typename T> void func(T a); // 通用模板 template <> void func<int>(int a); // 全特化 template <typename T> void func<T*>(T* a); // 偏特化 ``` 2. **`vector` 底层实现** - 动态数组,容量不足时以1.5~2倍扩容(`push_back`时间复杂度均摊O(1)) 3. **智能指针C++11)** - `unique_ptr`:独所有权,禁止拷贝 - `shared_ptr`:引用计数,支持拷贝 - `weak_ptr`:解决`shared_ptr`循环引用问题 --- ### **五、编译与底层** 1. **`extern "C"` 的作用** - 抑制C++的名称修饰(name mangling),确保C语言兼容性[^2] *例:`extern "C" void foo(int x);` → 编译后符号名为 `_foo` 而非 `_foo_int`* 2. **内存对齐原则** - 结构体成员按自身大小对齐(如`int`对齐到4字节) - 总大小为最大成员大小的整数倍[^4] 3. **拷贝构造函数的调用时机** - 对象初始化(`ClassA b = a;`) - 传参/返回值(值传递时)[^4] --- ### **六、经典问题** 1. **虚析构函数必要性** ```c++ Base* p = new Derived(); delete p; // 若~Base()非虚,仅调用Base的析构函数→内存泄漏 ``` 2. **深拷贝 vs 浅拷贝** - 浅拷贝:复制指针(同一内存) - 深拷贝:复制指向内容(新内存) 3. **`static` 关键字作用域** - 全局静态变量:文件内可见 - 局部静态变量:函数内持久化 - 类静态成员:所有实例共享 --- ### **相关问题** 1. 如何用C实现C++的类继承机制? 2. 在多线程环境下,`static`变量是否安全?如何保证线程安全? 3. 解释RTTI(运行时类型识别)的实现原理及其开销 4. C++11的移动语义如何提升性能?给出具体示例 5. 什么是“切片问题”(slicing problem)?如何避免? > 引用说明: > [^1]: 涉及内存分配的边界情况处理(如`malloc(0)`) > [^2]: C++名称修饰(name mangling)机制 > [^3]: 虚函数表构建时机与构造函数限制 > [^4]: 拷贝构造函数调用场景与内存对齐原则
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二进制架构

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值