返回引用的 Const 方法

发布于 2024-10-17 02:21:28 字数 216 浏览 2 评论 0原文

class Foo
{
    int Bar;

    public:

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

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

class Foo
{
    int Bar;

    public:

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

Is it okay that GetBar is a const method? It's not actually changing anything, but it's providing the "outside world" with a means of changing it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

灼痛 2024-10-24 02:21:28

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

您必须将该方法更改为非常量,返回常量引用,或者通过将其标记为可变来使 Bar 免除承诺。例如:mutable int Bar; mutable 关键字告诉编译器该对象的逻辑常量不依赖于Bar 的状态。然后你就可以用它做任何你想做的事。

No, this is not legal. When tagging a method with const, not only are you promising you won't touch any of the internal state of the object, you also promise that you will not return anything that can be used to change the state of the object. A non-const reference may be used to modify the value of Bar outside the scope of GetBar(), hence you are implying that you cannot hold the promise.

You must either change the method to being non-const, return a const reference, or make Bar exempt of the promise by marking it as mutable. E.g.: mutable int Bar; The mutable keyword tells the compiler that the logical constness of the object does not depend on the state of Bar. Then you are allowed to do whatever you please with it.

ㄖ落Θ余辉 2024-10-24 02:21:28

不,因为你不能做以下作业:
常量 int x; int &y = x;

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

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

Nope, since you cant do the following assignment:
const int x; int &y = x;

What you can do though is const int x; const int &y = x;

And of course there is no problem in overloading the method and creating both const and non-const variants.

孤独患者 2024-10-24 02:21:28

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

因此,如果您尝试执行在该代码中所做的操作,您将收到编译错误,因为您将尝试使用以下代码初始化 int & (方法的返回值) const 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 方法在不改变其“逻辑”状态的情况下更改对象的“真实”状态;这对于实现惰性求值、引用计数等很有用。

No, you can't do that; in a const method you have a const this pointer (in your case it would be a const Foo *), which means that any reference you can get to its fields1 will be a const reference, since you're accessing them through a "const path".

Thus, if you try to do what you did in that code you'll get a compilation error, since you'd be trying to initialize an int & (the return value of your method) with a const int & (the reference you get from Bar), which obviously is forbidden.

g++ actually says:

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*’

which is what I just said. :)

If, instead, you return a const reference to a class field from a const method you'll have no problem.


  1. Excluding fields marked as mutable, which tells to the compiler that such fields are modifiable even from const methods; this exception has been introduced to allow const methods to change the "real" state of the object in cases when this do not alter its "logical" state; this can be useful to implement lazy evaluation, reference counting, ...
零崎曲识 2024-10-24 02:21:28

您可能想要返回 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;
                 ^

You probably want to return Bar, not &Bar. Anyway, I dropped this code in 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;
}

And got the error:

line 9: error: qualifiers dropped in binding reference of type
          "int &" to initializer of type "const int"
          return Bar;
                 ^
知足的幸福 2024-10-24 02:21:28

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

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

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

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

因此这是合法的:

class A
{
  Foo * foo;

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

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

The members of your class are considered const when you are in a const method. So although Bar is int within your class and not const int, in the context of GetBar() const it is "const int". Therefore returning it as a non-const reference or pointer is just as illegal as doing:

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

This breaks const-correctness even though the 2nd line has not actually changed anything (yet) in y.

Note incidentally that if your class has pointer members the only thing that is const is the pointers themselves and not what they point to. (Often referred to as "shallow" constness)

Thus this would be legal:

class A
{
  Foo * foo;

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

Note that in your original code you would be allowed to return Bar by non-const reference if it were mutable, because those members are not bound by the constness of member functions.

萌︼了一个春 2024-10-24 02:21:28

成员函数的 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.

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

const modifier to a member function doesn't allow to change the object's state with in it's scope. Compiler just checks whether this function is modifying the state of the object or not in its scope. Taking another example -

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.

So, compiler just checks access specifiers ( i.e., whether this variable is accessible or not in this scope) but not about the private/public/protected variable's memory location if returned to some other variable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文