返回引用的Const方法

时间:2011-02-10 12:24:14

标签: c++ class methods const

class Foo
{
    int Bar;

    public:

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

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

6 个答案:

答案 0 :(得分:19)

您的代码中有拼写错误,这可能是您的意思:

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,返回const引用,或通过将其标记为Bar使mutable免除承诺。例如:mutable int Bar; mutable关键字告诉编译器对象的逻辑const不依赖于Bar的状态。然后你可以用它做任何你想做的事。

答案 1 :(得分:4)

不,因为你不能做以下任务: const int x; int &y = x;

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

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

答案 2 :(得分: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;
                 ^

答案 3 :(得分:1)

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

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

因此,如果您尝试执行在该代码中执行的操作,则会出现编译错误,因为您尝试使用{{初始化int &(方法的返回值) 1}}(你从const int &获得的参考),显然是被禁止的。

实际上,g ++说:

Bar

这就是我刚才所说的。 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*’

相反,如果您从:)方法返回对{class}字段的const引用,那么您将没有任何问题。


  1. 排除标记为const的字段,它告诉编译器即使从mutable方法也可以修改这些字段;引入此异常是为了允许const方法在不改变其“逻辑”状态的情况下改变对象的“真实”状态;这对于实现延迟评估,引用计数,......非常有用。

答案 4 :(得分:1)

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

一样非法

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

这打破了const-correctness,即使第二行实际上没有改变y中的任何东西。

顺便提一下,如果你的类有指针成员,唯一的const就是指针本身,而不是指向它们的指针。 (通常称为“浅”常量)

因此这是合法的:

class A
{
  Foo * foo;

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

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

答案 5 :(得分:0)

对成员函数的

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.

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