【问题标题】:Return constant reference from non-const function return reference value从非常量函数返回引用值返回常量引用
【发布时间】:2020-07-06 23:36:00
【问题描述】:

我有一个类,其中通过引用获取某个成员涉及逻辑,所以我为它创建了一个私有 getter 函数,它在内部工作正常。

我还想提供对相同引用的公共访问,但使用常量修饰符。 由于 public 函数不应修改类的状态,因此使用 const 关键字声明。 但是内部逻辑,因为它通过设计提供对内部成员的引用,所以不应将其声明为 const。

我如何能够使用相同的逻辑来获取引用,并同时提供 const 和非 const 访问点?

这里有我遗漏的模式吗?

下面我编译了一个小例子来演示:

class my_class{
public:

  const int& get_my_field() const{
    return get_my_field_ref(); //g++: error: error - passing 'const my_class' as 'this' argument discards qualifiers [-fpermissive]
  }

private:
    int field;

    int& get_my_field_ref(){ //g++: warning: note - in call to 'int& my_class::get_my_field_ref()'
      /* ..complex logic to get reference.. */
      return field;
    }
};

【问题讨论】:

  • 为什么get_my_field_ref() 必须是非const
  • 因为 'g++: error error - 将 'int&' 类型的引用绑定到 'const int' 如果它是 const 则丢弃限定符
  • 我了解您遇到的错误。我特别问为什么函数get_my_field_ref() 必须是非const - 而你没有回答。
  • 哦,非常感谢您的耐心等待!该接口专门用于内部修改field
  • 使field 成为mutable 成员。这允许在 const 成员函数中对其进行更改。

标签: c++ reference const-correctness


【解决方案1】:

有些人只要你知道注意事项,你就可以这样做:

int& get_my_field_ref(){'
  /* ..complex logic to get reference.. */
  return field;
}
const int& get_my_field_ref() const {
  return const_cast<my_class&>(*this).get_my_field_ref();
}

请注意,const 成员函数或多或少地保证了它可以在不引起数据竞争的情况下使用(也就是线程安全的)。您应该将complex logic 实现为线程安全的。

另外,请确保永远不要在已定义 const 的对象上调用您的函数。 (const 引用和指针只要追溯到非常量对象就可以了。)

【讨论】:

  • 对“某些人”来说太糟糕了,因为这样做会引入未定义的行为。
  • @Peter True,但前提是他们在 const 对象上使用该函数。我已经编辑了答案。
  • 谢谢,我接受了这个答案。但是我决定从 get_my_field 成员函数中删除 const 修饰符更安全。
  • @Peter:如果非常量 get_my_field_ref 修改了对象的状态(并且对象本身被声明为 const),则只有 UB。
【解决方案2】:

想了想,问题主要出在设计上。

示例程序没有提到的是“复杂逻辑”是在数组中获取索引。因此,考虑到这些信息,计算索引的逻辑可以分开,并在 const 和 non-const 接口中使用。

#include <iostream>

using namespace std;


class my_class{
public:

  const int& get_my_field() const{
    return field[complex_logic_to_get_reference()];
  }

private:
    int field[5];

    int complex_logic_to_get_reference() const{
      int result_index = 0;
      /* Complex logic to get reference */
      return result_index;
    }

    int& get_my_field_ref(int index){
      return field[complex_logic_to_get_reference()];
    }
};

int main(int argc, char *argv[])
{
    return 0;
}

我向@j6t 和@Peter 道歉,因为在发布问题时忽略了这些信息,这个概念现在才真正被点击。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-10
    • 2014-03-13
    • 1970-01-01
    • 2017-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多