面试常见工程类问题

158 阅读8分钟

自己实现一个智能指针

  • 需要注意各种构造函数和assign操作符的重载,包括左值右值情况都要考虑
  • 注意delete,防止内存泄漏
ini
复制代码
template <class T>
class SmartPtr {
public:
    SmartPtr(T* p = nullptr) {
        p_ = p;
        if (p_ != nullptr) {
            count_ = new int(1);
        }
    }

    ~SmartPtr() {
        if (count_ != nullptr) {
            (*count_)--;
            if (*count_ == 0) {
                if (p_ != nullptr) {
                    delete p_;
                }
                delete count_;
            }
        }
    }

    SmartPtr(const SmartPtr& oth) {
       p_ = oth.p_;
       count_ = oth.count_;
       if(p_ != nullptr) {
           *count_++;
       }
    }

    SmartPtr(SmartPtr&& oth) {
       p_ = oth.p_;
       count_ = oth.count_;
       oth.p_ = nullptr;
       oth.count_ = nullptr;
    }

    SmartPtr& operator =(const SmartPtr& oth) {
        if (this == &oth) {
            return *this;
        }

        if (count_ !=nullptr && *count_ == 1) {
            if (p_ != nullptr) {
                delete p_;
            }
            delete count_;
        }
        p_ = oth.p_;
        count_ = oth.count_;
        (*count_)++;
        return *this;
    }

    SmartPtr& operator = (SmartPtr&& oth) {
        std::swap(p_, oth.p_);
        std::swap(count_, oth.count_);
        return *this;
    }

    T* operator ->() const {
        return p_;
    }

    T& operator *() const {
        return *p_;
    }
    //k
    T& operator [](int index) {
        return p_[index];
    }
    
    T* get() {
        return p_;
    }

    int use_count() {
        return count_ == nullptr? 0: *count_;
    }

private:
    T* p_ = nullptr;
    int* count_ = nullptr;
};

struct ListNode {
  int data;
  SmartPtr<ListNode> prev;
  SmartPtr<ListNode> next;
  ~ListNode(){ cout << "~ListNode()" << endl; }
};

int main(int argc, char **argv) {
  SmartPtr<ListNode> node1(new ListNode);
  SmartPtr<ListNode> node2(new ListNode);
  cout << node1.use_count() << endl;
  cout << node2.use_count() << endl;
  node1->next = node2;
  node2->prev = node1;
  cout << node1.use_count() << endl;
  cout << node2.use_count() << endl;
  return 0;
}

自己实现一个queue

ini
复制代码
template <class T>
class SmartQueue {
public:
struct Node {
    Node() = default;
    Node(const T& t) {
        val = t;
    }
    T val;
    Node* pre = nullptr;
    Node* next = nullptr;
};

    SmartQueue() {
        dummy_head_ = new Node();
        dummy_tail_ = new Node();
        dummy_head_->next = dummy_tail_;
        dummy_tail_->pre = dummy_head_;
    }

    ~SmartQueue() {
        Release();
    }

    SmartQueue(const SmartQueue& oth) {
        dummy_head_ = new Node();
        Node* cur = dummy_head_;
        Node* p_oth = oth.dummy_head_->next;
        while (p_oth != nullptr) {
            cur->next = new Node(p_oth->val);
            cur->next->pre = cur;
            cur = cur->next;
            p_oth = p_oth->next;
        }
        dummy_tail_ = cur;
    }

    SmartQueue(SmartQueue&& oth) {
        dummy_head_ = oth.dummy_head_;
        dummy_tail_ = oth.dummy_tail_;
        size_ = oth->size_;

        oth->dummy_head_ = nullptr;
        oth->dummy_tail_ = nullptr;
        oth->size_ = 0;
    }

    SmartQueue& operator =(const SmartQueue& oth) {
        if (this == &oth) {
            return *this;
        }

        Release();
        dummy_head_ = new Node();
        Node* cur = dummy_head_;
        const Node* p_oth = oth.dummy_head_->next;
        while (p_oth != nullptr) {
            cur->next = new Node(p_oth->val);
            cur->next->pre = cur;
            cur = cur->next;
            p_oth = p_oth->next;
        }
        dummy_tail_ = cur;
    }

    void Release() {
        Node* cur = dummy_head_->next;
        while (cur != nullptr) {
            delete cur->pre;
            cur = cur->next;
        }
        delete dummy_tail_;
        dummy_tail_ = nullptr;
        dummy_head_ = nullptr;
        size_ = 0;
    }

