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;
}
//...
我想pop
从队列中返回一个元素,但前提是它有一个元素。目前在 m 实现中,它会引发异常。但是抛出异常是否代价高昂?我应该这样做吗?
我也可以像这样定义一个简单的类:
PossibleElement{
T t;
bool has = false;
}
并返回这个元素,但是当我可以访问它时,它会涉及到至少一次不必要的pop
复制。T
此外,当它没有返回任何元素时,它仍然会创建它。
在 ThreadSafeQueue 之外检查是否queue
为空,只有如果是,调用pop
也将不起作用,因为在这两个安全操作的中间它可能会丢失一个对象
解决方案
正如@SamVarshavchik 在他的评论中指出的那样,返回 astd::optional
是处理调用时堆栈为空的意外情况的一种好方法pop()
:
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;
推荐阅读
- java - java 可选:如果做某事模式
- javascript - 过滤具有多个值的对象数组
- javascript - AWS 从 ReceiptHandle 获取 SQS 队列名称
- python - 将 for 循环输出存储在一个变量中
- php - 如何从参数数组中查询任何值与教义数组中的任何值匹配的行
- json - 来自 json 的树表 html
- python - 通过 PIP 在虚拟环境中安装 NLTK - Python3 - Windows 64 位
- java - 使用 NativeMethodAccessor 而不是 GeneratedMethodAccessor 时缺少 Lambda 堆栈跟踪
- node.js - 尝试使用 _id 更新文档时,获取“BSON 字段“update.updates.collation”是错误类型“字符串”,预期类型“对象”
- html - HTML 语言切换器可访问性