2014-02-10 76 views
0

我一直在託管代碼編程大部分時間,我有興趣回到C++。 一直敲着我的頭(谷歌)找到答案。 所以我開始在這裏練習:http://www.cplusplus.com/forum/articles/12974/ 並且偶然發現了很多錯誤。 我試過可樂機(第二個),它給了我做一個可樂機的想法,只是想在一個初始化列表與指針飲料C++列表遍歷和初始化

我不想使用Boost庫,因爲我想了解容器如何工作(尤其是列表)。

我將張貼問題後我的代碼:

1)我收到以下錯誤的方法行(*it)->getDrinkName() EXC_BAD_ACCESSgetDrinkName()Drink.cpp這是爲什麼?我沒有正確初始化飲料清單嗎?

當我試試這個:

Drink* test = new Drink("Coke"); 
cout << test->getDrinkName(); 

它的工作原理。它在Drink中是我的構造函數嗎?

2)我是否想在Machine的構造函數中初始化列表?像:

_list = new list<Drink *>(); 

3) 下面是代碼:

Drink.h

#include <iostream> 
#include <string> 
using namespace std; 

class Drink 
{ 
public: 
    Drink(string name); 
    string getDrinkName(); 
private: 
    string _name; 
}; 

Drink.cpp:

#include "Drink.h" 

Drink::Drink(string name) 
{ 
    _name = name; 
} 

string Drink::getDrinkName() 
{ 
    return _name; 
} 

Machine.h

#include <iostream> 
#include <list> 
#include "Drink.h" 
using namespace std; 

class Machine 
{ 
public: 
    Machine(); 
    list<Drink*> getList() const; 
private: 
    list<Drink*> _list; 
}; 

Machine.cpp:

#include "Machine.h" 

Machine::Machine() 
{ 

} 
list<Drink*> Machine::getList() const 
{ 
    return _list; 
} 

的main.cpp

#include <iostream> 
#include <string> 
#include "Machine.h" 
using namespace std; 

int main() { 
    Machine* machine = new Machine(); 

    Drink* testCoke = new Drink("Coke"); 
    machine->getList().push_back(testCoke); 
    std::list<Drink*>::const_iterator it ; 
    for(it = machine->getList().begin();it!=machine->getList().end();it++) 
    { 
     cout << (*it)->getDrinkName(); 
     delete *it; 
    } 


    return 0; 
} 

Thanx提前!

+0

哎呀我忘了刪除,在這裏我加了!感謝名單。 我知道我可以拿出像他們使用像列表所有教程的所有動態分配...但我希望把指針在列表中,然後最終使用升壓,但現在我想知道爲什麼它<在使S崩潰地點。 – bachibusuc

+0

@juanchopanza雖然我同意他應該避免動態分配,但這不是問題的根源,這是一個迭代器範圍的問題。 – IdeaHat

+0

@bachibusuc添加'delete'只是使代碼變得更糟。真的退後一步,從一本好的C++書開始。 – pmr

回答

1

問題是您正在通過值返回容器,而不是引用。 machine-> getList()在每個調用中都創建一個副本,該副本在for循環中超出範圍。將其更改爲:

const list<Drink*>& Machine::getList() const; 

編輯:更加明確:

讓我們看看這個:

std::list<Drink*>::const_iterator it ; 
for(it = machine->getList().begin();it!=machine->getList().end();it++) 
{ 
    cout << (*it)->getDrinkName(); 
    delete *it; 
} 

第一次調用機 - >的GetList()創建一個額外的列表。我們調用.begin()來獲得指向該列表的第一個元素的指針。該列表超出了範圍,因此它被銷燬:out指針現在指向釋放內存。我們的迭代器(it)副本現在指向一個無效的位置。當我們尊重它(使用*(it))時,我們會看到您的錯誤。

+0

這不應該改變實際飲料*在列表中,有關係嗎?所以,這是他應該解決的一個問題,但我不認爲是造成這次事故的問題? –

+0

@TJBandrowsky問題是int'cout << (*it)-> getDrinkName();'迭代器指出它超出了範圍。我會讓這更explicite在我的答案 – IdeaHat

+0

這使得它!我會閱讀更多關於參考/價值回報。再次感謝! – bachibusuc

0

我會說,找出來,在循環做到這一點:

auto x = *it; 
cout << x->getDrinkName(); 
delete x; 

如果您設置的自動X線斷點,你應該能夠看到,如果x等於先前定義的testCoke。他們應該是一樣的。

2

首先,std::list應該只是容器,以瞭解當中的最後一個優先級。其次,明確地使用動態分配應該是比這更低的優先級。

如果我要模擬一個軟飲料機,這是一個公平的猜測,你不會在我寫的任何東西中找到一個明確的指針,newdelete或迭代器。我的第一個(當然簡體)版本可能會是這個樣子:

#include <map> 
#include <iostream> 
#include <string> 

int main() { 
    // Stores a Drink and a quantity of that drink. 
    // Establish initial stock according to drink quality. 
    std::map<std::string, int> machine{ 
     { "Coke", 2 }, 
     { "Mt Dew", 97 }, 
     { "Diet Coke", 1 } 
    }; 

    std::cout << "Please insert money and select from the following list:\n"; 
    for (auto const &s : machine) 
     if (s.second > 0) 
      std::cout << s.first << "\n"; 

    std::string temp; 
    std::getline(std::cin, temp); 
    while (machine.find(temp) == machine.end()) { 
     std::cout << "\rBad name. Please a name from the list."; 
     std::getline(std::cin, temp); 
    } 
    --machine[temp]; 
    std::cout << "\nEnjoy your " << temp << "\n"; 
} 

在探空居高臨下的風險,當前的代碼顯示了你的背景都非常清楚。從最古老的C++實踐開始,混合最糟糕的「可管理」代碼,並最終得到一個難以理解的混亂,只有 運行 跛行。

我的建議是,如果你要嘗試編寫C++,而不是從心態開始,比如:「我將會使用list和指針」,而是以「最開始」爲開頭:「什麼是最簡單的最有效的辦法來解決這個問題?」並採取相應的行動。

如果您是有效的解決辦法的印象,包括任何原始指針或listnewdelete用途,你可能應該停止,然後有,多做一些讀取和/或想法,因爲那樣的話是一個非常固體跡象表明,你可能不知道不足以解決目前的問題以及在所有。如果多一些讀書不讓你離開那個洞的,那麼很可能你正在閱讀一本書糟糕 - 不幸的是,對C++的好書是近一個罕見的(你可能要檢查的C++ Book List的建議)。

+0

不用擔心,謝謝你的評論和你的解決方案。正如我所說,我正在挖裏面。我可以在一個主要功能都做到了像你這樣(尤其是運動很簡單),但我只是想看看標題,類甚至指針如何實際工作。這個例子幫助我查看並閱讀了MadScienceDreams提到的價值/參考回報。 – bachibusuc