0

我有一个多线程程序(客户端-服务器程序,但在这个问题中不一定相关),其中多个线程访问全局队列。有两个队列:哪个是 type msgs_inc,我的班级在哪里。clients_msgqueue<msgInfo>msgInfo

第一个线程从客户端接收消息,执行以下操作(相关片段):

msgInfo message_processed(message_fr_client); //line 1: takes in string 
msgs_inc.push(message_processed); //line 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

第三个线程从 中检索clients_msg,之后不再需要它。

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

我的问题是:

  1. 在第 3 行中,这个构造函数(下文详述)是被称为复制构造函数还是标准构造函数?
  2. 我是否错误地“实例化”msgInfo了两次,即在将其推入之前一次,然后在检索它之前再一次?我应该使用指针或其他东西吗?感觉它可能效率低下,但我不知道另一种方法。
  3. 我什么时候应用析构函数?我是否只在第 7 行之后应用它,当我不再需要它时,或者我是否需要在第 4 行再次应用析构函数,因为我已经msgInfo使用该信息创建了另一个实例?

对于这种乏味,我深表歉意-我找不到有关此的信息,也无法得出一个具体的结论。


这是我的课:

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() );

这会调用复制构造函数(因为它会复制);在您的情况下,编译器提供的复制构造函数就足够了。

至于实例化msgInfo两次,您实际上是在实例化它更多,因为它是从原始实例复制到队列中,然后从队列复制到第二个线程。这没有什么问题。C++ 旨在为使用值语义提供特权,否则需要特殊处理。如果后来发现复制是性能瓶颈,那么您可以修复它。std::list(可能是通过降低复制成本,而不是通过移动到指针。例如,摆脱它。)

如果确实使用指针,则必须考虑所有权问题。您不能只传递局部变量的地址。如果有人修改数据,让两个或多个线程访问相同的数据是非法的。

至于你的最后一个问题:不调用(我认为这就是你所说的“应用”的意思)析构函数(至少在使用值语义时)。编译器为局部变量自动调用它,当对象从队列中移除时,队列的底层容器调用它。就此而言,您也不调用构造函数:当您定义一个对象时,编译器会为您调用它,而当对象被复制到队列中时,队列会执行复制。

最后,您没有显示任何同步逻辑。我认为这仅仅是因为您将其删除以简化演示,并且您确实知道一旦有多个线程就需要同步访问。

于 2013-03-27T09:13:15.727 回答