2013-10-27 61 views
0

我不得不簡化一些我的代碼來問這個問題。但是,在下面的代碼中,我沒有聲明x作爲參考類型,這意味着一旦函數退出,減量的更改就會「忘記」了。從函數內部改變對象狀態

解決這個問題的最聰明的方法是宣佈xAnotherClass& x

void MyClass::myFunc(unordered_map<int, AnotherClass>* dictionary, int z, int y){ 

    AnotherClass x = dictionary->at(z); 

    //Does this change on x get "forgotten" in terms of what dictionary stores 
    //once myFunc() has finished, because x is not a reference/pointer type? 
    x.changeSomething(y--); 
} 


class MyClass{ 
    public: 

    private: 
     myFunc(unordered_map<int, AnotherClass>* dictionary, int z); 
     unordered_map<int, AnotherClass>* dictionary 

}; 

回答

3

正確。 xdictionary元素的副本。您正在將更改應用到該函數的本地副本。您應該在來電方看到沒有效果。您可以乘坐參考,或直接在調用的結果採取行動at

dictionary->at(z).changeSomething(z--); 

注意,此無關的代碼的函數裏面是。

+0

只是一個額外的問題,如果我不是修改字典,但我創建了一個新的AnotherClass對象插入字典 - 我不需要申報新的AnotherClass對象作爲引用類型,它可以只是AnotherClass new_obj? – user997112

+0

@ user997112我不確定我是否理解這個問題,但也許這會澄清一些事情:1)參考必須引用某些內容。它只是一個對象的別名。 2)當你在地圖中放置一個對象時,地圖會自己創建該對象的副本。所以你*可以*給予通過地圖對另一個對象的引用,但它沒有區別,因爲地圖會複製它引用的對象。 – juanchopanza

+0

我認爲你無論如何都回答了 - 我無法聲明一個新的引用類型的字典元素,因爲如你所說,你需要一個現有的元素,而且我正在詢問一個新的元素進入字典。 – user997112

2

在編寫Thing t = s;時,在Java或C#等語言中,您實際上正在創建一個別名t,它指的是與s中引用的內存相同的對象。在C++中,然而,值和別名是嚴格分開:

  • Thing t = s;是有關使的s
  • Thing& t = s;爲約創建別名指相同的對象比s(基準)
  • 一個 拷貝
  • Thing* t = &s;爲約創建別名指相同的對象比s(指針)

的差值b在這裏引用和指針並不重要,重要的是副本和別名之間的區別。

  • 更改副本可以通過所有別名指的是物體

局部的副本

  • 通過別名更改對象是本地到該對象,並可見以你爲例:

    // Fix 1: take dictionary by *reference* and not by *pointer*. 
    void MyClass::myFunc(std::unordered_map<int, AnotherClass>& dictionary, int z, int y){ 
        // Fix 2: dictionary.at(z) returns a "AnotherClass&" 
        // that is an alias to the element held within the dictionary. 
        // Make sure not to accidentally make a copy by using that "&" 
        // for the type of x. 
        AnotherClass& x = dictionary.at(z); 
    
        // "x" is now a mere alias, the following call is thus applied 
        // to the value associated to "z" within "dictionary". 
        x.changeSomething(y--); 
    } 
    

    請注意,你可以寫dictionary.at(z).changeSomething(y--);在這種情況下;然而有幾個缺點:

    • 如果x被重複使用多次,命名它使它更清晰。
    • 在調用的函數/方法有副作用的情況下,調用次數很重要,需要加以控制。
    • 從性能的角度來看,避免不必要的計算反覆總是一樣的東西總是受歡迎的...但不要太掛性能;)