    T back() {
        return dummy_tail_->pre->val;
    }

    T front() {
        return dummy_head_->next->val;
    }

    void push_back(const T& t) {
        auto pre = dummy_tail_->pre;
        Node* new_node =  new Node(t);
        pre->next = new_node;
        new_node->pre = pre;
        new_node->next = dummy_tail_;
        dummy_tail_->pre = new_node;
        ++size_;
    }

    void push_front(const T& t) {
        auto next = dummy_head_->next;
        Node* new_node = new Node(t);
        dummy_head_->next = new_node;
        new_node->next = next;
        new_node->pre = dummy_head_;
        next->pre = new_node;
        ++size_;
    }

    bool pop_back() {
        if (dummy_head_->next == dummy_tail_) {
            return false;
        }
        Node* n = dummy_tail_->pre;
        n->pre->next = n->next;
        n->next->pre = n->pre;
        delete n;
        --size_;
        return true;
    }

    bool pop_front() {
        if (dummy_head_->next == dummy_tail_) {
            return false;
        }
        Node* n = dummy_head_->next;
        n->pre->next = n->next;
        n->next->pre = n->pre;
        delete n;
        --size_;
        return true;
    }

    size_t size() const {
        return size_;
    }

    void Debug() {
        Node* p = dummy_head_->next;
        while (p != dummy_tail_) {
            cout << p->val << "->";
            p = p->next;
        }
        cout << endl;
    }


private:
    size_t size_ = 0;
    Node* dummy_head_ = nullptr;
    Node* dummy_tail_ = nullptr;
};

实现memcpy和memmove

ini
复制代码
void* memcpy (void* dst, const void* src, size_t size) {
    void* ret = dst;
    while (size--) {
        *(char*)dst = *(char*)src;
        dst = (char*)dst + 1;
        src = (char*)src + 1;
    }
    return ret;
}

void* memmove(void* dst, const void* src, size_t size) {
    void* ret = dst;
    // 没有重叠
    if (dst <= src || (char*)dst >= (char*)src + size) {
        while(size-- > 0) {
            *(char*)dst = *(char*)src;
            dst = (char*)dst + 1;
            src = (char*)src + 1;
        }
    }
    else {
        dst = (char*)dst + size - 1;
        src = (char*)src + size - 1;
        while (size-- > 0) {
            *(char*)dst = *(char*)src;
            dst = (char*)dst - 1;
            src = (char*)src - 1;
        }
    }
    return ret;
}

自己实现一个hashmap

c
复制代码
#include <iostream>
// 使用了vector和list的模板库,实际上list可以自己实现,vector不是很有必要自己实现
// C++的哈希表是unordered_map,属于标准库,实现了各种高阶功能,建议研究一下源码
#include <vector>
#include <list>

const int MAX_SIZE = 10;

// 1. 首先定义一个键值对的数据结构
template<typename K, typename V>
struct KVNode {
    K key;
    V value;
    KVNode(K k, V v) : key(k), value(v) {}
};

// 2. 自定义HashMap类
template<typename K, typename V>
class HashMap {
private:
    // 2.1 通过一个简单的复合数据结构直接就可以实现HashMap,甚至有分桶。其中list也可以自己实现
    std::vector<std::list<KVNode<K, V>>> table;

    // 2.2 哈希函数,将键映射到索引
    int hash(K key) {
        return key % MAX_SIZE;
    }

// 3. 实现初始化和增删查的方法
public:
    // 3.1 初始化
    HashMap() {
        table.resize(MAX_SIZE);
    }

    // 3.2 增
    void insert(K key, V value) {
        int index = hash(key);
        // 遍历当前链表,看是否已经存在
        for (auto& kv : table[index]) {
            if (kv.key == key) {
                // 如果键已存在,更新值
                kv.value = value;
                return;
            }
        }
        // 如果键不存在,插入新的键值对
        table[index].emplace_back(key, value);
    }

    // 3.3 查
    V get(K key) {
        int index = hash(key);
        for (auto& kv : table[index]) {
            if (kv.key == key) {
                return kv.value;
            }
        }
        return -1; // 如果键不存在,返回-1或其他合适的值
    }

