2017-02-26 38 views
-1

为什么编译?C++常量在参考上丢失

struct A {}; 
struct B { 
    B(A& _a) : a(_a) {} 
    A &a; 
}; 

void f1(A&) {} 
void f2(const B &b) { f1(b.a); } 

int main() { 
    A a; 
    B b{a}; 
    f2(b); 
    return 0; 
} 

f2()b是const,所以我的理解是b.a也应该是const。但它编译并且编译器允许调用f1()。

替换为'A &';'在结构B中用'A a'它不再有效。 现在F1()b.a确实是常量:

invalid initialization of reference of type 'A&' from expression of type 'const A' 

请帮我理解这...谢谢。

回答

5

当对象是const时,它不会导致引用成员也变为const,因为引用不是对象本身的一部分。引用成员只是代表其他对象地址的一条信息。 B对象本身是否是不可变的,不应该影响是否应该可能对它引用的对象进行变异。

如果使B::a成员非基准,如A a;,那么B对象实际上将自身内部包含一个A对象,所以当前者是const,后者也将如此。

1

Inside f2() b is const, so my understanding was that b.a should also be const.

它是。如果实例是const那么它的成员也是。但看看会员的类型:

A & a; 

这是对A的参考。使该const产生一个恒定参考A

A & const a; 

一个参照本发明的恒定A

+0

错误:'const'限定符不能应用于'A&' – Jarek

+0

谁说的? (在什么情况下?)是的,它是[完全多余](https://isocpp.org/wiki/faq/const-correctness#const-ref-nonsense)。无论如何,它更像是思想实验;) –

0

严格地说,没有恒定的引用。有对常量对象的引用。

在类B的数据成员a被声明等向型A.

A &a; 

的非恒定对象的引用和该引用作为参数传递给一个函数,它接受一个引用传递非恒定对象

void f1(A&) {} 
void f2(const B &b) { f1(b.a); } 

因此代码编译成功。