正确使用迭代器从列表中返回一个对象

时间:2012-05-15 16:00:45

标签: c++

我有一份会议清单:

std::list<meeting*> meetings;

我想迭代列表并返回对特定会议的引用:

meeting& day::findMeeting( float StartHour )
{
std::list<meeting*>::iterator it;
for(it = meetings.begin(); it != meetings.end(); it++)
{
    if (it->getStartHour() == StartHour)
    {
        return *it;
    }
}
throw no_such_meeting_error;
}  

我收到以下错误:

  1. 'getStartHour' : is not a member of 'std::_List_iterator<_Mylist>'
  2. 'return' : cannot convert from 'meeting *' to 'meeting &'
  3. invalid return type 'meeting **' for overloaded 'operator ->'
  4. 我还在学习c ++,所以很高兴能够理解我做错了什么。此外,

    • 从函数返回对象的引用是一种好习惯吗?还有更好的事吗?
    • 由于列表中项目的更改,某些引用可能会失效吗?

    由于

6 个答案:

答案 0 :(得分:13)

  

我有一份会议清单。

不,你没有。你有一个会议指针列表。从那一个误解,你所有的进一步错误都在流动。

if (it->getStartHour() == StartHour)

如果您有会议列表,此代码将是正确的。如果你有一个会议指针列表是错误的。尝试:

if ((*it)->getStartHour() == StartHour)

下一步:

return *it;

尝试:

return **it;

<小时/> 或者,也许你真的想要一个“会议清单”。在这种情况下,您可以声明您的列表:

std::list<meeting> meetings;

我不知道你想要哪一个 - 会议列表或会议指针列表。这与您计划的其余部分的设计有关。我几乎从不保持一个装满指针的容器。

您可能需要一个指针列表,例如,如果您需要多个列表条目来引用同一个会议。 (“我和Abe在10点开会,与Bob和Chuck在11点开会,然后在10点与Abe再次会面”?)

如果复制meeting不可能或过于昂贵,您也可能需要一个指针列表。在这种情况下,我建议你使用smart pointer而不是裸指针。

要回答您的其他问题,是的,返回对象的引用是一件好事。您需要了解该对象的生命周期;永远不会在销毁后通过引用访问对象。

答案 1 :(得分:6)

是指向对象会议的指针时,你必须返回它。返回引用很好,但请注意稍后使用它做什么。指针的工作方式是,如果您编辑引用,列表中的项也将被更改,反之亦然。

答案 2 :(得分:4)

您有std::list<meeting*>::iterator,但您的函数承诺会返回meeting&

当你说*it要求迭代器给你“指向”的东西时,在这种情况下它仍然是meeting*。因此,您还需要取消引用以获得实际会议,例如:

return **it; 

答案 3 :(得分:3)

如上所述,我建议你宣布:

std::list<meeting> meetings;

而不是:

std::list<meeting*> meetings;

(相应地将迭代器it更改为std::list<meeting>::iterator;),并让std::list容器为您完成所有与内存相关的工作,除非您特别想自己做某种原因。

关于返回参考,答案取决于您的需求。如果要将整个对象返回给调用函数,返回引用是个好主意。

另外,考虑使用const-reference,const meeting& day::findMeeting(float startHour),如果希望返回的对象是只读的,,调用函数能够访问对象但不能更改它

答案 4 :(得分:1)

更多的评论而不是答案,但是太大而无法发表评论。

如声明的那样,在给定const day&引用的情况下无法调用该函数。你可以考虑解决这个问题。

如果修改Meeting的行为也是对day的修改,则重载该函数:

class day {
public:
  Meeting& findMeeting(float StartHour);
  const Meeting& findMeeting(float StartHour) const;
  //...
};

这两个定义看起来大致相同,除了第二个定义需要const_iterator。现在findMeetingconst day&上调用时会返回const Meeting&,或者如果在day&上调用,则会返回可修改的Meeting

或 -

如果修改Meeting不会修改day,那么只需允许以任一方式调用该函数,并始终返回可修改的Meeting

class day {
public:
  Meeting& findMeeting(float StartHour) const;
  //...
};

或 -

如果班级day的用户根本无法修改其Meetings,请执行相同操作,但始终返回const Meeting&

class day {
public:
  const Meeting& findMeeting(float StartHour) const;
  //...
};

现在只允许class day种方法(和friend s)修改属于Meeting的{​​{1}}。您可能还需要另一个day方法来查找可修改的会议,但在这种情况下,它应该具有不同的名称,而不是过载。

答案 5 :(得分:1)

这与您的问题没有直接关系,但在比较浮点数是否相等时应该小心。浮点数不准确,将它们与==进行比较是不安全的。

查看http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm