昨天闲着没事去面试了一个C++岗位,问了很多基础的东西都没答上来。主要原因是这些知识在硬件资源丰富的pc端用的不多,二来确实很久没温习之前的C++相关的知识了。在面试官问了几次类似的问题没有答好的情况下(还喜欢问你确不确定),最后面试结果也就可想而知了。
1.const和指针
在 C++ 中,const
的作用取决于它修饰的内容(指针本身或指针指向的值)。理解 const
的修饰规则可以通过以下原则:
1. 快速判断的方法
声明形式 | 从右往左读解释 | 指针行为 | 值行为 |
---|---|---|---|
const int* ptr; | 指针指向的值是常量,不能修改值 | 可改变地址 | 不可改变值 |
int* const ptr; | 指针本身是常量,不能改变指向 | 不可改变地址 | 可改变值 |
const int* const ptr; | 指针本身是常量,指向的值也是常量 | 不可改变地址 | 不可改变值 |
int* ptr; | 普通指针,可修改指针指向的地址和指针指向的值 | 可改变地址 | 可改变值 |
总结:看 const
修饰什么
const
修饰int*
:表示指针指向的值是常量,不能通过指针修改值。const
修饰ptr
:表示指针本身是常量,不能改变指针指向的地址。- 两个
const
同时使用:表示指针和指针指向的值都不能修改。
通过从右往左读声明,可以快速理解 const
的实际作用,应用到代码中时就能明确意图。
2.Qt的资源管理
这个问题主要是Qt的parent
设置问题,我也是浅浅的记得是这样管理的。后面面试官又问了我确不确定,第一我确实不确定(其实有点确定),第二就是软件工程里面不确定的东西实在是太多了,所以就说了确实不确定。
1. parent
的作用
- Qt 的对象树以
parent
和child
关系为基础。当一个对象设置了parent
:- 子对象会被自动添加到父对象的子对象列表中。
- 当父对象销毁时,其所有子对象会被 自动销毁。
- 如果
parent
是nullptr
,则该对象不会被其他对象管理,需要手动管理内存。
2. parent = nullptr
时的内存管理
- 如果创建一个
QObject
或其子类对象(如QWidget
),且没有设置parent
,它不会被 Qt 的对象树自动管理。 - 在这种情况下,你需要显式调用
delete
来释放内存,或者将其分配到栈上以自动管理生命周期。
// 在堆上创建,没有 parent
QObject *obj = new QObject();
// 需要手动删除
delete obj;
// 在栈上创建,无需关心内存释放
QObject obj2;
3. 常见场景分析
(1)动态分配且 parent = nullptr
QWidget *window = new QWidget(nullptr); // 没有 parent
window
不会被 Qt 自动管理,因此需要在适当的时候手动delete
。- 如果不
delete
,会导致 内存泄漏。
(2)分配在栈上
QWidget window; // 没有 parent
- 对象分配在栈上,生命周期由 C++ 的作用域管理,无需手动释放。
- 作用域结束后,对象自动销毁。
(3)结合 Qt 的智能指针
从 Qt 5.11 开始,可以使用 QScopedPointer
或标准的 std::unique_ptr
来管理内存:
#include <QScopedPointer>
QScopedPointer<QObject> obj(new QObject(nullptr)); // 自动释放内存
或者使用标准智能指针:
#include <memory>
std::unique_ptr<QObject> obj = std::make_unique<QObject>(nullptr); // 自动释放内存
4. 避免问题的建议
-
优先设置
parent
如果可能,尽量为对象设置parent
,让 Qt 自动管理其生命周期。特别是 GUI 对象,通常需要将其子对象挂接到父对象上。QWidget *child = new QWidget(parent); // parent 销毁时,child 自动销毁
-
明确生命周期管理
- 如果
parent = nullptr
,确保在适当时候调用delete
,或使用智能指针。 - 避免同时使用
delete
和 Qt 的parent
管理,这可能导致二次销毁或未定义行为。
- 如果
-
检查内存泄漏
使用工具(如 Valgrind 或 AddressSanitizer)检查未正确释放的内存。
5. 常见误区
- 误解 Qt 的内存管理全自动化:只有设置了
parent
的情况下,Qt 才能管理内存。parent = nullptr
时,内存管理完全是开发者的责任。 - 对对象树的过度依赖:设置
parent
可以简化内存管理,但在复杂对象关系下,可能导致意外的销毁顺序或内存问题。
总结
当 QObject
的 parent
为 nullptr
时:
- 需要开发者手动管理内存(使用
delete
或智能指针)。 - 分配在栈上的对象无需特别管理。
- 为避免内存泄漏或未定义行为,应始终明确对象的生命周期,合理使用
parent
或智能指针。
3.教训
既然是面试,很多八股文还是要看滴,不看是会吃亏滴…