[英]Mutable Lvalue Reference of Parameter Passed by const Reference
我剛發現一個有趣的情況:我通過const reference
傳遞了一個對象,但仍然能夠修改其成員(恰好是一個lvalue reference
)。 以下是一個示例:
#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
傳遞的,則對象是不可變的,但在這里似乎並非如此。 有人可以解釋一下嗎? 謝謝!
請注意,在const
成員函數中,數據成員_name
本身將被視為const
。 _name
沒什么區別,因為它是一個引用,不能為const
限定的。 (在某種意義上,引用始終是const
,您不能修改引用本身,引用不能在初始化后反彈到其他對象。)
另一方面,被引用的對象不會成為const
,因此仍然可以對其進行修改, _name
不會成為const std::string&
(對const
引用)。
指針成員也會發生類似的情況。 在const
成員函數,他們成為const
指針,而不是指向const
; 如果指向對象從一開始就不是const
則仍然可以對其進行修改。
考慮一個不同的例子。
假設您有struct A {int *x;};
。
通過const A &ref
訪問時, x
類型為int *const
const
指向(non- const
) int
的const
指針。
如您所見, const
不會遞歸地添加到指針。 它僅在頂層添加。
回到您的代碼。 嚴格來說, const PersonRef& pr
不是const
引用。 這是對 const PersonRef
的非const
引用。
(理論上, const
引用將寫為PersonRef &const pr
。但是由於引用不能一開始就可以重新綁定,因此添加const
不會做任何事情,因此是不允許的。因此從技術上講,引用永遠不是const
,即使您無法重新綁定它們。)
編譯器無法將const
-ness添加到std::string& _name
,因為引用不能是const
。 並且它不會遞歸地將const
-ness添加到所引用的類型,僅僅是因為這就是語言的工作方式。
如果您不希望出現這種情況,請將std::string& _name
設為private
並添加一對const
和非const
指針:
class PersonRef
{
std::string &_name;
public:
PersonRef(std::string& name_) : _name(name_) {}
std::string &name() {return _name;}
const std::string &name() const {return _name;}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.