自定义内存管理(一)

我们来一道c++笔试题:
统计对象中某个成员变量的访问次数。

分析一下,这道题想让我们做什么?
实现一个统计功能,统计对象里面的某个成员变量被访问了多少次(包括读的次数和写的次数)

那我们来实现一下该功能吧。

#include<iostream>
using namespace std;

class Object
{
private:
    int m_value;
    int m_count;    //用来统计访问次数
public:
    Object(int value = 0):m_value(value),m_count(0) {}

    int get_value()
    {
        m_count++;
        return m_value;
    }

    void set_value(int value)
    {
        m_count++;
        m_value = value;
    }

    //获取访问次数
    int get_count()
    {
        return m_count;
    }
};

int main()
{
    Object obj;

    //这里访问了三次value
    cout<< "value:" << obj.get_value()<<endl;
    obj.set_value(30);
    cout<< "value:" << obj.get_value()<<endl;

    cout<< "count:" << obj.get_count()<<endl;

    return 0;
}

程序运行结果
在这里插入图片描述
好像题目的功能实现了呢,交卷!


(坏笑)可是当你交卷后,面试官却只给了你 50 分,难道不对?

其实基本上对了,但是有些情况我们要考虑。比如

#include<iostream>
using namespace std;

class Object
{
private:
    int m_value;
    int m_count;    //用来统计访问次数
public:
    Object(int value = 0):m_value(value),m_count(0) {}

    int get_value()
    {
        m_count++;
        return m_value;
    }

    void set_value(int value)
    {
        m_count++;
        m_value = value;
    }

    //获取访问次数
    int get_count()
    {
        return m_count;
    }
};

int main()
{
    Object obj;

    //这里访问了三次value
    cout<< "value:" << obj.get_value()<<endl;
    obj.set_value(30);
    cout<< "value:" << obj.get_value()<<endl;

    cout<< "count:" << obj.get_count()<<endl<<endl;

    /***** 新添加的代码1 start *****/

    //我们有时候需要定义一个只读对象
    const Object obj1(688);
    cout<< "value:" << obj1.get_value()<<endl;
    obj1.set_value(300);

    /***** 新添加的代码1 end   *****/

    return 0;
}

编译一下,报错了。
在这里插入图片描述
意料之中的事情呢。我们知道,只读对象只能调用 const 成员函数。那我们先改成 const 成员函数吧。

编译一下,又报错了。
在这里插入图片描述
图中可以看到,我们试图在 const 成员函数中修改成员变量,怪不得编译器要报错。那我们现在就遇到难题了。

有什么办法可以解决这个问题吗???其实是有的。看一看吧

#include<iostream>
using namespace std;

class Object
{
private:
    mutable int m_value;
    mutable int m_count;    //用来统计访问次数
public:
    Object(int value = 0):m_value(value),m_count(0) {}

    int get_value() const
    {
        m_count++;
        return m_value;
    }

    void set_value(int value) const
    {
        m_count++;
        m_value = value;
    }

    //获取访问次数
    int get_count() const
    {
        return m_count;
    }
};

int main()
{
    Object obj;

    //这里访问了三次value
    cout<< "value:" << obj.get_value()<<endl;
    obj.set_value(30);
    cout<< "value:" << obj.get_value()<<endl;

    cout<< "count:" << obj.get_count()<<endl<<endl;

    /***** 新添加的代码1 start *****/
    //我们有时候需要定义一个只读对象
    const Object obj1(688);
    cout<< "value:" << obj1.get_value()<<endl;
    obj1.set_value(300);

    cout<< "count:" << obj1.get_count()<<endl<<endl;
    /***** 新添加的代码1 end   *****/

    return 0;
}

C++中有这么一个关键字 mutable

  1. mutable 成员变量将永远处于可修改的状态
  2. mutable 是为了突破 const 函数的限制而设计的
  3. mutable 在实际开发中被严禁滥用

大家会不会觉得很奇怪,mutable 这个家伙的出现,使得 const 名存实亡。

  1. mutable 成员变量破坏了只读对象的内部状态
  2. const 成员函数保证只读对象的状态不变性
  3. mutable 成员变量的出现无法保证状态不变性

所以实际开发 mutable 用的非常非常少。


如果刚才的代码提交给面试官能得满分了吗?
可能不行哦,毕竟你用了被大家讨厌的 mutable。
那我们该怎么做???

#include<iostream>
using namespace std;

class Object
{
private:
    int* const m_value;
    int* const m_count;    //用来统计访问次数
public:
    Object(int value = 0):m_value(new int(value)),m_count(new int(0)) {}
    ~Object()
    {
        delete m_value;
        delete m_count;
    }


    int get_value() const
    {
        //在这里,我们并没有改变指针的地址
        (*m_count)++;
        return *m_value;
    }

    void set_value(int value) const
    {
        (*m_count)++;
        *m_value = value;
    }

    //获取访问次数
    int get_count() const
    {
        return *m_count;
    }
};

int main()
{
    Object obj;

    //这里访问了三次value
    cout<< "value:" << obj.get_value()<<endl;
    obj.set_value(30);
    cout<< "value:" << obj.get_value()<<endl;

    cout<< "count:" << obj.get_count()<<endl<<endl;

    /***** 新添加的代码1 start *****/

    //我们有时候需要定义一个只读对象
    const Object obj1(688);
    cout<< "value:" << obj1.get_value()<<endl;
    obj1.set_value(300);

    cout<< "count:" << obj1.get_count()<<endl<<endl;

    /***** 新添加的代码1 end   *****/

    return 0;
}

这样子的代码提交给面试官他肯定会很高兴的。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值