C++中mutable关键字

参考链接:https://www.zhihu.com/question/64969053

这个关键字的允许你将一个类中的变量声明为易变的,从而const对象也能修改它。它就不算作类的状态的了。

我感觉这个东西可以用在性能优化和多线程的锁。

例如计算平均值:

有一个类统计了很多数值,传给很多人,很多人去拿平均值。但是平均值不是加完值直接算出来的,而是访问平均值的时候再算。这样就可以避免不必要的计算,访问的时候又可能会访问很多次,但是只想算一次,所以肯定要用一个变量表示现在算了没算,最简单的就是用cnt来表示,既能表示现在加了几个值了,又能表示现在算没算平均值。

mutable计算平均值代码:

#include <iostream>
#include <string>

using namespace std;

class CalcAverage {
public:
    CalcAverage() : average(0), cnt(0) {};

    const double getAverage() const {
        if(cnt>1) {
            // 如果average不是mutable,这里就会报错,因为函数体声明了为const,但是这里却修改了类中的变量。
            average /= cnt;
            cnt = 1;
        }
        return average;
    };
    void addValue(double t) {
        average += t;
        cnt++;
    }

private:
    // double average;
    mutable double average;
    mutable int cnt;
};

void show(const CalcAverage& calc) {
    cout<<calc.getAverage()<<endl;
}

int main() {
    CalcAverage calc;
    for (int i=0;i!=5;++i) {
        calc.addValue(i);
    }
    show(calc);
    show(calc);
    show(calc);
    return 0;
}

在多线程加锁的时候也需要将锁设为mutable,这样const对象就也可以加锁访问数据了。

作者:Timothy Liu
链接:https://www.zhihu.com/question/64969053/answer/1809304604
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

#pragma once

#ifndef CONCURRENCY_CONCURRENT_QUEUE_HPP

#define CONCURRENCY_CONCURRENT_QUEUE_HPP

#include <queue>
#include <mutex>
#include <utility>

#define CONCURRENT_NAMESPACE_BEGIN namespace concurrency {
#define CONCURRENT_NAMESPACE_END }

CONCURRENT_NAMESPACE_BEGIN

template <typename Elem>
class concurrent_queue
{
public:

    void clear()
    {
        std::lock_guard<std::mutex> lg(mtx);
        while (!q.empty()) q.pop();
    }

    [[nodiscard]] bool empty() const
    {
        std::lock_guard<std::mutex> lg(mtx);
        bool ret = q.empty();
        return ret;
    }

    template <typename... Ts>
    void push(Ts&&... args)
    {
        std::lock_guard<std::mutex> lg(mtx);
        q.emplace(std::forward<Ts>(args)...);
    }

    bool try_pop(Elem& out)
    {
        std::lock_guard<std::mutex> lg(mtx);
        if (q.empty()) return false;
        out = std::move(q.front());
        q.pop();
        return true;
    }

private:

    std::queue<Elem> q;
    mutable std::mutex mtx;
};

CONCURRENT_NAMESPACE_END

#undef CONCURRENT_NAMESPACE_END
#undef CONCURRENT_NAMESPACE_BEGIN

#endif //!CONCURRENCY_CONCURRENT_QUEUE_HPP
文章目录