    // 3.4 删
    void remove(K key) {
        int index = hash(key);
        table[index].remove_if([key](const KVNode<K, V>& kv) {
            return kv.key == key;
        });
    }
};

// 测试
int main() {
    HashMap<char, char> map;

    map.insert(1, 42);
    map.insert(2, 53);

    std::cout << "Key 1: " << map.get(1) << std::endl;
    std::cout << "Key 2: " << map.get(2) << std::endl;

    map.remove(1);

    std::cout << "After Delete: " << map.get(1) << std::endl; // 输出 -1

    return 0;
}

自己实现一个timer

要点就是一个优先队列,每次epoll wait栈顶最早超时的时间

arduino
复制代码
#include <functional>
#include <iostream>
#include <algorithm>
#include <sys/epoll.h>
#include <sys/time.h>
#include <unistd.h>
#include <queue>
#include <vector>


class Timer
{
  public:
    Timer(unsigned long long expire, std::function<void(void)> fun)
        : expire_(expire), fun(fun)
    {
    }

    inline void run() { fun(); }

    inline unsigned long long getExpire() const{ return expire_; }

  private:
    std::function<void(void)> fun;

    unsigned long long expire_;
};


class TimerManager
{
public:
    TimerManager() {}

    Timer *addTimer(int timeout_ms, std::function<void(void)> fun)
    {
        if (timeout_ms <= 0) {
            return NULL;
        }

        unsigned long long now = getCurrentMillisecs();
        Timer* timer = new Timer( now+timeout_ms, fun);

        queue_.push(timer);

        return timer;
    }

    void delTimer(Timer* timer)
    {
        std::priority_queue<Timer*,std::vector<Timer*>,cmp> newqueue;

        while( !queue_.empty() )
        {
            Timer* top = queue_.top();
            queue_.pop();
            if( top != timer )
                newqueue.push(top);
        }

        queue_ = newqueue;
    }

    unsigned long long getRecentTimeout()
    {
        unsigned long long timeout = -1;
        if( queue_.empty() )
            return timeout;

        unsigned long long now = getCurrentMillisecs();
        timeout = queue_.top()->getExpire() > now?  queue_.top()->getExpire() - now:0;

        return timeout;
    }

    void takeAllTimeout()
    {   
        unsigned long long now = getCurrentMillisecs();

        while ( !queue_.empty() )
        {
            Timer* timer = queue_.top();
            if ( timer->getExpire() <= now ) {
                queue_.pop();
                timer->run();
                delete timer;

                continue;
            }

            return;
        }
    }

    unsigned long long getCurrentMillisecs()
    {
        struct timespec ts;
        clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
        return ts.tv_sec * 1000 + ts.tv_nsec / (1000 * 1000);
    }

private:

    struct cmp
    {
        bool operator()(Timer*& lhs, Timer*& rhs) const { return lhs->getExpire() > rhs->getExpire(); }
    };

    std::priority_queue<Timer*,std::vector<Timer*>,cmp> queue_;
};

int main () {
    TimerManager tm;
    int epfd = epoll_create(1);
    // epoll_ctl(epfd, ...); //将所有需要监听的socket添加到epfd中

    epoll_event events[1];
    tm.addTimer(1000, []() { std::cout << "hello world" << std::endl; });
    while (1) {
        int n = epoll_wait(epfd, events, 1, tm.getRecentTimeout());
        tm.takeAllTimeout();
    }

    return 0;

}

float转string

c
复制代码
#include <string>
#include <vector>
#include <sstream>
#include <iostream>

using namespace std;
std::string i2s(int i, int times)
{
    if (i == 0)
    {
        return "0";
    }
    std::vector<int> v;
    v.reserve(16);
    while (i > 0)
    {
        v.push_back(i % 10);
        i /= 10;
        --times;
    }
    while (times > 0) {
        v.push_back(0);
        --times;
    }
    std::stringstream ss;
    for (int j = v.size() - 1; j >= 0; --j)
    {
        --times;
        ss << v[j];
    }
    return ss.str();
}
std::string float2str(float f)
{
    std::stringstream result;
    // 符号
    if (f < 0)
    {
        result << "-";
        f = -f;
    }
    // 整数部分
    int z = int(f);
    result << i2s(z, 0);

    // 小数部分
    float x = f - float(z);
    if (x < 1e-6)
    {
        return result.str();
    }
    int times = 0;
    while (x - int(x) > 1e-6) // 判断有几位小数,但是*10后可能丢失精度
    {
        x *= 10;
        ++times;
    }
    // 小数点
    result << "." << i2s(int(x), times);
    return result.str();
}

