[英]moving the content of a unique_ptr
所以如果我有一個可移動的 (rval) std::unique_ptr,我可以使用簡單的賦值來移動內容而不是復制嗎? (指向object的內容,而不是指向它的指針)
看起來我做不到,但是“也許我做錯了”?
如果不是,不允許這樣做的理由是什么?
細節:
所以我已經成為 class 的所有者,其方法是從 Hell 返回 std::map,我真的不想在所有使用 /my/ class 的地方包含 hell.h,只是在少數幾個真正使用的地方想go那里。
所以我的想法是改變方法的返回簽名
#include "hell.h"
std::map<std::string, Hell> CopyTheObjectSpecified(...);
到
class Hell;
std::unique_ptr<std::map<std::string, Hell>> CopyTheObjectSpecified(...);
而且,對於 new 和 delete 的成本,我現在不需要詳細說明 Hell,除非調用該方法,並且該代碼將安全地由 unique_ptr 限定范圍。 鑒於 map 副本有很多分配,我不關心多一個。
(ben-v 建議我在 Hell 周圍建立一個編譯防火牆 - 看它的好方法)
但是,其中一位來電者正在做:
void Angel(std::map<std::string, Hell>& hell)
{
hell = CopyTheObjectSpecified(...);
}
用於減少移動分配(甚至是完整的返回復制省略 - 可能不是)
所以現在我正在做一個
void Angel(std::map<std::string, Hell>& hell)
{
hell = * CopyTheObjectSpecified(...);
}
或者更冗長,視覺上令人反感,但幾乎可以在任何地方跟蹤和注射:
void Angel(std::map<std::string, Hell>& hell)
{
hell = CopyTheObjectSpecified(...) .get()[0] ;
}
在我看來,查看調試, *
和get()
的重載似乎沒有看出 unique_ptr 是一個 r-val,因此內容也應該作為 r-val 返回。
(請注意,我在這里的意圖是 rval unique_ptr 實例繼續擁有它指向的 object,並且當它正常離開 scope 時將刪除它,但是 object 將通過移動剝離其內容。)
所以這是調用復制/刪除語義而不是移動語義,這是一種開銷。 我不能讓代碼運行得更慢!
當然,我可以簡單地添加一個 std::move(),但是當原作者取回它時,那將是一種額外的味道。 我仍然看到“未封裝”的 std::move 作為氣味。 也許最終我會習慣看到它。
void Angel(std::map<std::string, Hell>& hell)
{
hell = std::move( * CopyTheObjectSpecified(...) ) ;
}
或者使用交換操作(感謝 Ben Voigt)
void Angel(std::map<std::string, Hell>& hell)
{
hell.swap ( * CopyTheObjectSpecified(...) ) ;
}
(是的,CopyTheObjectSpecified() 的最佳(目前)實現是實際制作並返回一個副本,而不是返回一些對不斷變化的數據的 shared_ptr const 引用)
或者我可以將可移動性最低限度地封裝在 unique_ptr 的包裝器 class 中。 使用 when-rval-content-movable unique_ptr 有危險嗎?
目前我們編碼為 c++11。也許我需要后期標准的幫助才能正確執行此操作? 但這可能會幫助我制定一個可讀和可轉移的解決方案。
呃。 我只想要 /my/ 類的 /out/ 這個方法! 但今天這不是一個選擇。
在最簡單的層面上,似乎不需要 unique_ptr,因為std::map
可以在不完整的類型上實例化就好了。 所以你可以這樣做:
class Hell;
std::map<std::string, Hell> CopyTheObjectSpecified(...);
並且您只需要 #include 代碼即可將某些內容放入 map 或將其從 map 中取出(或復制/復制整個地圖)。 std::map
已經包含一個間接級別,這意味着它可以在不知道鍵/值類型的細節的情況下移動。
所以
void Angel(std::map<std::string, Hell>& hell)
{
hell = CopyTheObjectSpecified(...);
}
應該繼續工作就好了。
我不確定我的回答是否有幫助,但據我所知,創建unique_ptr
意味着 object 的所有權無法更改,這意味着它僅在已定義的 scope 中有效/創建所以我認為你不能移動它的內容,因為它會改變所有權。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.