LOADING

加载过慢请开启缓存 浏览器默认开启

面试笔记

2025/3/20 C++ Interview Language

最近在面试阿里云文件存储 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