在 C++ 中: const 引用是指“只读视图”还是需要被引用对象的不变性?
Posted
技术标签:
【中文标题】在 C++ 中: const 引用是指“只读视图”还是需要被引用对象的不变性?【英文标题】:in C++: Is const reference means "read-only view of" or it requires immutability of object being referenced? 【发布时间】:2014-03-16 12:31:12 【问题描述】:问题可以通过例子表述如下:这段代码的sn-p是否有效?
int a = 1;
const int& ca = a;
++a; //< Q: Is this valid?
cout << "a: " << a << endl;
cout << "ca: " << ca << endl; // Q: Is it guaranteed to output "2"? Is it valid at all?
使用 MSVC 和 MinGW,上面的 sn-p 按预期工作:如果我在后面查询 ca
,它会返回 2
(即它被非常量引用更改)。但问题是:如何从标准的角度考虑这种情况?可以更改对象,我们有 const 引用(或者例如,我们必须将 ca
定义为 const volatile 引用,以便 sn-p 正确)?
所以,如果上面的 sn-p 是正确的,那么这意味着 const 引用不能保证被引用的对象是常量。它只禁止我们通过给定的引用来改变它,即建立被引用对象的“只读”视图。这是正确的吗?
编辑: 感谢所有回答我问题的人。答案说明了事情,这对我来说似乎很自然。但是,我真的很感激有人参考 c++ 标准中的特定条款。
编辑2: 扩展了原始示例以使问题的概念更加清晰。
编辑3 另一个例子,最初出现在我对 Mats Peterson 答案的评论中。
class MyClass
public:
// ...
const X& getX() const;
void modifyX();
private:
X m_x;
;
void someFun()
//...
MyClass myObj = ... // non-cons
const X& x = myObj.getX();
// ...
myObj.modifyX(); // Q: is `x` guaranteed to track value of x stored in myObj here?
问题是:在优化期间是否允许编译器删除x
变量的更新,因为它被声明为const
?例如。如果类型 X
是 bool
,则按值存储 x
比按引用存储提供更好的性能和更少的内存消耗。
换句话说:如果后续调用myObj
的方法修改了该内部值,是否保证局部变量x
将跟踪myObj
内部相应内部值的变化?
【问题讨论】:
"这意味着,const 引用并不能保证被引用的对象是常量。它只是禁止我们通过给定的引用来改变它,即建立被引用对象的“只读”视图" 这与我回答的评论中的示例仍有很大不同。在某些可能的情况下,要弄清楚到底发生了什么是极其复杂的。 我会说在上面的代码中修改a
是绝对合法的。
我记得有一种奇怪的感觉,必须同步来自 const 引用的读取。我知道只有当 ref 引用的对象最初声明为 const 时,抛弃 const 才是 UB。
【参考方案1】:
这是有效的代码,因为a
不是const
。 const
引用意味着您不能通过引用修改所引用的对象。
【讨论】:
【参考方案2】:在这种特殊情况下,您所做的只是创建一个const
的引用——这意味着ca
不能修改它所引用的值(在这种情况下为a
)。
一种常见的用法是将 const 引用传递给函数:
void foo(const int& cr)
... use cr ...
这表明虽然该值是一个引用,但函数foo
不会改变cr
中的值。使用可修改的int
变量或什至无法引用的变量(例如foo(4);
- 值 4 只是一个常量,因此不能真正用作参考)调用此函数是完全有效的- 编译器将通过创建一个临时 int 变量来“修复”这个问题,并将引用传递给它)。
当然,这更常用于比int
更复杂的类型——例如std::string
或std::vector
。在这种情况下,主要原因是避免复制值,而不是“我想要参考”。
【讨论】:
更相关的是以下示例的分析师:const X& x = myObj.getConstX(); myObj.modifyX();
。问题是:本地x
是否可以保证跟踪myObj
的相应内部数据的变化?当然mhObj
不是常量。
嗯,这是一个完全不同的问题,可能真的应该作为一个单独的问题提出。我不知道标准是否规定了这一点。可以很容易地看出,如果标准没有要求,编译器可以优化 x
的读取,并且只使用以前读取的值。
是的,完全正确。这不是另一个问题,这正是我从一开始就提出的问题。虽然,现在我明白了,我最初的例子并没有清楚地突出主要思想。我会努力解决的。
使用 g++ 4.6.3 和 clang++ 的一个非常简单的测试表明这些东西似乎没有得到优化。换句话说,对象内部的变化确实会改变引用中的实际值。这是你所期望的,至少是这样的。
@DmitrySemikin:不,这是一个不同的问题。 :) 引用总是精确地“跟踪”所指对象,但是是否在对同一对象的两次单独读取中获得正确的结果,而两者之间的写入在当前翻译单元中可能不可见,这是一个完全不同的问题(而不是与参考文献本身相关)。以volatile
为例。【参考方案3】:
因为引用只是对变量的另一个名称,而不是对象本身,是的,在您显示的 sn-p 中,它可以被认为是只读引用。引用提供的代码只能访问它,但它不保证对象本身不会在程序的其他地方被更改。
【讨论】:
以上是关于在 C++ 中: const 引用是指“只读视图”还是需要被引用对象的不变性?的主要内容,如果未能解决你的问题,请参考以下文章
C++中的const关键字深入理解(关于引用指针顶层const)
C++,在函数中采用 const lvalue 和 rvalue 引用
C++ 成员引用基类型'Vertex *const'不是结构或联合