int main()
{
    cout << float2str(2.5) << endl;
    cout << float2str(10.5) << endl;
    cout << float2str(0.55002564565555) << endl;
    return 0;
}

无锁链表与CAS

compare_exchange_weak 方法用于将原子对象的当前值与期望值进行比较,如果相等,则将其更新为新值。如果不相等,则将原子对象的当前值加载到期望值中,并返回 false

markdown
复制代码
bool compare_exchange_weak(T& expected, T desired, std::memory_order success, std::memory_order failure) noexcept;
bool compare_exchange_weak(T& expected, T desired) noexcept; // 简化版本
-   `expected`: 期望值,如果原子对象的当前值与此值相等,则更新为 `desired`-   `desired`: 用于更新原子对象的值。
-   `success`: 成功时的内存序。
-   `failure`: 失败时的内存序。
arduino
复制代码
template<typename T>
class LockFreeStack {
private:
    std::atomic<Node<T>*> head;

public:
    LockFreeStack() : head(nullptr) {}

    void push(T value) {
        Node<T>* newNode = new Node<T>(value);
        newNode->next = head.load(std::memory_order_relaxed);

        while (!head.compare_exchange_weak(newNode->next, newNode,
                                           std::memory_order_release,
                                           std::memory_order_relaxed)) {
            // CAS failed, newNode->next is updated with the new head value
        }
    }

    bool pop(T& result) {
        Node<T>* oldHead = head.load(std::memory_order_relaxed);

        while (oldHead != nullptr && 
               !head.compare_exchange_weak(oldHead, oldHead->next,
                                           std::memory_order_acquire,
                                           std::memory_order_relaxed)) {
            // CAS failed, oldHead is updated with the new head value
        }

        if (oldHead == nullptr) {
            return false; // Stack is empty
        }

        result = oldHead->data;
        delete oldHead;
        return true;
    }
};

priorty queue 使用

c
复制代码
// 自定义比较器
struct Compare {
    bool operator()(const std::pair<int, int>& a, const std::pair<int, int>& b) {
        // 根据第二个元素进行比较,构造大顶堆
        return a.second < b.second;
    }
};

int main() {
    // 声明一个 std::priority_queue,使用自定义比较器
    std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, Compare> pq;

    // 插入一些元素
    pq.push({1, 20});
    pq.push({2, 15});
    pq.push({3, 30});
    pq.push({4, 10});

    // 输出并移除队列中的元素
    while (!pq.empty()) {
        auto p = pq.top();
        std::cout << "(" << p.first << ", " << p.second << ")" << std::endl;
        pq.pop();
    }

    return 0;
}

std::function 使用

c
复制代码
#include <iostream>
#include <functional>
#include <vector>
using namespace std;


void callFunction(const std::function<void(int)>& func, int value) {
    func(value);
}

void printValue(int x) {
    std::cout << "Value: " << x << std::endl;
}

template <class T>
void Fun(std::vector<T>& vec, const std::function<void(T)>& func) {
    for (auto t: vec) {
        func(t);
    }
}

int main() {
        // 使用普通函数
    // callFunction(printValue, 10);

    // // 使用 lambda 表达式
    // callFunction([](int x) { std::cout << "Lambda Value: " << x << std::endl; }, 20);

    // // 使用 std::bind
    // auto boundFunc = std::bind(printValue, std::placeholders::_1);
    // callFunction(boundFunc, 30);

    std::vector<int> v({1,2,3});
    Fun<int>(v, [](int i) {cout <<i <<endl;});

    return 0;
}

float 转 string

c
复制代码
#include <sstream>
#include <iostream>
#include <string>
#include <vector>
std::string i2s(int i, int min_lenth)
{
    if (i == 0)
    {
        return "0";
    }
    std::vector<int> v;
    v.reserve(16);
    while (i > 0)
    {
        v.push_back(i % 10);
        i /= 10;
        --min_lenth;
    }
    std::stringstream ss;
    for (int j = v.size() - 1; j >= 0; --j)
    {
        --min_lenth;
        ss << v[j];
    }
    return ss.str();
}
std::string float2str(float f)
{
    std::stringstream result;
    if (f < 0)
    {
        result << "-";
        f = -f;
    }
    int z = int(f);
    float x = f - float(z);

    result << i2s(z, 0);
    if (x < 1e-6)
    {
        return result.str();
    }
    int min_lenth = 0;
    while (x - int(x) > 1e-6)
    {
        x *= 10;
        ++min_lenth;
    }
    result << "." << i2s(int(x), min_lenth);
    return result.str();
}

