const引用传递的类的引用成员行为的设计原因
Design reasons for the behavior of reference members of classes passed by const reference
假设有代码
#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;
}
内部g()不允许对y调用f(),因为a是用const修饰符传递的然而,y的值可以在g()中通过对x调用f来修改;
有了指针,类似的东西可以得到非常相似的
struct B{
int* x;
}
和
g(const B&){
*x++;
}
是允许的。这一点非常清楚:我们有一个指向非常量int的常量指针。但是在前面的引用示例中,如果引用是对象,为什么在这种情况下它们表现为指针?这种行为下的设计策略是什么?
如果引用是对象
引用是而不是对象——它们是对对象的引用。
你说得对,将引用本身设为const并不是很有用:因为它们是不可重新密封的,所以在任何情况下都不能像指针一样进行变异。
事实上,将引用视为具有特殊语法的const指针(而不是指向const的指针!)可能会更有帮助。
请注意,如果想要一个间接方法,它确实为引用对象提供常量(即,为了防止这里的f(a.x)
调用),您可以编写一个智能指针样式的东西来实现它。
的具体示例
struct A
{
int x;
int *p;
int &r;
A() : x(0), p(&x), r(x) {}
};
现在处于A a
:
a.x
是可变inta.p
是指向可变int的可变指针(因此我们可以重新放置它)(我们可以更改它指向的整数的值)- 并且
a.r
是对可变int的引用- 请注意,由于我们无论如何都不能更改(重新设置)引用,因此引用本身是常量或可变的并不意味着什么
但在const A b
:中
b.x
是一个常量整数b.p
是一个指向可变int的常量指针(因此我们无法重新定位它)b.r
是对可变int的引用- 注意constness是如何应用于A的成员(指针或引用)的,并且不按比例传递到引用
标准中的实际语言是
c++11
8.3.2参考文献[dcl.ref]
1-[…][注:引用可以被认为是对象的名称。--尾注]
因此,如果引用是一个对象的名称,而不是对象本身,那么使封闭结构为const
会使名称为const
(这毫无意义,因为引用不能反弹),但不是对象本身。
我们也看到
6-如果typedef、类型模板参数或decltype说明符表示类型TR即对类型T的引用,尝试创建类型"对cvTR的左值引用"会创建类型"T的左值参考"[…]
由于对cv对象的成员访问会创建cv左值,因此同样适用,cv资格将被取消。
在C++中,引用通常由指针实现。(我认为sizeof
a引用和指针是相同的)。
事实上,我通常认为引用是指针,但语法不同。
相关文章:
- 具有引用成员的结构是否具有唯一的对象表示形式
- 初始化右值引用成员
- C++通过绑定到引用成员而缩短临时变量寿命?
- C++为具有引用成员变量的类创建复制构造函数
- 常量和引用成员函数限定符
- C++将引用成员绑定到构造函数参数
- 如果包含引用成员的类中缺少原始变量,为什么它仍然可以访问?
- 初始化指针或引用成员变量以指向另一个成员
- 将常量引用成员设置为临时变量是否安全
- 对象超出范围后,引用成员设置为 0
- 复制构造函数初始化初始化列表中的引用成员会导致指针悬空
- 使用默认构造函数引用成员变量初始化错误
- 如何从派生类访问引用成员变量?
- Visual Studio 2017 允许在构造函数中使用自身初始化引用成员.真的是合法的C++吗?
- 为什么当类具有引用成员时C++编译器不删除复制构造函数
- 引用成员到构造函数参数按值传递
- 在执行不平凡的构造函数之前引用成员
- 具有引用成员变量的多态性
- 从按值构造函数参数初始化的引用成员
- 深度复制包含引用成员(C++)的结构