去哪儿 客户端 AI一面 总结
1. 先做个自我介绍
面试官好,我是[姓名],目前就读于[学校][专业][年级]。我的技术方向主要是客户端开发,熟悉C++和移动端开发技术。
在技术栈方面,我掌握C++11/14特性,熟悉STL、智能指针、多线程编程;移动端方面有iOS/Android开发经验,了解UI优化和性能调优。
项目经验上,我参与过[项目名称],负责[具体模块]的开发,主要解决了[技术难点]。在[公司]实习期间,参与了[项目],积累了实际开发和问题排查的经验。
平时我会在LeetCode刷题保持算法能力,也关注技术博客学习新技术。我对去哪儿的旅游业务很感兴趣,希望能将技术应用到实际产品中,提升用户体验。
2. 解释一下HTTP协议
HTTP(超文本传输协议)是应用层协议,用于客户端和服务器之间传输数据。
核心特点:
- 无状态:每次请求独立,服务器不保存客户端状态(通过Cookie/Session解决)
- 基于请求-响应模型:客户端发起请求,服务器返回响应
- 基于TCP协议:可靠传输
- 默认端口:HTTP是80,HTTPS是443
请求结构:
- 请求行:方法(GET/POST/PUT/DELETE等)、URL、HTTP版本
- 请求头:Host、User-Agent、Content-Type、Cookie等
- 空行
- 请求体:POST请求的数据
响应结构:
- 状态行:HTTP版本、状态码、状态描述
- 响应头:Content-Type、Content-Length、Set-Cookie等
- 空行
- 响应体:实际数据
常用方法:
- GET:获取资源,参数在URL中,幂等
- POST:提交数据,参数在body中,非幂等
- PUT:更新资源
- DELETE:删除资源
HTTP/1.1 vs HTTP/2:
- HTTP/1.1:持久连接、管道化,但有队头阻塞问题
- HTTP/2:多路复用、头部压缩、服务器推送,性能更好
HTTPS:HTTP + SSL/TLS,加密传输,保证安全性。
3. HTTP状态码404表示什么?还知道哪些常见状态码?
404表示"Not Found",请求的资源在服务器上不存在。常见原因是URL拼写错误、资源已删除或移动。
常见状态码分类:
1xx 信息性状态码:
- 100 Continue:客户端可以继续发送请求
2xx 成功状态码:
- 200 OK:请求成功
- 201 Created:资源创建成功(POST请求)
- 204 No Content:请求成功但无返回内容
3xx 重定向状态码:
- 301 Moved Permanently:永久重定向
- 302 Found:临时重定向
- 304 Not Modified:资源未修改,使用缓存
4xx 客户端错误:
- 400 Bad Request:请求语法错误
- 401 Unauthorized:未授权,需要身份验证
- 403 Forbidden:服务器拒绝请求
- 404 Not Found:资源不存在
- 405 Method Not Allowed:请求方法不支持
5xx 服务器错误:
- 500 Internal Server Error:服务器内部错误
- 502 Bad Gateway:网关错误
- 503 Service Unavailable:服务不可用(过载或维护)
- 504 Gateway Timeout:网关超时
客户端开发中,需要根据不同状态码做相应处理,比如401跳转登录,404提示资源不存在,5xx提示服务器异常。
4. C++中try-catch如何使用?什么情况下需要使用?
try-catch是C++的异常处理机制,用于捕获和处理运行时错误。
基本语法:
try {
// 可能抛出异常的代码
int result = riskyOperation();
} catch (const std::exception& e) {
// 处理异常
std::cerr << "Error: " << e.what() << std::endl;
} catch (...) {
// 捕获所有类型的异常
std::cerr << "Unknown error" << std::endl;
}
多重捕获:
try {
// 代码
} catch (const std::bad_alloc& e) {
// 内存分配失败
} catch (const std::runtime_error& e) {
// 运行时错误
} catch (const std::exception& e) {
// 其他标准异常
}
重新抛出异常:
try {
// 代码
} catch (const std::exception& e) {
// 记录日志
log(e.what());
throw; // 重新抛出
}
使用场景:
需要使用:
- 资源分配失败(内存、文件、网络)
- 外部依赖调用(第三方库、网络请求)
- 数据解析和验证
- 跨模块边界的错误传递
不建议使用:
- 正常的控制流程(用if-else)
- 性能关键路径(异常有开销)
- 可以通过返回值处理的简单错误
- 构造函数和析构函数中要谨慎使用
最佳实践:
- 按引用捕获异常(避免拷贝和切片)
- 捕获具体异常类型,而非所有异常
- 使用RAII保证异常安全
- 不要在析构函数中抛出异常
5. noexcept修饰的函数抛出了异常会怎么样?
noexcept表示函数承诺不抛出异常。如果noexcept函数抛出了异常,程序会调用std::terminate()直接终止,不会进行栈展开。
void func() noexcept {
throw std::runtime_error("error"); // 程序会终止
}
noexcept的作用:
性能优化:编译器可以进行更激进的优化,因为不需要生成异常处理代码。
移动语义:容器(如vector)在扩容时,如果移动构造函数是noexcept,会使用移动而非拷贝,性能更好。
接口约定:明确告诉调用者这个函数不会抛异常,可以放心使用。
条件noexcept:
template<typename T>
void swap(T& a, T& b) noexcept(noexcept(T(std::move(a)))) {
T temp = std::move(a);
a = std::move(b);
b = std::move(temp);
}
使用建议:
- 析构函数默认是noexcept的,不要在析构函数中抛异常
- 移动构造和移动赋值尽量标记noexcept
- 确定不会抛异常的函数才标记noexcept
- 不确定的情况不要随意使用,否则可能导致程序崩溃
6. C++智能指针有哪些?各自的使用场景是什么?
C++11引入了三种智能指针,用于自动管理内存。
unique_ptr:
- 独占所有权,不能拷贝,只能移动
- 零开销,性能等同于裸指针
- 使用场景:明确的单一所有权,工厂函数返回值,替代裸指针
std::unique_ptr<Object> ptr = std::make_unique<Object>(); auto ptr2 = std::move(ptr); // 转移所有权
shared_ptr:
- 共享所有权,引用计数管理
- 最后一个shared_ptr销毁时释放对象
- 有引用计数开销(原子操作)
- 使用场景:多个对象共享资源,对象生命周期不确定
std::shared_ptr<Object> ptr1 = std::make_shared<Object>(); std::shared_ptr<Object> ptr2 = ptr1; // 引用计数+1
weak_ptr:
- 不控制对象生命周期,不增加引用计数
- 用于打破shared_ptr的循环引用
- 使用前需要lock()转换为shared_ptr
- 使用场景:观察者模式,缓存,避免循环引用
std::shared_ptr<Object> sp = std::make_shared<Object>();
std::weak_ptr<Object> wp = sp;
if (auto sp2 = wp.lock()) { // 检查对象是否还存在
// 使用sp2
}
选择原则:
- 默认使用unique_ptr,性能最好
- 需要共享所有权时用shared_ptr
- 避免循环引用时用weak_ptr
- 优先使用make_unique和make_shared
注意事项:
- 避免shared_ptr循环引用导致内存泄漏
- 不要用同一个裸指针初始化多个智能指针
- 自定义删除器的使用场景(如文件句柄、数组)
7. 客户端如何优化加载速度?
加载速度优化是提升用户体验的关键,可以从多个层面优化:
启动优化:
- 延迟加载:非必要模块延后初始化
- 预加载:提前加载可能用到的资源
- 并行加载:多线程并行初始化
- 减少启动时的IO操作
- 优化启动流程,去除不必要的初始化
网络优化:
- 接口合并:减少请求次数
- 数据压缩:gzip、protobuf等
- 缓存策略:HTTP缓存、本地缓存
- 预加载:提前请求下一页数据
- CDN加速:静态资源使用CDN
- 弱网优化:超时重试、降级策略
图片优化:
- 图片压缩:WebP格式,降低质量
- 懒加载:可见区域才加载
- 缩略图:列表用小图,详情用大图
- 图片缓存:内存缓存+磁盘缓存
- 渐进式加载:先显示模糊图,再加载清晰图
数据库优化:
- 索引优化:常查询字段建索引
- 批量操作:减少数据库访问次数
- 异步查询:不阻塞主线程
- 分页加载:避免一次加
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专栏系统梳理C++技术面试核心考点,涵盖语言基础、面向对象、内存管理、STL容器、模板编程及经典算法。从引用指针、虚函数表、智能指针等底层原理,到继承多态、运算符重载等OOP特性从const、static、inline等关键字辨析,到动态规划、KMP算法、并查集等手写实现。每个知识点以面试答题形式呈现,注重原理阐述而非冗长代码,帮助你快速构建完整知识体系,从容应对面试官提问,顺利拿下offer。