int main()
{
    std::cout << float2str(0) << std::endl;
    std::cout << float2str(-0.15) << std::endl;
    std::cout << float2str(10) << std::endl;
    std::cout << float2str(-100.586) << std::endl;
    std::cout << float2str(2.5) << std::endl;
    std::cout << float2str(10.5) << std::endl;
    std::cout << float2str(0.55002564565555) << std::endl;
    return 0;
}

URL

c
复制代码

#include <iostream>
#include <cctype>
#include <string>
#include <unordered_set>

using namespace std;

class IsServer {
public:
    void Set(const std::string& url) {
        black_list_.insert(FormatUrl(url));
    }

    bool IsBlackListed(const std::string& url) {
        return black_list_.count(FormatUrl(url)) > 0;
    }

    std::string FormatUrl(const std::string& url) {
        has_handle_port_ = false;

        std::string res = "";
        size_t p = RemoveProtocol(url);

        while(p < url.size()) {
            char c = url[p];    
            if (c == ':') {
                IgnorePort(url, p, res);
            }
            else if (c == '?') {
                return res;
            }
            else if (c == '/') {
                if (res.back() =='/') {
                    ++p;
                    continue;
                }
                else {
                    res.push_back(c);
                }
            } 
            else {
                res.push_back(std::tolower(c));
            }
            ++p;
        }

        if(res.back() == '/') {
            res.pop_back();
        }
        return res;
    }

private:
    void IgnorePort(const std::string& url, size_t& i, std::string& res) {
        if (has_handle_port_) {
            res.push_back(url.at(i));
            return;
        }
        while (i < url.size() && url.at(i) != '/') {
            ++i;
        }
        if (url.at(i) == '/' && res.back() != '/') {
            res.push_back( url.at(i));
        }
        has_handle_port_ = true;
    }

    size_t RemoveProtocol(const std::string& url) {
        size_t first_slash = url.find('/');
        size_t pos = url.find("://");
        if (pos == url.npos || pos > first_slash) {
            return 0;
        }
        return pos + 3;
    }

    bool has_handle_port_ = false;
    std::unordered_set<std::string> black_list_;
};

int main () {
    IsServer is;
    cout << is.FormatUrl("AKA.MS/A/b/C") << endl;
    cout << is.FormatUrl("https://aks.ms/a/b/c") << endl;
    cout << is.FormatUrl("http://aks.ms/a://b/c") << endl;
    cout << is.FormatUrl("http://aks.ms/a://b/c") << endl;
    cout << is.FormatUrl("aka.ms:80/a/b/c?p=1&q=2") << endl;
    cout << is.FormatUrl("aks.ma/a///b////c") << endl;
    cout << is.FormatUrl("aks.ma/a://b/c") << endl;
}

thread 生产消费者

#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <atomic>

class Worker {
public:
    Worker() : stop_thread_(false) {
        work_thread_ = std::thread(&Worker::WorkThread, this);
    }

    ~Worker() {
        {
            std::unique_lock<std::mutex> lock(queue_mutex_);
            stop_thread_ = true;
        }
        queue_cond_var_.notify_all();
        if (work_thread_.joinable()) {
            work_thread_.join();
        }
    }

    void Enqueue(int item) {
        {
            std::unique_lock<std::mutex> lock(queue_mutex_);
            work_queue_.push(item);
        }
        queue_cond_var_.notify_one();
    }

private:
    void WorkThread() {
        while (true) {
            int item;
            {
                std::unique_lock<std::mutex> lock(queue_mutex_);
                queue_cond_var_.wait(lock, [this]() { return stop_thread_ || !work_queue_.empty(); });

                if (stop_thread_ && work_queue_.empty()) {
                    return;
                }

                item = work_queue_.front();
                work_queue_.pop();
            }
            ProcessItem(item);
        }
    }

    void ProcessItem(int item) {
        std::cout << "Processing item: " << item << std::endl;
        // 这里可以添加实际的处理逻辑
    }

