• 手撕代码


    1、阻塞队列/线程安全队列

    实现:

    注意问题:

      1、防止虚假唤醒的lambda表达式需要传入this,也就是调用变量

      2、lambda表达式的函数体不可以使用自己写的判断队列满或者空函数

    template <typename T>
    class block_queue
    {
    public:
        block_queue(int max_size = 1000)
        {
            if (max_size <= 0)
            {
                exit(-1);
            }
    
            m_max_size = max_size;
            m_size = 0;
            m_array = new T[m_max_size];
            m_front = -1;;
            m_back = -1;
        }
        block_queue(const block_queue&) = delete;
    
        ~block_queue()
        {
            std::unique_lock<std::mutex> ulk(m_mutex);
            if (m_array != NULL)
                delete[] m_array;
        }
    
        /*
            往队列添加元素,需要将所有使用队列的线程先唤醒
            当有元素push进队列,相当于生产者生产了一个元素
            若当前没有线程等待条件变量,则唤醒无意义
        */
        bool push(const T &item)
        {
            std::unique_lock<std::mutex> ulk(m_mutex);
    
            /*
            while (m_size >= m_max_size)
                m_cond.wait(ulk);
            */
    
            m_cond.wait(ulk, [this]() {
                return m_size < m_max_size;
            });
    
            //将新增数据放在循环数组的对应位置
            m_back = (m_back + 1) % m_max_size;
            m_array[m_back] = item;
            m_size++;
    
            m_cond.notify_all();
            return true;
        }
        //pop时,如果当前队列没有元素,将会等待条件变量
        bool pop(T &item)
        {
            std::unique_lock<std::mutex> ulk(m_mutex);
    
            /*
            //多个消费者的时候,这里要是用while而不是if
            while (m_size <= 0)
                m_cond.wait(guard);
            */
            m_cond.wait(ulk, [this]() {
                return m_size > 0;
            });
    
            //取出队列首的元素,这里需要理解一下,使用循环数组模拟的队列
            m_front = (m_front + 1) % m_max_size;
            item = m_array[m_front];
            m_size--;
            m_cond.notify_all();
            return true;
        }
    
        //返回队首元素
        bool front(T &value)
        {
            std::unique_lock<std::mutex> ulk(m_mutex);
            if (0 == m_size)
            {
                //ulk.unlock();
                return false;
            }
            value = m_array[m_front];
            m_mutex.unlock();
            return true;
        }
    
        //返回队尾元素
        bool back(T &value)
        {
            std::unique_lock<std::mutex> ulk(m_mutex);
            if (0 == m_size)
            {
                //ulk.unlock();
                return false;
            }
            value = m_array[m_back];
            return true;
        }
    
    
        int size()
        {
            int tmp = 0;
            std::unique_lock<std::mutex> ulk(m_mutex);
            tmp = m_size;
            return tmp;
        }
    
        int max_size()
        {
            int tmp = 0;
            std::unique_lock<std::mutex> ulk(m_mutex);
            tmp = m_max_size;
            return tmp;
        }
    
        //判断队列是否满了
        bool full()
        {
            std::unique_lock<std::mutex> ulk(m_mutex);
            if (m_size >= m_max_size)
            {
                return true;
            }
            return false;
        }
        //判断队列是否为空
        bool empty()
        {
            std::unique_lock<std::mutex> ulk(m_mutex);
            if (0 == m_size)
            {
                return true;
            }
            return false;
        }
    
    private:
        std::mutex m_mutex;
        std::condition_variable m_cond;
    
        int m_max_size;
        int m_size;
        T* m_array;
        int m_front;
        int m_back;
    };
    View Code

     2、unique_ptr智能指针

      C++11中又引入了unique_ptr,他的实现思路非常简单粗暴,就是防拷贝,既然多个智能指针指向同一资源会导致问题那就干脆不让你这样做,这样问题自然也就解决了。C++11中也是非常推荐使用这种智能指针,因为其比起shared_ptr和auto_ptr来说较为稳定,不会导致严重的错误但是其也存在缺陷,就是在需要拷贝的场景下他没有办法使用。

    实现:

      1、禁止拷贝构造

      2、进制复制构造

      3、可以实现移动语义

     1 template<typename T>
     2 class My_unique_ptr
     3 {
     4 private:
     5     T* _ptr;
     6 public:
     7     My_unique_ptr(const T* ptr) : _ptr(ptr) {}
     8     My_unique_ptr(const My_unique_ptr<T>&) = delete;
     9     My_unique_ptr& operator=(const My_unique_ptr<T>&) = delete;
    10     ~My_unique_ptr()
    11     {
    12         if (_ptr)
    13         {
    14             delete _ptr;
    15             _ptr = nullptr;
    16         }
    17     }
    18     T& operator*()
    19     {
    20         return *_ptr;
    21     }
    22     T* operator->()
    23     {
    24         return _ptr;
    25     }
    26 };

    3、实现shared_ptr智能指针

      为了弥补unique_ptr不能拷贝的缺陷,C++11中还引入了shared_ptr,他的实现思路是引用计数,通过计数的方式来实现多个智能指针共同管理一个资源。shared_ptr在其内部,给每个资源都维护了着一份计数,用来记录该份资源被几个对象共享。在对象被销毁时(也就是析构函数调用),就说明自己不使用该资源了,对象的引用计数减一。如果引用计数是0,就说明自己是最后一个使用该资源的对象,必须释放该资源;如果不是0,就说明除了自己还有其他对象在使用该份资源,不能释放该资源,否则其他对象就成野指针了。

      相较于unique_ptr,它弥补了不能拷贝的缺陷,但是因为需要保证多线程并发时的线程安全问题,所以对于计数操作要进行加锁,所以导致其效率相对来说会低一些,并且还存在循环引用的问题,所以大部分情况下如果不需要进行拷贝,都会使用unique_ptr,需要拷贝时才使用shared_ptr.

    实现:

      1、引用计数实现

      2、独特地析构函数

      3、允许拷贝构造

      4、允许复制构造(注意:需要先释放掉原来所指向地对象)

     1 template<typename T>
     2 class mysharedptr {
     3 private:
     4     T* _ptr;
     5     int* _pcount;
     6     std::mutex* _pmtx;
     7     //加锁保证线程安全
     8     void add_ref_count() {
     9         _pmtx->lock();
    10         ++(*_pcount);
    11         _pmtx->unlock();
    12     }
    13     void release() {
    14         bool flag = false;
    15         _pmtx->lock();
    16         if (--(*_pcount) == 0) {
    17             if (_ptr) {
    18                 delete _ptr;
    19                 _ptr = nullptr;
    20             }
    21             delete _pcount;
    22             _pcount = nullptr;
    23             flag = true;
    24         }
    25         _pmtx->unlock();
    26         if (flag) {
    27             delete _pmtx;
    28             _pmtx = nullptr;
    29         }
    30     }
    31 
    32 public:
    33     mysharedptr(T* ptr) : _ptr(ptr), _pcount(new int(1)), _pmtx(new std::mutex) {}
    34     mysharedptr(mysharedptr<T>& sp) : _ptr(sp._ptr), _pcount(sp._pcount), _pmtx(sp._pmtx){
    35         add_ref_count();
    36     }
    37     mysharedptr<T>& operator=(mysharedptr<T>& sp) {
    38         if (this != &sp ) {
    39             release();        //自己原来所指向的对象的引用计数减1
    40             _ptr = sp._ptr;
    41             _pcount = sp._pcount;
    42             _pmtx = sp._pmtx;
    43 
    44             add_ref_count();
    45         }
    46         return *this;
    47     }
    48     ~mysharedptr() {
    49         release();
    50     }
    51 
    52     T& operator*() {
    53         return *_ptr;
    54     }
    55     T* operator->() {
    56         return _ptr;
    57     }
    58 
    59     T* get() const {
    60         return _ptr;
    61     }
    62     size_t use_count() const {
    63         return *_pcount;
    64     }
    65 };
    View Code

     四、数字字符串相加(lc415)

     1 string addStrings(string num1, string num2) {
     2     int len1 = num1.size(), len2 = num2.size();
     3     int len = max(len1, len2);
     4     vector<int> reg(len, 0);
     5     int i1 = len1 - 1, i2 = len2 - 1, index = len - 1, pre = 0;
     6     string ans;
     7     while (i1 >= 0 || i2 >= 0 || pre != 0)
     8     {
     9         int x = i1 >= 0 ? num1[i1] - '0' : 0;
    10         int y = i2 >= 0 ? num2[i2] - '0' : 0;
    11         int cur = x + y + pre;
    12         ans.push_back('0' + cur % 10);
    13         pre = cur / 10;
    14         i1--;
    15         i2--;
    16     }
    17     reverse(ans.begin(), ans.end());
    18     return ans;
    19 }

    本文来自博客园,作者:Mr-xxx,转载请注明原文链接:https://www.cnblogs.com/MrLiuZF/p/15078857.html

  • 相关阅读:
    JavaScript -基础- 变量、常量
    Python 执行SQL带参数
    Python 装饰器
    Bootstrap
    python 数据如何保存到excel中--xlwt
    django 中下载文件与下载保存为excel
    AttributeError: 'cx_Oracle.Cursor' object has no attribute 'numbersAsStrings'
    Python Django 之 基于JQUERY的AJAX 登录页面
    Python Django 之 登录页面
    Python pycharm 引入需要使用的包
  • 原文地址:https://www.cnblogs.com/MrLiuZF/p/15078857.html
Copyright © 2020-2023  润新知