2015-08-25 60 views
3

如果我有一個地圖一類的作爲關於地圖和迭代器

class MyClass 
{ 
    public: 
    MyClass(); 
    std::map<std::string, std::string> getPlatforms() const; 
    private: 
    std::map<std::string, std::string> platforms_; 
}; 

MyClass::MyClass() 
     : 
{ 
    platforms_["key1"] = "value1"; 
    // ... 
    platforms_["keyN"] = "valueN"; 
} 

std::map<std::string, std::string> getPlatforms() const 
{ 
    return platforms_; 
} 

而且在我的主要功能會有這兩段代碼之間的差異這樣一個私有成員理論澄清?

代碼1:

MyClass myclass(); 
std::map<std::string, std::string>::iterator definition; 
for (definition = myclass.getPlatforms().begin(); 
    definition != myclass.getPlatforms().end(); 
    ++definition){ 
    std::cout << (*definition).first << std::endl; 
} 

代碼2:

MyClass myclass(); 
std::map<std::string, std::string> platforms = myclass.getPlatforms(); 
std::map<std::string, std::string>::iterator definition; 
for (definition = platforms.begin(); 
    definition != platforms.end(); 
    ++definition){ 
    std::cout << (*definition).first << std::endl; 
} 

在代碼2我剛剛創建了一個新的地圖變量來保存地圖從getPlatforms()函數返回。無論如何,在我的真實代碼中(我不能發佈實際的代碼,但它直接對應於這個概念)第一種方式(代碼1)導致運行時錯誤,無法訪問某個位置的內存。

第二種方式有效!

您能否告訴我這兩個不同代碼片段之間的理論基礎?

回答

7

getPlatforms()按照值返回地圖,而不是參考,這通常是一個壞主意。

,你們充分展示了爲什麼這是一個壞主意一個例子:

getPlatforms().begin()是地圖,使用前迭代器和getPlatforms().end()是來自同一個原始地圖上的不同副本的迭代器,沒有了上一個迭代。

+0

正如喬指出getPlatforms()是const,所以通過非const引用返回映射將是一個問題。 (從const方法返回值是沒有問題的,但正如我試圖解釋的那樣,按值返回是一個壞主意)。所以你想通過'const&'返回,在這種情況下,Joe對const_iterator的描述將會變得正確。 – JSF

+0

謝謝。如果您不介意的話,可以附帶一些後續問題:(1)如何通過引用返回地圖? (2)通過引用還是按值返回對象最好? – nonremovable

+0

而不是'std :: map getPlatforms()const;''你使用'std :: map const&getPlatforms()const;那麼你需要切換到你的code1的const_iterator。 – JSF

-2

您遇到的問題是您應該使用const_iterator而不是iterator。這是因爲函數getPlatformsconst限定的,而映射iterator begin()中的函數不是;您必須使用const合格的const_iterator begin() const,而不是明確告訴編譯器,您將不會修改該類的任何成員。

注意:這只是針對碼1,應順便返回const&

+2

錯誤。 'getPlatforms()'的返回值是* not *'const'限定的,所以完全可以使用它的變異迭代器。 – Angew

+0

@AngeW - 對不起,我忘了澄清,它只發生在'const&'返回類型 – Joe

+0

'const'不是問題。他們有一個不再存在的對象的迭代器。 – NathanOliver

1

你可以告訴我,什麼是這兩個不同的代碼塊之間正在進行的理論基礎的情況下?

當您按值返回時,將返回數據的深層副本。

當你打電話myclass.getPlatforms().begin();myclass.getPlatforms().end();你有效地構建您的數據的兩個副本,然後讓從一個副本,並從其他結束迭代的開始迭代器。然後,你比較兩個迭代器是否相等; 這是未定義的行爲

由於無法訪問某個位置的內存而導致運行時錯誤。

這是因爲definition被初始化,則使用的臨時對象來創建它被刪除,迭代器指向的數據無效。然後,您嘗試通過迭代器使用數據。