0

複数のスレッドがグローバルキューにアクセスするマルチスレッドプログラム(クライアントサーバープログラムですが、この質問には必ずしも関係ありません)があります。2つのキューがあります:msgs_incそしてclients_msg、タイプはqueue<msgInfo>msgInfo私のクラスです。

最初のスレッドは、クライアントからメッセージを受信し、次のことを行います(関連するスニペット)。

msgInfo message_processed(message_fr_client); //line 1: takes in string 
msgs_inc.push(message_processed); //line 2

2番目のスレッドは、から取得してmsgs_inc処理し、にプッシュすることになっていますclients_msg

msgInfo msg_from_queue(msgs_inc); //line 3: retrieve from front of queue
msgs_inc.pop(); //line 4
clients_msg.push(msg_from_queue); //line 5

3番目のスレッドはから取得しますclients_msg。その後は不要になります。

msgInfo msg_from_queue(clients_msg); //line 6: retrieve from front of queue
clients_msg.pop(); //line 7

私の質問は:

  1. 3行目で、このコンストラクター(以下で詳しく説明します)は、コピーコンストラクターと標準コンストラクターとして知られていますか?
  2. msgInfo「インスタンス化」を2回、つまりプッシュする前に1回、取得する前にもう一度行うのは間違っていますか?代わりにポインタなどを使用する必要がありますか?非効率に感じるかもしれませんが、他の方法はわかりません。
  3. デストラクタを適用するのはいつですか?必要がなくなった7行目以降にのみ適用しますか、それともmsgInfo情報を使用して別のインスタンスをすでに作成しているため、4行目でデストラクタを再度適用する必要がありますか?

この退屈さについての私の謝罪-私はこれについての情報を見つけることができず、具体的な結論をまとめることができません。


これは私のクラスです:

class msgInfo
{
public:
    msgInfo();
    msgInfo(std::string); //creating instance fr string rxed fr client
    msgInfo(std::map<int, std::map<int, std::queue<msgInfo>>>, int, int); //creating instance for string to be sent to client

    ~msgInfo();

private:
    int source_id;
    int dest_id;
    int priority;
    std::string payload;
    std::list<int> nodePath;
};

3行目と6行目で使用されているコンストラクター:

msgInfo::msgInfo(std::queue<msgInfo> outgoing_msg)
{
    source_id = outgoing_msg.front().source_id;
    dest_id = outgoing_msg.front().dest_id;
    priority = outgoing_msg.front().priority;
    payload = outgoing_msg.front().payload;
    nodePath = outgoing_msg.front().nodePath;
}
4

1 に答える 1

1

キューからのコンストラクターは使用しません。これは紛らわしいです。次のように書く方がはるかに優れています(そして明確になります)。

msgInfo msg_from_queue( msgs_inc.front() );

これにより、コピーコンストラクターが呼び出されます(コピーを作成するため)。あなたの場合、コンパイラが提供するコピーコンストラクタで十分です。

2回インスタンスmsgInfo化する場合、実際にはそれ以上にインスタンス化されます。これは、元のインスタンスからキューにコピーされ、次にキューから2番目のスレッドにコピーされるためです。これには何の問題もありません。C ++は、値のセマンティクスの使用を優先するように設計されており、それ以外の場合は特別な処理が必要です。後でコピーがパフォーマンスのボトルネックであることが判明した場合は、それを修正できます。(おそらく、ポインターに移動するのではなく、コピーをより安価にすることによって。std::listたとえば、それを取り除きます。)

ポインタを使用する場合は、所有権の問題を考慮する必要があります。ローカル変数のアドレスだけを渡すことはできません。また、誰かがデータを変更している場合、2つ以上のスレッドが同じデータにアクセスすることは違法です。

最後の質問については、デストラクタを呼び出さないでください少なくとも、値のセマンティクスを使用する場合は、「適用する」という意味だと思います)。コンパイラーはローカル変数に対して自動的に呼び出し、オブジェクトがキューから削除されると、キューの基になるコンテナーがそれを呼び出します。さらに言えば、コンストラクターも呼び出さないでください。オブジェクトを定義すると、コンパイラーがそれを呼び出し、オブジェクトがキューにコピーされると、キューがコピーを実行します。

最後に、同期ロジックは表示されていません。これは、デモンストレーションを簡素化するために削除しただけであり、複数のスレッドがあるとすぐにアクセスを同期する必要があることを知っているからだと思います。

于 2013-03-27T09:13:15.727 に答える