[英]What's the lifetime of boost::asio::ip::tcp::resolver::iterator from async_resolve?
當我調用boost::asio::ip::tcp::resolver::async_resolve
,我的處理程序收到一個ip::tcp::resolver::iterator
,該迭代ip::tcp::resolver::iterator
遍歷一個或多個ip::tcp::resolver::entries
。 他們的一生是什么?如何使他們存活?
例如,如果我得到第一個entry
並對其啟動tcp::async_connect
,則可以在async_connect
處理程序中迭代到下一個entry
並啟動另一個async_connect
到下一個條目(只要我將iterator
傳遞給async_connect
處理程序,當然)?
何時resolver::iterator
和resolver::entries
? 我是否需要做一些特別的事情,還是只是讓它們超出范圍而不受任何回調閉包的約束?
(我知道我可以在async_resolve
處理程序中遍歷所有resolver::entries
並將它們存儲在智能指向的結構或其他任何東西中,以便我控制它們的生命周期,但是如果asio::ip::tcp::resolver
是已經處理過了,如果我讓它完成工作,我的代碼就會更簡單。)
迭代器具有值語義。 因此,它們的壽命總是與周圍對象的壽命或它們的存儲期限(自動堆放,動態堆放,甚至靜態堆放)綁定在一起。
我想您想知道迭代器的有效性 。
好了, 文檔顯示迭代器類別是正向迭代器 。 前向迭代器具有“多次通過保證”,可以重復取消迭代器副本的引用,從而獲得相同的結果¹。
因此,我們處於半途而廢:保留迭代器仍然可以。 但是,當然,與任何其他[forward]迭代器一樣,我們必須考慮迭代器失效 。
因此,真正的問題歸結為: 解析程序迭代器何時失效 。
resolve
函數實現的用例是connection 。 對於連接而言,第一個有效的端點就足夠了,因此無需實際保留列表。
本着“按需購買”的精神,對於解決程序而言,將狀態保持在比所需時間更長的時間是沒有意義的。 另一方面,如果不支持Multipass,則將迭代器歸為ForwardIterator類別是沒有意義的。
文檔什么也沒說。 我們只有一種方法: 深入研究代碼
我們在表面之下找到了一些步驟: asio / detail / resolver_service.hpp:73
// 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 };
resolve_op
顯示迭代器是使用basic_resolver_iterator.hpp :: create創建的
這就引出了答案: 第251行
typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type;
boost::asio::detail::shared_ptr<values_type> values_;
std::size_t index_;
因此,只要您保留有效迭代器(而不是最終迭代器)的副本,就可以繼續取消引用它。 它甚至會與每個解析程序條目一起保留查詢參數( host_name
和service_name
)的副本。 這似乎有點浪費,但是我想在設計緩存方案時會派上用場。
譯為“它們始終保持有效”(如果它們一直有效)。
¹與輸入迭代器相反
²通常,C ++實現遵循零開銷原則:您不用的東西,不用付錢[C ++的設計和演進,1994年]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.