[英]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.