2011-07-31 40 views
10

我覺得這個問題已經足夠基本,可以在某處找到,但我似乎無法找到答案。聲明對象和賦值運算符的引用

假設我有這樣的代碼:

//class member function 
std::map< std::string, std::string > myMap; 

const std::map< std::string, std::string >& bar() 
{ 
    return myMap; 
} 

void myFunc(std::map< std::string, std::string >& foo1) 
{ 
    foo1 = bar(); 
    std::map< std::string, std::string >& foo2 = bar(); 
} 

我的理解是,如果我開始使用foo2的,因爲foo2的是同一個實例的引用作爲什麼吧()返回時,任何事情我foo2的辦會體現在myMap中。但是foo1呢? foo1是否獲取myMap的副本,或者它是否指向與bar()返回的實例相同的實例? C++標準庫說std :: map的賦值操作符會將元素複製過來,但這是否意味着賦值操作符在foo2的聲明中沒有被真正調用?

謝謝!

回答

15

引用不能在C++中重置。這意味着一旦它們初始化,就不能重新分配它們。相反,任何分配實際上都涉及被引用的對象。因此,在你的代碼,

foo1 = bar(); 
std::map< std::string, std::string >& foo2 = bar(); 

第一行調用被作爲參數傳遞myFunc的對象std::map::operator=。之後,foo1劇照指的是同一個對象 - 但它的價值(例如它擁有的元素)可能已經改變。

請注意,第二行是而不是如果您有任何疑問,請將其分配給您。相反,它是一個初始化。由於返回類型實際上是std::map<std::string, std::string> const&,因此它不能綁定到std::map<std::string, std::string>&,所以這是一個編譯錯誤。


爲了擴展事物的'哲學'一面,C++引用被設計成儘可能透明,並且不是作爲對象存在。這是使用術語的C++標準含義(它與OOP無關):這意味着例如參考類型而不是有一個大小。相反,sizeof(T&) == sizeof(T)。類似地,參考文獻沒有地址,並且不可能形成指針或參考文獻:給出int& ref = i;,然後&ref == &i

參考文獻因此有意使用好像所提及的對象本身正在使用。在引用的生命週期中唯一引用特定的是它的初始化:它可以綁定到什麼以及它在生命週期方面意味着什麼。

+0

+1謝謝,我自己學到了一些新東西。我只是做了一個測試,我確實是100%錯誤,你是對的= - ) – flumpb

+0

好了!謝謝,我真正需要知道的是賦值運算符在foo1中調用,並且不在foo2中調用。很好的解釋,謝謝! – bhh1988

+0

@Luc如果可能,你能否理解爲什麼通常不使用引用變量?我對它們是什麼有了更好的理解(感謝你的回答),但似乎編程人員普遍贊成對它的指示。它是多餘的嗎?範圍有限? –

0

foo1 = bar(); 

創建一個副本(因爲這是map的賦值操作符做什麼)。

+0

似乎很奇怪返回一個全局變量的引用,不是嗎? – 2011-07-31 00:33:37

+0

@ 0A0D:如果「全局」變量實際上沒有外部鏈接,則不是真的,它可以用於封裝。或者你可能返回一個對全局變量'a'或全局變量'b'的引用。 –