败犬日报 2025-07-16
1. 有没有优化编译时间的编译选项
不开优化就行了,-O0
。
不过这做不到任何情况最优。理论上可能存在某些 pass 可以大量简化 IR,然后加快后续的编译进度,比如死代码删除的 pass。
2. 将引用绑定到两个变量中的一个
用三目就行了。
int x;
int y;
int &ref = condition ? x : y;
3. 工作只需要用现成的库,之前学的基础知识有什么用
面试的时候不就用到了吗。
另一方面,做项目不是说会调几个库跑个 mvp 出来就行了,出现问题了你得会定位,某些情况下你得自己编下库把断点打到那里,你如果没有通用的相对 low level 的知识,效率会很低。—— hiki
4. std::sort 是内省排序 (introsort)
是快速排序、堆排序、插入排序融合版。快排为主,如果范围小用插入,如果递归深度大用堆排。
5. 实现快速排序,但是 swap 开销特别大
先对索引快速排序,然后 swap 捋一遍,尽可能减少 swap 次数。
6. llm-friendly LLM 体工程学
未来大量接口首先需要考虑面向 llm。例如微服务,由于上下文短非常适合 LLM 写。而 infra 上下文牵涉太多,还得靠人。
7. 怎么判断 shared_ptr
基类和 shared_ptr
子类指向的是同一个对象
可以判断控制块 (control block) 的指针是否相同。
控制块是什么?shared_ptr 包含指向对象、控制块两个指针,而控制块存储的是对象(或对象的指针)、Deleter、分配器、引用计数和弱引用计数。ref https://en.cppreference.com/w/cpp/memory/shared_ptr.html 里的 Implementation notes 章节。
不过判断控制块的技巧没什么用。赋值一般是 swap 实现(就是 copy-and-swap idiom),不需要判断对象相同。
==
不能判断是同一对象,在菱形继承情况下(下面解释),标准规定了 ==
比较的都是存储的指针,https://en.cppreference.com/w/cpp/memory/shared_ptr/operator_cmp.html:
In all cases, it is the stored pointer (the one returned by get()) that is compared.
一般来说,判断指针相同可以直接 ==
,因为编译期基类地址对于子类的偏移是确定的(偏移不为 0 的情况是多继承、有虚函数类继承无虚函数类)。
#include <cstdio>
struct Base1 {
int data0;
};
struct Base2 {
int data1;
};
struct Derived : Base1, Base2 {};
int main() {
Derived d;
Derived* derived_ptr = &d;
Base1* base1_ptr = &d;
Base2* base2_ptr = &d;
printf("%p %p %p\n", derived_ptr, base1_ptr, base2_ptr); // 可能输出 0x7ffcdf034dcc 0x7ffcdf034dcc 0x7ffcdf034dd0
printf("%d %d\n", derived_ptr == base1_ptr, derived_ptr == base2_ptr); // 输出 1 1
}
但是菱形继承是不行的,因为子类包含了多个基类(类型相同但是地址不同),就会有歧义。
#include <cstdio>
struct Base0 {};
struct Base1 : Base0 {
int data0;
};
struct Base2 : Base0 {
int data1;
};
struct Derived : Base1, Base2 {};
int main() {
Derived d;
Derived* derived_ptr = &d;
Base0* base0_ptr = static_cast<Base1*>(&d);
printf("%d\n", derived_ptr == base0_ptr); // error: 'Base0' is an ambiguous base of 'Derived'
}