最近在面试阿里云文件存储 C++ 岗位,问了很多底层的问题,以前没有了解过或者印象不清,现在在此记录一番。
std::shared_ptr 和 std::weak_ptr
std::shared_ptr
由指向的数据和控制块组成。控制块维护的是一些元数据,包括强引用计数和弱引用计数。
- 当强引用计数变为 0 的时候,会释放指向的数据,但是保留控制块,因为可能存在若干
std::weak_ptr
指向该数据。可以通过std::weak_ptr::expired
判断是否当前数据已过期(即强引用为 0,数据已经被释放)。 - 当弱引用计数变为 0 的时候,控制块也被释放,此时
std::shared_ptr
走向生命周期的终点。
如何遍历 std::tuple
std::get
auto t = std::make_tuple(1, '123', 2.0);
std::cout << std::get<0>(t) << std::endl;
std::apply
std::apply([](auto&&... args) {
((std::cout << args << " "), ...);
}, t);
std::index_sequence
template <typename T, size_t... Is>
void printTuple(const T &tuple, std::index_sequence<Is...>) {
((std::cout << std::get<Is>(tuple) << " "), ...);
std::cout << std::endl;
}
template <typename ...Args>
void printTuple(const std::tuple<Args...> &t) {
printTuple(t, std::make_index_sequence<sizeof...(Args)>{});
}
printTuple(t);
顺便复习了一下可变参数模板:
template <typename ...Args>
void print(Args... args) {
// 注意下面这个有无空格的两种写法
// (std::cout << ... << args);
((std::cout << args << " "), ...);
std::cout << std::endl;
}
template <typename ...Args>
auto sum(Args... args) {
return (... + args);
}
template <typename T, size_t... Is>
void printElements(const T &v, std::index_sequence<Is...>) {
print(v[Is]...);
}
template <typename T, typename... Is>
void printElements(const T &v, Is... idx) {
print(v[idx]...);
}
template <typename T, size_t... Is>
void printTuple(const T &tuple, std::index_sequence<Is...>) {
((std::cout << std::get<Is>(tuple) << " "), ...);
std::cout << std::endl;
}
其他 points
- 使用数据分区、分片来提升性能;
- top 指令的 nice 值应该就对应 MLPQ 里的优先级;
- std::string_view;
- 为什么 MCS lock 使用 spin lock?
- 基于 CAS,不涉及上下文切换
- std::mutex 基于睡眠和唤醒
- WAL 和 多机分布式备份的优劣对比
- std::shared_from_this
- 内外 const