mutable关键字

前言

mutable的字面意思是,易变的。它在C++中的作用是让一个常函数可以修改mutable修饰的变量。

常成员函数的声明原则

在类中声明成员函数时,如果这个函数不会改变对象的状态,那么我们就应该用const去修饰它,将其声明为常成员函数。那么怎样才算是改变对象状态呢?我以前只是简单的认为,只要修改了成员变量就是改变了对象状态,但是这种想法太片面了。

还有一种特殊的情况,如果一个函数会改变某个成员对象的值,但未必会改变对象状态。这是因为,并不能够完全根据成员对象的值是否被改变来判定,而应当根据这个对象对外的接口函数所反应的信息来判断。如果对一个成员函数的调用,不会使其后对该对象的成员函数的调用的结果发生变化,那么就可以认为这个成员函数的调用不会改变对象状态。这个原则,只是从经验的角度得出来的,对于具体物理意义的对象,还是应当有更具体的判别方式。

来看看下面这个例子

class Line {
public:
    explicit Line(const Point &p1, const Point &p2)
        : p1(p1), p2(p2), len(-1) {}
    double getLen();

private:
    Point p1, p2;
    double len;
};

double Line::getLen() {
    if (len < 0) {
        double x = p1.getX() - p2.getX();
        double y = p1.getY() - p2.getY();
        len = sqrt(x*x + y*y);
    }
    return len;
}

Line类的getLen函数用于计算两点之间的长度,并将结果保存到变量len中。这样可以避免以后重复计算。从经验的角度看,在它调用多次后,得到的都是相同的结果,因此不会改变对象的状态。既然是这样,那就和之间的原则矛盾了,既然不会改变对象状态,就应当将其声明为常成员函数,但是语法上不允许,因为它终究是改变了len的值,虽然只有一次。为此,C++提供了一个解决方法,那就是关键字——”mutable”。通过它进行修饰后,即使是常成员函数也可以修改它们的值。于是可以把上面的代码改成如下形式:

class Line {
public:
    explicit Line(const Point &p1, const Point &p2)
        : p1(p1), p2(p2), len(-1) {}
    double getLen() const;

private:
    Point p1, p2;
    mutable double len;
};

double Line::getLen() const{
    if (len < 0) {
        double x = p1.getX() - p2.getX();
        double y = p1.getY() - p2.getY();
        len = sqrt(x*x + y*y);
    }
    return len;
}

使用了mutable修饰后,就可以将getLen函数声明为常成员函数了。
其实mutable不只允许在常成员函数中修改被它修饰的数据成员,“常对象的成员对象被视为常对象”这一语言原则,对mutable修饰的成员并不适用。被mutable修饰的成员对象在任何时候都不会被视为常对象,这是mutable更一般的含义。尽管mutable能够很好的解决上例中的问题,但绝对不能滥用,否则会破坏const形成的语言保护机制。也就是说,一定要确定存在常成员函数要改变一个成员对象,而且对该成员函数的调用确实不会改变对象状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值