2

会議のリストがあります。

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 ->'

私はまだc++を学んでいるので、私が間違っていることを理解できれば幸いです。また、

  • 関数からオブジェクトへの参照を返すのは良い習慣ですか?何か良いことはありますか?
  • リスト内の項目が変更されたために、一部の参照が無効になる可能性がありますか?

ありがとう

4

6 に答える 6

13

会議のリストがあります。

いいえ、しません。会議へのポインタのリストがあります。その1つの誤解から、さらにすべてのエラーが発生します。

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

会議のリストがある場合、このコードは正しいでしょう。会議へのポインタのリストがある場合は間違っています。試す:

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

次:

return *it;

試す:

return **it;


別の方法として、おそらく「会議のリスト」が本当に必要なのかもしれません。その場合、次のようにリストを宣言します。

std::list<meeting> meetings;

どちらが必要かわかりません。会議のリストまたは会議へのポインタのリストです。それはあなたのプログラムの残りの部分のデザインと関係があります。コンテナをポインタでいっぱいに保つことはほとんどありません。

たとえば、同じ会議を参照するために複数のリストエントリが必要な場合は、ポインタのリストが必要になることがあります。(「10時に安倍と、11時にボブとチャックと、そしてまた10時に安倍と会う」?)

meetingをコピーすることが不可能または非常に高価な場合は、ポインタのリストが必要になることもあります。その場合は、ネイキッドポインターではなく、スマートポインターを使用することをお勧めします。

他の質問に答えるには、はい、オブジェクトへの参照を返すことは良いことです。そのオブジェクトの存続期間を知っておく必要があります。破棄された後は、参照を介してオブジェクトにアクセスしないでください。

于 2012-05-15T16:05:47.923 に答える
6

オブジェクト会議へのポインタである場合は、**itを返す必要があります。参照を返すことは問題ありませんが、後でそれをどうするかについて注意してください。ポインタが機能する方法は、参照を編集すると、リスト内の項目も変更され、その逆も同様です。

于 2012-05-15T16:05:37.463 に答える
4

あなたは持ってstd::list<meeting*>::iteratorいますが、あなたの関数はを返すことを約束しますmeeting&

*itあなたがそれが「指し示す」ものをあなたに与えるようにイテレータに求めていると言うとき、それはこの場合はmeeting*静止しているでしょう。したがって、実際の会議を取得するには、それを逆参照する必要もあります。例:

return **it; 
于 2012-05-15T16:03:12.473 に答える
3

上記のすべてを踏まえて、次のことを宣言することをお勧めします。

std::list<meeting> meetings;

それ以外の:

std::list<meeting*> meetings;

(これに対応してイテレータitをに変更します) 。特に何らかの理由で自分で実行したい場合を除いて、メモリ関連のすべての作業をコンテナstd::list<meeting>::iterator;に任せます。std::list

参照を返すことについて、答えはあなたのニーズに依存します。オブジェクト全体を呼び出し元の関数に返したい場合は、参照を返すことをお勧めします。

const meeting& day::findMeeting(float startHour)また、返されたオブジェクトを読み取り専用にする場合、つまり呼び出し元の関数がオブジェクトにアクセスできるがオブジェクトを変更できない場合は、const-referenceの使用を検討してください。

于 2012-05-15T16:13:03.853 に答える
1

答えよりもコメントですが、コメントを入れるには大きすぎます。

宣言されているように、参照を指定して関数を呼び出すことはできませんconst day&。あなたはそれを修正することを検討するかもしれません。

aを変更する行為が、の変更Meetingでもある場合はday、関数をオーバーロードします。

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

2番目の定義が必要になることを除いて、2つの定義はほとんど同じに見えますconst_iteratorfindMeetingこれで、で呼び出された場合はconst 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これで、メソッド(およびfriends)のみがMeetingに属するsを変更できdayます。変更可能な会議を見つけるために別のprivate方法が必要な場合もありますが、この場合は、過負荷ではなく、別の名前にする必要があります。

于 2012-05-15T16:17:07.010 に答える
1

これはあなたの質問に直接関係していませんが、フロートが等しいかどうかを比較するときは注意が必要です。浮動小数点数は正確ではなく、==と比較するのは安全ではありません。

http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htmをご覧ください

于 2012-05-15T16:20:19.423 に答える