眼谷科技嵌入式软件开发 一面 总结
1.自我介绍
面试官好,我是[姓名],[学校][专业][年级]。我的技术方向是嵌入式软件开发,主要使用C++进行开发。
技术栈方面,我熟悉C++11/14特性、STL容器和算法,有Linux环境下的开发经验,了解交叉编译、驱动开发等嵌入式相关技术。在AI方面,我接触过深度学习模型的部署,特别是在嵌入式平台上部署YOLO等目标检测模型。
项目经验上,我做过[具体项目],主要负责[具体模块]的开发,涉及到[技术点]。在这个过程中积累了嵌入式开发和模型部署的实际经验。
我对嵌入式AI很感兴趣,特别是如何在资源受限的设备上实现高效的算法。希望能加入眼谷科技,在智能视觉领域深入学习和实践。
2.class和struct在C++中有什么区别?
在C++中,class和struct的区别很小,主要是默认访问权限不同。struct的成员默认是public的,而class的成员默认是private的。继承时也一样,struct默认是public继承,class默认是private继承。
struct MyStruct {
int x; // 默认public
};
class MyClass {
int x; // 默认private
};
除了这个区别,两者在功能上完全相同,都可以有成员函数、构造函数、析构函数、继承、多态等特性。实际使用中,一般用struct表示简单的数据结构(POD类型),用class表示有复杂行为的对象。
在C语言中,struct只能包含数据成员,不能有成员函数。但在C++中,struct和class几乎没有区别,这是为了兼容C语言的设计。
3.new和malloc有什么区别?使用时要注意什么?
new和malloc都是用来动态分配内存的,但有几个重要区别。
首先,new是C++的操作符,malloc是C的库函数。new会调用构造函数初始化对象,malloc只是分配内存,不会初始化。相应地,delete会调用析构函数,free只是释放内存。
// new会调用构造函数 MyClass* obj = new MyClass(); delete obj; // 调用析构函数 // malloc不会调用构造函数 MyClass* obj2 = (MyClass*)malloc(sizeof(MyClass)); free(obj2); // 不会调用析构函数,可能导致资源泄漏
其次,new返回的是具体类型的指针,类型安全;malloc返回void*,需要强制类型转换。new分配失败会抛出bad_alloc异常,malloc返回NULL。new可以被重载,malloc不能。
使用建议:C++中优先使用new/delete,或者更好的是使用智能指针。如果要和C代码交互,或者需要realloc功能,才使用malloc/free。注意new和delete要配对,malloc和free要配对,不能混用。
4.C++中的智能指针有哪些?它们的核心特点是什么?
C++11引入了三种智能指针,用于自动管理内存,避免内存泄漏。
unique_ptr表示独占所有权,不能拷贝只能移动,性能开销最小,几乎等同于裸指针。适合明确的单一所有权场景,比如工厂函数返回值、替代裸指针。
std::unique_ptr<int> ptr1 = std::make_unique<int>(10); // std::unique_ptr<int> ptr2 = ptr1; // 错误,不能拷贝 std::unique_ptr<int> ptr2 = std::move(ptr1); // 可以移动
shared_ptr表示共享所有权,使用引用计数管理,最后一个shared_ptr销毁时释放对象。有引用计数的开销(原子操作),适合多个对象共享资源、对象生命周期不确定的场景。
std::shared_ptr<int> ptr1 = std::make_shared<int>(10); std::shared_ptr<int> ptr2 = ptr1; // 引用计数+1 // ptr1和ptr2都销毁后,对象才被释放
weak_ptr是shared_ptr的观察者,不增加引用计数,用于打破循环引用。使用前需要lock()转换为shared_ptr,检查对象是否还存在。
std::shared_ptr<int> sp = std::make_shared<int>(10);
std::weak_ptr<int> wp = sp;
if (auto sp2 = wp.lock()) { // 检查对象是否还存在
// 使用sp2
}
嵌入式开发中,由于资源受限,要特别注意智能指针的开销。unique_ptr是首选,shared_ptr要谨慎使用,避免循环引用导致内存泄漏。
5.map和unordered_map有什么区别?如何选择?
map和unordered_map都是关联容器,但底层实现和性能特点不同。
map基于红黑树实现,元素按键自动排序,查找、插入、删除的时间复杂度都是O(log n)。遍历时元素是有序的,支持范围查询(lower_bound、upper_bound)。
std::map<int, std::string> m; m[3] = "three"; m[1] = "one"; m[2] = "two"; // 遍历时按键排序:1, 2, 3
unordered_map基于哈希表实现,元素无序,查找、插入、删除的平均时间复杂度是O(1),最坏情况O(n)(哈希冲突严重时)。不支持范围查询,遍历顺序不确定。
std::unordered_map<int, std::string> um; um[3] = "three"; um[1] = "one"; um[2] = "two"; // 遍历时顺序不确定
选择建议:如果需要排序或范围查询,用map;如果只需要快速查找,用unordered_map性能更好。嵌入式开发中,如果内存紧张,map的内存占用更可控;如果追求性能,unordered_map更快。注意unordered_map需要好的哈希函数,否则性能会退化。
6.C++模板有哪些特性?在嵌入式开发中如何使用?
C++模板是泛型编程的基础,主要特性包括:
函数模板和类模板,可以编写与类型无关的代码:
template<typename T>
T max(T a, T b) {
return
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
这是一个全面的嵌入式面试专栏。主要内容将包括:操作系统(进程管理、内存管理、文件系统等)、嵌入式系统(启动流程、驱动开发、中断管理等)、网络通信(TCP/IP协议栈、Socket编程等)、开发工具(交叉编译、调试工具等)以及实际项目经验分享。专栏将采用理论结合实践的方式,每个知识点都会附带相关的面试真题和答案解析。
