我正在审核Boost网站上的HTTP Server 3示例。 connection类中有以下代码:
boost::tribool result;
boost::tie(result, boost::tuples::ignore) = request_parser_.parse(request_, buffer_.data(), buffer_.data() + bytes_transferred);
其中parse
声明为
template <typename InputIterator>
boost::tuple<boost::tribool, InputIterator> parse(request& req, InputIterator begin, InputIterator end)
我认为目标是将tribool
的返回值复制到本地变量。但是,如果可以编写类似
boost::tie
)执行此操作的重点是什么
boost::tuple<boost::tribool, char*> result = request_parser_.parse(request_, buffer_.data(), buffer_.data() + bytes_transferred);
// Our tribool is available via result.get<0>();
答案 0 :(得分:9)
好处不是性能,而是实用性和可读性:因为您对parse
返回的第二个对象不感兴趣,所以没有必要保留它。最好完全忽略它,只获得你真正感兴趣的结果,即tribool
。以下使用result
的代码将更加清晰。
实际上,当一个函数返回多个数据时,通常有用(就可读性而言)将其“拆分”以分别获取各个元素。例如,考虑std::set<T>::insert
,它返回元素的迭代器以及指示它是否是新插入的布尔值。您觉得以下哪些代码更清晰:
std::set<int> s;
std::pair<std::set<int>::iterator, bool> res = s.insert(42);
if (res.second)
{
doSomething(res.first);
}
VS
std::set<int> s;
std::set<int>::iterator itInsertedElement;
bool isNewlyInserted;
tie(itInsertedElement, isNewlyInserted) = s.insert(42);
if (isNewlyInserted)
{
doSomething(itInsertedElement);
}
在我看来,后者更容易阅读。
答案 1 :(得分:3)
我认为他们主要是为了方便而使用tie
。如果您不需要InputIterator
,只需要tribool
值,为什么要创建命名变量?
此:
boost::tribool result;
boost::tie(result, boost::tuples::ignore) = request_parser_.parse(request_, buffer_.data(), buffer_.data() + bytes_transferred);
成为这个:
boost::tuple<boost::tribool, char*> results = request_parser_.parse(request_, buffer_.data(), buffer_.data() + bytes_transferred);
boost::tribool result = boost::get<0>(results); // or you can use boost::get<0>(results) everywhere you use it.
你的筹码完全无用results
。
从boost:tie
返回的临时值可能会被编译器优化,因此不应该有任何内存开销。
答案 2 :(得分:2)
我认为这只是一个语义考虑因素。
.get<0>()
result
变量仅与有用的部分绑定,不需要其他变量。此处的性能不应受到影响,因为编译器会将其视为:
boost::tuple<boost::tribool, char*> __tmp = request_parser_.parse(/**/);
boost::trilbool result;
boost::tie(result, boost::tuples::ignore) = __tmp;
然后优化器会尽可能地消除这种情况并尽可能减少这种情况。
答案 3 :(得分:0)
我怀疑是否存在任何可衡量的性能差异(当然不能与IO成本相比),但简单地引用result
而不是使用get<0>()
将其从元组中删除会更方便。