通过引用传递向量然后调用清除

Posted

技术标签:

【中文标题】通过引用传递向量然后调用清除【英文标题】:Pass Vector by Reference Then Call Clear 【发布时间】:2017-11-27 16:19:31 【问题描述】:

我很好奇在通过引用传递后清除 client.cpp 中的data_received 向量时是否一直在处理未定义的行为?我从来没有遇到过无效数据的问题,但我可以看到这可能是一个问题vector 一直通过引用传递到最终队列 - 同时另一个线程将在 queue_event.notify_all() 触发后以自己的速率出队。

如果这是一个问题,我相信解决方案可能会在 blocking client->receive 调用之后立即清除。想法?

blocking_queue.h

template <typename T>
class BlockingQueue 
    ...
    std::queue<T> queue;
    ...
;

blocking_queue.cpp

template <class T>
void BlockingQueue<T>::enqueue(T const &item)

    std::unique_lock<std::mutex> lk (queue_lock);
    queue.push(item);
    lk.unlock();
    queue_event.notify_all(); 


template <class T>
T BlockingQueue<T>::dequeue()

    std::unique_lock<std::mutex> lk (queue_lock);
    if(queue_event.wait_for(lk, std::chrono::milliseconds(dequeue_timeout))  == std::cv_status::no_timeout)
    
        T rval = queue.front();
        queue.pop();
        return rval;
    
    else
    
        throw std::runtime_error("dequeue timeout");
    

client.cpp

void Client::read_from_server()

    std::vector<uint8_t> data_received;

    while(run)
    
        if (client->is_connected())
           
            uint8_t buf[MAX_SERVER_BUFFER_SIZE];
            int returned;

            memset(buf, 0, MAX_SERVER_BUFFER_SIZE);
            returned = client->receive(client->get_socket_descriptor(), buf, MAX_SERVER_BUFFER_SIZE);
            // should probably move data_received.clear() to here!!
            if (returned > 0)
            
                for (int i = 0; i < returned; i++)
                
                    data_received.push_back(buf[i]);
                

                if (incoming_queue)
                
                    incoming_queue->enqueue(data_received);
                

                data_received.clear();
            
            else
            
                client->set_connected(false);
            
            
    

【问题讨论】:

【参考方案1】:

由于data_received.clear();,我看不到任何潜在的UB,因为std::queue&lt;T&gt; queue; 将在调用incoming_queue-&gt;enqueue(data_received); 时保存传递的项目(向量)的副本。

如果对队列的访问很好地同步,看起来就是这样,那么代码应该是安全的。

【讨论】:

啊,这就是const 在 void std::queue push (const value_type& val); 中的作用? @atomSmasher 这与const ness 无关。明确指出使用push_back The new element is initialized as a copy of value (或者如果值是临时的或者编译器确定不再需要该值的状态,则作为移动副本)。在您的情况下,Tvector&lt;uint8_t&gt;,因此它将被复制或移动,无论哪种情况,之后清除它都不会有任何问题。事实上,任何container&lt;T&gt; 在传递T 时都会复制或移动传递的T。只有当T 是指针类型时才需要担心。 哇。你是对的。它在那里;平淡如日。我想我需要新眼镜。

以上是关于通过引用传递向量然后调用清除的主要内容,如果未能解决你的问题,请参考以下文章

C++:试图理解通过引用传递向量

通过引用传递 - 左值和向量

C++ 通过引用传递向量字符指针

通过引用传递向量内联

通过引用传递向量的 typedef 向量

通过引用返回通过引用传递的向量的实用程序