C++ 什么';async_resolve的boost::asio::ip::tcp::resolver::iterator的生存期是多少?
当我调用C++ 什么';async_resolve的boost::asio::ip::tcp::resolver::iterator的生存期是多少?,c++,sockets,boost,tcp,boost-asio,C++,Sockets,Boost,Tcp,Boost Asio,当我调用boost::asio::ip::tcp::resolver::async_resolve时,我的处理程序接收到一个迭代一个或多个ip::tcp::resolver::条目的ip::resolver::iterator他们的生命是什么?是什么把柄让他们活着? 例如,如果我获取第一个条目并启动一个到它的tcp::async\u connect,那么在async\u connect处理程序中,我可以迭代到下一个条目并启动另一个到下一个条目的async\u connect(当然,只要我将迭代器
boost::asio::ip::tcp::resolver::async_resolve
时,我的处理程序接收到一个迭代一个或多个ip::tcp::resolver::条目的ip::resolver::iterator
他们的生命是什么?是什么把柄让他们活着?
例如,如果我获取第一个条目
并启动一个到它的tcp::async\u connect
,那么在async\u connect
处理程序中,我可以迭代到下一个条目
并启动另一个到下一个条目的async\u connect
(当然,只要我将迭代器
传递给异步连接
处理程序)
什么时候清理resolver::iterator
和resolver::entries
呢?我需要做什么特别的事情,还是让它们超出范围而不被任何回调闭包占用
(我知道我可以在我的async\u resolve
处理程序中运行所有resolver::entries
,并将它们存储在一个智能点结构或任何东西中,这样我就可以控制它们的生存期,但如果asio::ip::tcp::resolver
已经在处理它,我的代码就会简单一些,只要让它完成它的工作就行了。)解构问题
迭代器具有值语义。因此,迭代器的生存期始终与周围对象的生存期或其存储持续时间(堆栈用于自动,堆用于动态,有时甚至与其他对象(例如静态)绑定)
我想你应该知道迭代器的有效性
那么,迭代器类别是。前向迭代器具有“多路径保证”,允许迭代器副本的重复解引用,从而产生相同的结果
所以,我们已经做了一半:保留迭代器还是可以的。但是,当然,就像任何其他[forward]迭代器一样,我们必须考虑
因此,真正的问题可以归结为:什么时候解析器迭代器失效
我们知道什么?
resolve
函数实现的用例是连接。对于连接,第一个有效的端点就足够了,因此它不需要实际保留一个列表
本着“按需付费”的精神,解析器将状态保持在所需的时间之外是没有意义的。另一方面,如果不支持多路径,迭代器将处于ForwardIterator类别中是没有意义的
文档什么也没说。我们只有一个办法:深入代码
深入研究代码
我们发现表面以下的一些步骤:
因此,只要您保留一个有效的迭代器(而不是最终迭代器)的副本,您就可以继续取消引用它。它甚至会在每个解析器条目中保留一个查询参数(host\u name
和service\u name
)的副本。这似乎有点浪费,但我认为在设计缓存方案时可能会派上用场
总结:
- Q.解析器迭代器何时失效
- A.当有效迭代器的最后一个副本被销毁时
也就是说“它们总是有效的”(如果它们曾经有效的话)
与例如输入迭代器相反
一般来说,C++实现遵循
零开销原则:你不使用,你不支付(C++的设计和演化,1994)你应该问的有趣。我回答了另一个问题,我避免了将迭代器传递给另一个函数,因为我非常谨慎。我现在知道这不是必须的:啊,你找到了它。(basic\u resolver\u iterator.hpp:251
)…我在头文件、IPP文件等文件中迷失了方向。共享的ptr
是我用来保存所有信息的工具,只要我需要它,所以我显然准备好了基本上重复工作。再往前一点,我看到内存被分配给gethostbyname
返回的信息,所以我假设它被正确地释放了,当所有有效迭代器都消失并且smart\u ptr
注意到时,可能会发生这种情况。谢谢!
// Asynchronously resolve a query to a list of entries.
template <typename Handler>
void async_resolve(implementation_type& impl,
const query_type& query, Handler& handler)
{
// Allocate and construct an operation to wrap the handler.
typedef resolve_op<Protocol, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
boost_asio_handler_alloc_helpers::allocate(
sizeof(op), handler), 0 };
typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type;
boost::asio::detail::shared_ptr<values_type> values_;
std::size_t index_;