【发布时间】:2019-09-15 09:12:44
【问题描述】:
我刚刚发现了一个有趣的案例:我通过const reference 传递了一个对象,但我仍然能够修改它的成员(恰好是lvalue reference)。 Following 就是一个例子:
#include <iostream>
#include <string>
struct PersonRef
{
PersonRef(std::string& name_) : _name(name_) {}
std::string& _name; // <==== IMPORTANT: it is a reference
};
void testRef(const PersonRef& pr) {
std::string& name = pr._name; // binding to lvalue reference? How does it even compile?
name = "changed!";
}
int main() {
std::string name = "trivial_name";
PersonRef pr{name};
std::cout << pr._name << "\n"; // prints: trivial_name
testRef(pr);
std::cout << pr._name << "\n"; // prints: changed!
}
我曾经认为如果参数由const ref 传递,那么对象是不可变的,但这里似乎不是这样。有人可以解释一下吗?谢谢!
【问题讨论】:
-
1) 传递
const &并不意味着对象是不可变的,这意味着引用具有const限定符,这将影响重载决议 2) 你永远不会修改它的成员,你修改一个非其成员引用的 const 限定对象;请注意,即使您使用Person const &访问_name,它也不会将_name的类型调整为std::string const &。如果_name是指针std::string *,那么const限定符将应用于指针,因此它将变为std::string * const,但默认情况下引用不可重新绑定,因此std::string & const什么也不做。 -
好的,所以也许,基本问题是:1) 如果我通过
const PersonRef&访问_name,为什么它的类型没有调整为const std::string&。这是我所预料的。 2) std::string & const 什么都不做 是什么意思?如果我将_name声明为const std::string&,则此代码无法编译,因为在将其绑定到函数内部的non-const lvalue reference时,我无法忽略它的cost-ness。 -
通过 const 限定引用访问类成员确实会为类成员添加 const 限定符。但是
_name成员是一个引用,它具有一级间接性。 const 限定符不通过该间接杠杆传播,它仅直接应用于类成员。访问_name会产生std::string & const而不是std::string const &,正如您所期望的(您似乎对const位置感到困惑)因为引用不可重新绑定std::string & const的行为方式与std::string &完全相同。 -
谢谢,很有道理!我对
std::string & const和std::string const &感到困惑
标签: c++