2014-02-10 80 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