    std::thread work_thread_;
    std::queue<int> work_queue_;
    std::mutex queue_mutex_;
    std::condition_variable queue_cond_var_;
    std::atomic<bool> stop_thread_;
};

int main() {
    Worker worker;

    for (int i = 0; i < 10; ++i) {
        worker.Enqueue(i);
    }

    // 给一点时间让工作线程处理队列中的元素
    std::this_thread::sleep_for(std::chrono::seconds(2));

    return 0;
}

异步线程池

#include <iostream>
#include <future>
#include <vector>
#include <functional>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>

class ThreadPool {
public:
    ThreadPool(size_t thread_num) {
        for (size_t i = 0; i < thread_num; ++i) {
            workers_.emplace_back([this] {
                while (true) {
                    std::function<void()> task;
                    {
                        std::unique_lock<std::mutex> lock(queue_mutex_);
                        condition_.wait(lock, [this] { return stop_ || !task_queue_.empty(); });
                        if (stop_ && task_queue_.empty()) {
                            return;
                        }
                        task = std::move(task_queue_.front());
                        task_queue_.pop();
                    }
                    task();
                }
            });
        }
    }

    template <class F, class... Args>
    auto AddFuture(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
        using return_type = typename std::result_of<F(Args...)>::type;

        auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));

        std::future<return_type> result = task->get_future();
        {
            std::unique_lock<std::mutex> lock(queue_mutex_);
            if (stop_) {
                throw std::runtime_error("enqueue on stopped ThreadPool");
            }
            task_queue_.emplace([task]() { (*task)(); });
        }
        condition_.notify_one();
        return result;
    }

    
template <class ItemType, tepename Function>
bool Visit(const int thread_num, const std::vector<ItemType>& container, Function&& visit_func, int timeout_ms = 0) {
    if (thread_num == 0) {
        return false;
    }
    int container_size = container.size();
    int item_num_for_one_thread = std::ceil((double)container_size / thread_num);

    std::vector<std::future<bool>> futures;
    futures.resize(std::min(thread_num,container_size));
    auto func_ptr = std::make_shared<Function>(std::move(visit_func));
    for (int i = 0; i < futures.size(); ++i) {
        const int start_index = i * item_num_for_one_thread;
        if (start_index >= container_size) {
            continue;
        }
        const int end_index = std::min((container_size - 1), start_index + item_num_for_one_thread - 1);
        futures[i] = AddFuture([start_index, end_index, &container, func_ptr, this]() {
            for (int j = start_index; j <= end_index; ++j) {
                bool res = (*func_ptr)(container[j]);
            }
            return true;
        });
    }
    
    if (timeout_ms == 0) {
        for (int i = 0; i < futures.size(); ++i) {
            futures[i].wait();
        }
    }
    else {
        for (int i = 0; i < futures.size(); ++i) {
            auto status = futures[i].wait_for(std::chrono::milliseconds(timeout_ms));
            if (status == std::future_status::timeout) {
                LOG_ERROR("wait for future timeout");
            }
        }
    }
    
    return true;
}

    template <class ContainerType, tepename

    ~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(queue_mutex_);
            stop_ = true;
        }
        condition_.notify_all();
        for (std::thread& worker : workers_) {
            worker.join();
        }
    }

private:
    std::vector<std::thread> workers_;
    std::queue<std::function<void()>> task_queue_;
    std::mutex queue_mutex_;
    std::condition_variable condition_;
    bool stop_ = false;
};

int main() {
    const size_t thread_num = 4; // 限定线程数量为4
    ThreadPool pool("pool", thread_num);
    std::string s = "hello world";
    auto sp = std::make_shared<std::string>("hello world");
    pool.AddFuture([sp]() {
        std::cout << *sp << std::endl;
        return true;
    });

    // visit
    // 并行将string从s_vec写到map里
    std::vector<std::string> s_vec;
    const int vec_size = 5000;
    for (int i = 0; i < vec_size; ++i) {
        s_vec.push_back(std::to_string(i));
    }

    std::mutex mu_;
    std::map<int, std::string> map_;
    auto func = [&mu_](const std::string& s) {
        std::lock_guard<std::mutex> lock(mu_);
        map_.emplace(stoi(s), s);
        return true;
    }
   bool res = pool.Visit(10, s_vec, std::move(func));
   for (const auto& [k, v]: map_) {
       std::cout <<k << ":" << v << std::endl;
   }

    return 0;
}