C++ 从队列返回对象的最快方法,但仅当队列中有对象时

C++ 从队列返回对象的最快方法,但仅当队列中有对象时,c++,C++,假设我正在编写一个简单的线程安全队列 template <class T> class ThreadSafeQueue { T pop() { std::unique_lock<std::mutex>{mutex}; if (q.empty()) //throw auto t = q.front(); q.pop(); return t; } //...

假设我正在编写一个简单的线程安全队列

template <class T>
class ThreadSafeQueue
{
T pop()
    {
        std::unique_lock<std::mutex>{mutex};
        if (q.empty())
            //throw
        auto t = q.front();
        q.pop();
        return t;
    }
//...
并在
pop
中返回此元素,但这将涉及在我访问它时不必要地复制
T
至少一次。而且,当它不返回任何元素时,它仍然会创建它


检查,在ThreadSafeQueue之外,是否<代码>队列是空的,如果是,调用<代码> POP也不起作用,因为在这两个安全操作的中间,它可能丢失一个对象

正如SamVarshavchik在他的评论中所指出的那样。当调用

pop()
时,返回
std::optional
是处理堆栈为空的意外情况的一种好方法:

std::optional<T> pop()
{
    std::unique_lock<std::mutex>{mutex};
    if (q.empty()) return std::nullopt;
    auto t = q.front();
    q.pop();
    return t;
}

// Calling code
std::optional<string> myVal = myQueue.pop();
if (myVal) std::cout << "Popped: " << *myVal << std::endl;
std::可选的pop()
{
std::unique_lock{mutex};
if(q.empty())返回std::nullopt;
自动t=q.前();
q、 pop();
返回t;
}
//呼叫码
std::可选的myVal=myQueue.pop();

如果(myVal)std::cout您的
PossibleElement
重新发明了一个名为
std::optional
的轮子。只需在此处使用
std::optional
。请参阅您最近的最新C++书籍,了解使用<代码> STD::可选< /COD>。您的代码> UNQuijyLoo.<代码>是临时的。抛出异常可能相对昂贵,因此您不应该在正常情况下设计程序以抛出异常——而不是只有当某个错误严重到性能不再是最重要的问题时(而应该从错误中干净地恢复),才应该抛出异常。不要尝试创建线程安全的集合类。他们天生就是有车的,而且会有比赛条件。只需使用std::collections,让您的功能代码在场景级别而不是类的每个方法上使用适当的锁。有关为什么尝试使收集线程安全是有风险的更详细示例,请参见。@selbie谢谢,我喜欢这种建议,我将按照您的建议执行。这是非常有帮助的
std::optional<T> pop()
{
    std::unique_lock<std::mutex>{mutex};
    if (q.empty()) return std::nullopt;
    auto t = q.front();
    q.pop();
    return t;
}

// Calling code
std::optional<string> myVal = myQueue.pop();
if (myVal) std::cout << "Popped: " << *myVal << std::endl;
bool pop(T & retVal)
{
    std::unique_lock<std::mutex>{mutex};
    if (q.empty()) return false;
    retVal = q.front();
    q.pop();
    return true;
}

// calling code
std::string myVal;
if (myQueue.pop(myVal)) std::cout << "Popped: " << myVal << std::endl;
T pop()
{
    std::unique_lock<std::mutex>{mutex};
    if (q.empty()) return T();
    auto t = q.front();
    q.pop();
    return t;
}

// calling code
std::string myVal = myQueue.pop();
if (myVal.size() > 0) std::cout << "Popped: " << myVal << std::endl;