成员函数返回类成员变量的引用,有存在修改成员变量的值的风险。

桃扇骨 2023-01-11 09:10 168阅读 0赞

很多时候我们将函数返回值设置为引用类型,这样可以提高函数返回的效率,而如果我们在类成员方法中这样做了,很可能会出一些问题。

参考如下代码:我们通过设置类成员方法 data() ,本意是想查看类私有变量的数值,为了提高效率我们增加了引用。

  1. class Object {
  2. private:
  3. int value;
  4. public:
  5. Object(int x = 10) :value(x) {
  6. };
  7. int& data() {
  8. return value; }
  9. };
  10. int main()
  11. {
  12. Object obj(10);
  13. obj.data() = 11;
  14. cout << "val : " << obj.data() << endl;
  15. return 0;
  16. }

可以看到,我们使用obj.data() = 11;这条语句可以将obj对象的私有属性obj.value修改,这就造成了很大的安全隐患。

而我们即想要提高返回值效率,又不想变量在外部被修改,那么我们只需将返回值设置为常引用即可。

  1. const int& data() {
  2. return value; }

这里的常引用指的是常量左值引用const Type&类型,而声明为常引用之后此函数的返回值就无法再修改我们的类私有成员属性了。
在这里插入图片描述

同理,在类成员函数后加const,也能有效的阻止成员函数自身修改类属性。原理是在类的成员方法中有个隐藏的this指针,它的类型是Object * const类型(这里限制了this不可改变指向)。

而我们添加了const参数后,它作用于此this指针后变成Object const * const类型(这里同时限制this不可改变指向,也不可修改所指向空间的数据) 。

因此,成员函数后声明为const后视为常方法,即函数内不可以对类成员属性做修改(同理也不可调用类的非常量方法,因为存在修改类成员属性的风险),但可以修改其他不通过this指针调用的变量,比如传入的形参。

参考以下示例:

  1. class Object {
  2. private:
  3. int value;
  4. public:
  5. Object(int x = 10) :value(x) {
  6. };
  7. const int& data() {
  8. return value; }
  9. void show()
  10. {
  11. cout << typeid(this).name() << endl;
  12. }
  13. void show() const
  14. {
  15. cout << typeid(this).name() << endl;
  16. }
  17. };
  18. int main()
  19. {
  20. Object obj(10);
  21. obj.show(); // 普通对象调用普通方法
  22. const Object Cobj(10);
  23. Cobj.show(); // 常对象调用常方法
  24. return 0;
  25. }

在这里插入图片描述
注:Object * const this 修饰的是this所指向之值不可被修改,对指针自身并没有限定,因此我们使用typeid 输出this的类型时为 Object * 类型,具体const修饰指针案例请参考下面给出的整理:

const 对指针修饰时的情况及含义(const 在*左边,则修饰的是“p”,const 在右边,修饰的是p)

  • const int * p <=等价=> int const *p :指针p所指的内存单元为常量,不可修改该内存
  • int * const p:指针p自己是常量,该指针的地址值不可修改。const int *p = new int(); 这里的 p 被const限定
  • const int * const p :以上两种情况都包含:既不可修改指针值也不可修改指针所指位置的值。

声明为的成员函数 const 不能更改成员数据-在此类函数中, this 指针是指向 const 对象的指针。
——参考自《https://docs.microsoft.com/zh-cn/cpp/cpp/this-pointer?view=msvc-160》

发表评论

表情:
评论列表 (有 0 条评论,168人围观)

还没有评论,来说两句吧...

相关阅读

    相关 静态成员变量

    类的静态成员变量 coding时遇到一个需求,抽象出来大概意思就是:A类的一个静态成员变量,需要在B类里面赋值,然后在C类里面使用。知识点:类的静态成员变量需要在全局域进