何时使用构造函数和析构函数,尤其是在容器和跨线程中

时间:2013-03-27 08:49:34

标签: c++ multithreading class constructor destructor

我有一个多线程程序(客户端 - 服务器程序,但在这个问题中不一定相关),其中多个线程访问全局队列。有两个队列:msgs_incclients_msg,其类型为queue<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实例?
  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;
    }
    

1 个答案:

答案 0 :(得分:1)

使用队列中的构造函数。这是 混乱。写得好得多(也更清晰):

msgInfo msg_from_queue( msgs_inc.front() );

这会调用复制构造函数(因为它会复制);在 你的情况,编译器提供的拷贝构造函数是 足够的。

至于实例化msgInfo两次,你实际上是 实例化它不止于此,因为它是从你的复制 原始实例进入队列,然后从队列到 第二个线程。这没什么不对。 C ++是 旨在特权使用值语义,并做 否则需要特殊处理。如果它后来证明了这一点 复制是一个性能瓶颈,你可以修复它。 (可能是通过使副本更便宜,而不是通过移动 指针。例如,摆脱那个std::list。)

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

关于你的上一个问题:不打电话(我猜是的 你是什​​么意思“应用”)析构函数(至少在使用时) 价值语义)。编译器自动为本地调用它 变量和队列的底层容器调用它 从队列中删除对象时。就此而言,你 不要调用构造函数:当你定义一个对象时, 编译器会为您调用它,并在复制对象时调用它 队列进入队列后执行复制。

最后,您没有显示任何同步逻辑。 我认为这只是因为你被删除了 简化演示,并确保您知道所需 一旦有多个线程就立即同步访问。