【问题标题】:Const Methods that Return References返回引用的 const 方法
【发布时间】:2011-06-24 19:53:55
【问题描述】:
class Foo
{
    int Bar;

    public:

    int& GetBar() const
    {
        return Bar;
    }
}

GetBarconst 方法可以吗?它实际上并没有改变任何东西,但它为“外部世界”提供了一种改变它的方法。

【问题讨论】:

  • 我想你已经回答了你的问题。此外,在示例中 Bar 已经公开。
  • &Bar 的类型为 const int*,而不是 int&。你的编译器应该告诉你这是不行的。
  • 你试过编译吗?编译器告诉你什么?
  • @Charles :这条评论和对我帖子的评论很有意义。所以我删除了我的帖子。谢谢。 :-)

标签: c++ class methods constants


【解决方案1】:

您的代码中有错字,这可能是您的意思:

class Foo
{
    int Bar;

    public:

    int& GetBar() const
    {
        return Bar; // Removed the ampersand, because a reference is returned, not an address
    }
}

不,这是不合法的。当使用const 标记方法时,您不仅保证不会触及对象的任何内部状态,还保证不会返回任何可用于更改对象状态的东西。非 const 引用可用于在 GetBar() 范围之外修改 Bar 的值,因此您暗示您无法遵守承诺。

您必须将方法更改为非常量,返回一个 const 引用,或者通过将 mutable 标记为 mutable 使 Bar 免除承诺。例如:mutable int Bar; mutable 关键字告诉编译器对象的逻辑常量不依赖于Bar 的状态。然后你就可以随心所欲了。

【讨论】:

    【解决方案2】:

    不,因为您不能执行以下任务: const int x; int &y = x;

    你可以做的是const int x; const int &y = x;

    当然,重载方法并创建 const 和非 const 变体当然没有问题。

    【讨论】:

      【解决方案3】:

      您可能想返回Bar,而不是&Bar。无论如何,我在 Comeau 中删除了这段代码:

      class Foo
      {
          int Bar;
      
          public:
      
          int& GetBar() const
          {
              return &Bar;
          }
      };
      
      int main(int argc, char** argv)
      {
        Foo x;
        int y = x.GetBar();
        y = 5;
        return 0;
      }
      

      得到了错误:

      line 9: error: qualifiers dropped in binding reference of type
                "int &" to initializer of type "const int"
                return Bar;
                       ^
      

      【讨论】:

        【解决方案4】:

        首先,要返回一个引用,您不需要在被引用对象上使用 & 运算符;如果您想获得指向它的 指针,则需要它。所以,我假设你想写return Bar;

        那么,不,你不能那样做;在const 方法中,您有一个const this 指针(在您的情况下它将是一个const Foo *),这意味着您可以访问其字段的任何引用1 将是const 引用,因为您通过“const 路径”访问它们。

        因此,如果您尝试执行您在该代码中所做的操作,您将收到编译错误,因为您将尝试使用 const int & 初始化 int &(方法的返回值)(你从Bar得到的引用),这显然是被禁止的。

        g++ 实际上是这样说的:

        testconstref.cpp: In member function ‘int& Foo::GetBar() const’:
        testconstref.cpp:9: error: invalid initialization of non-const reference of type ‘int&’ from a temporary of type ‘const int*’
        

        这就是我刚才所说的。 :)

        相反,如果您从 const 方法返回对类字段的 const 引用,则没有问题。


        1. 排除标记为mutable 的字段,这告诉编译器这些字段甚至可以从const 方法修改;引入此异常是为了允许const 方法在不改变其“逻辑”状态的情况下更改对象的“真实”状态;这对于实现惰性求值、引用计数等很有用...

        【讨论】:

          【解决方案5】:

          当您使用 const 方法时,您的类的成员被视为 const。因此,尽管Bar 在您的班级中是int 而不是const int,但在GetBar() const 的上下文中它是“const int”。因此,将其作为非常量引用或指针返回与这样做一样非法:

          const int y = 57; int& z = y;

          这会破坏 const 正确性,即使第二行实际上还没有改变 y 中的任何内容。

          请注意,如果您的类有指针成员,那么唯一的 const 就是指针本身,而不是它们指向的内容。 (通常称为“浅”常量)

          因此这是合法的:

          class A
          {
            Foo * foo;
          
            public:
              Foo * getFoo() const // legal. does not have to return const Foo *
              {
                 return foo;
              }
          };
          

          请注意,在您的原始代码中,如果 mutablemutable,则允许您通过非常量引用返回 Bar,因为这些成员不受成员函数的 const 约束。

          【讨论】:

            【解决方案6】:

            const 对成员函数的修饰符不允许在其范围内更改对象的状态。编译器仅检查此函数是否在其范围内修改对象的状态。再举一个例子——

            class foo
            {
                int num ;
                public :
                   foo( int anum )
                   {
                       anum = 10;
                   }
                   int getNum()
                   {
                       return num;
                   }
             };
            
             foo obj;
             int& myNum = obj.getNum() ; // myNum is just an alias to the private class variable num
             myNum = 40; // Actually changes the content of the private variable.
            

            因此,编译器只检查访问说明符(即,此变量是否在此范围内可访问),而不检查私有/公共/受保护变量的内存位置(如果返回给其他变量)。

            【讨论】:

              猜你喜欢
              • 2017-03-19
              • 2013-10-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-12-11
              • 2021-12-21
              相关资源
              最近更新 更多