2017-01-03 44 views
-2

我想創建存儲的情況下,在地圖像這樣一類:C++地圖拋出向量下標越界

class Apple { 
    public: 
     static Apple* getApple(const std::string &name) { 
      auto it = allApples.find(name); 

      if (it == allApples.end()) // if this apple doesnt exist, make a new one 
       return new Apple(name); 
      else // if the apple exists, return its pointer 
       return it->second; 
     } 
    private: 
     static std::unordered_map<std::string, Apple*> allApples =     
      std::unordered_map<std::string, Apple*>(); 

     Apple(const std::string &name) { 
      // create an apple 
      allApples.insert({ name, this }); 
     } 
} 

現在,我做了哪些存儲靜態蘋果像這樣的類:

class Orange { 
    static Apple *myOrangeApple; 
} 

myOrangeApple = Apple::getApple("orange"); 

當我運行程序時,它在getApple()方法的第一行崩潰,矢量下標超出範圍錯誤。我試圖四處尋找,但我無法找到任何解決地圖和超出範圍錯誤的解決方案。我從我做的一些研究中得出的最好的猜測是,它是關於靜態順序初始化的東西,但我確實不太確定。

+0

第一行你的意思是'auto it = allApples.find(name);'?我沒有看到任何與'std :: vector'或下標操作符相關的東西。 – songyuanyao

+0

@songyuanyao,是的那一行是拋出調試斷言/異常(在發佈版本中)。我沒有看到任何與矢量相關的東西,這就是爲什麼我很困惑。 –

+0

你能給我們足夠的代碼,以便我們可以編譯它並複製問題嗎? –

回答

1

使用函數範圍的靜態對象。

... 
private: 
    std::unordered_map<std::string, Apple*>& allApples() { 
     static std::unordered_map<std::string, Apple*> apples; 
     return apples; 
    } 

這是對抗靜態初始化順序失敗的標準方法之一。它的工作原理是因爲在第一次執行塊時保證了塊範圍的靜態對象被初始化。

如果以這種方式管理的對象之間存在相互依賴關係,則此方法將不起作用。

+1

這是一個很好的建議,但作爲一個答案,如果你解釋了*爲什麼這會更好,那將會更好。 –

0

第一件事你的getApple方法應該是靜態的,你應該在類之外初始化類成員(靜態成員)。試試這個吧 -

class Apple { 
    public: 
     static Apple* getApple(const std::string &name) { 
      auto it = allApples.find(name); 

      if (it == allApples.end()) // if this apple doesnt exist, make a new one 
       return new Apple(name); 
      else // if the apple exists, return its pointer 
       return it->second; 
     } 
    private: 
     static std::unordered_map<std::string, Apple*> allApples; 

     Apple(const std::string &name) { 
      // create an apple 
      allApples.insert({ name, this }); 
     } 
}; 

std::unordered_map<std::string, Apple*> Apple::allApples = std::unordered_map<std::string, Apple*>(); 

class Orange { 
    static Apple *myOrangeApple; 
}; 

Apple * Orange::myOrangeApple=Apple::getApple("orange"); 
+0

我有我的代碼,我應該改變它在這裏,我只是不認爲這是相關的問題。 –

+0

@ThomasPaine沒有足夠的代碼來複制問題,任何人都無法判斷相關與否。 –

0

你在訪問allApples它被初始化之前。在您輸入main之前,不能保證allApples已經構建,因此訪問它是一個明確的禁止。

將自己添加到容器中的類是一個壞主意,但在全局對象中執行它確實很糟糕。不要這樣做。

+0

但是,當我在斷點前打印出'allApples'的大小時,它會讓我爲零,這意味着'allApples'被初始化了,是正確的嗎?如果'allApples'沒有被初始化,那麼它會不會是未定義的行爲呢? –

+0

@ThomasPaine這是你的代碼中的另一個錯誤。你必須調用'size'直到'allApples'確保被初始化爲UB。你碰巧得到零,這會誤導你。這就是爲什麼你不應該這樣做! –

+0

這就是爲什麼你應該儘可能少地在構造函數和析構函數中進行操作 - 控制它們執行的上下文非常困難。擁有從全局靜態構造函數中調用的這麼多代碼是非常困難的。你怎麼能保持這個代碼,而不用在整個過程中發出大的警告,說:「不要做任何不合法的事情在主要之前」並通過所有被調用的函數來傳播它?瘋。 –