3

Suppose to have the code

#include <iostream>

struct A{
  int y;
  int& x;
  A():y(0),x(y){}
};



void f(int& x){
  x++;
}

void g(const A& a){
  f(a.x);
  //f(a.y);
}


int main(){
  A a;
  g(a);
  std::cout<<a.y<<std::endl;

}

inside g() calling f() on y is not allowed because a is passed with the const modifier however, the value of y can be modified inside g() by calling f on x;

With pointers, a similar things can be obtained very similarly

struct B{
  int* x;  
}

and

g(const B&){
   *x++;
}

is allowed. This is perfectly clear: We have a const pointer to non-const int. But in the previous reference example, if references ARE the object, why do in this case they behave as pointers? What are the design policies under this behavior?

4

3 回答 3

4

if references ARE the object

references are not objects though - they're references to objects.

You're right that making a reference itself const isn't very useful: since they're non-reseatable, they can't be mutated like pointers in any case.

In fact, it might be more helpful to think of a reference as a const pointer (not a pointer-to-const!) with special syntax.

Note that if you want an indirection which does propogate constness from the referee to the referent (ie, to prevent the f(a.x) call here), you can write a smart pointer-style thing to do it.


Concrete example

struct A
{
    int x;
    int *p;
    int &r;

    A() : x(0), p(&x), r(x) {}
};

Now in A a:

  • a.x is a mutable int
  • a.p is a mutable pointer (so we can reseat it) to a mutable int (we can change the value of the integer it points to)
  • and a.r is a reference to a mutable int
    • note that since we can't mutate (reseat) references anyway, it doesn't mean anything for the reference itself to be either const or mutable

... but in const A b:

  • b.x is a constant integer
  • b.p is a constant pointer (so we can't reseat it) to a mutable int
  • b.r is a reference to a mutable int
    • note how the constness is applied to the member of A (the pointer or reference) and does not propogate through to the referent.
于 2012-07-31T12:21:27.917 回答
3

The actual language in the standard is

8.3.2 References [dcl.ref]

1 - [...] [ Note: A reference can be thought of as a name of an object. —end note ]

So if a reference is a name of an object, not an object itself, then it makes sense that causing the enclosing structure to be const makes the name const (which is meaningless, as references can't be rebound), but not the object itself.

We also see

6 - If a typedef, a type template-parameter, or a decltype-specifier denotes a type TR that is a reference to a type T, an attempt to create the type “lvalue reference to cv TR” creates the type “lvalue reference to T” [...]

Since member access on a cv object creates a cv lvalue, the same applies and the cv qualification is extinguished.

于 2012-07-31T12:21:50.560 回答
0

In C++ references are usually implemented by pointers. (I think that the sizeof a reference and pointer are the same).

Indeed I usually think of references as pointers, but with different syntax.

于 2012-07-31T12:19:00.643 回答