簡體   English   中英

常量參考傳遞的參數的可變左值參考

[英]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- constintconst指針。

如您所見, 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM