给出以下代码:
typename std::aligned_storage<sizeof(T), alignof(T)>::type storage_t;
//this moves the back of src to the back of dst:
void push_popped(std::list<storage_t> & dstLst, std::list<storage_t> & srcLst)
{
auto & src = srcLst.back();
dstLst.push_back(storage_t());
auto & dst = dstLst.back();
std::memcpy(&dst, &src, sizeof(T));
srcLst.pop_back();
}
我清楚地知道为什么这种方法通常不正确的3个原因(即使它避免调用src->~T()
,因此避免了T
的双重回收资源)。
U*
的对象成员,指向同一对象的其他U
成员T
处不再存在src
,而T
dst
醇>
(这里提到这些:http://www.gamedev.net/topic/655730-c-stdmove-vs-stdmemcpy/#entry5148523。)
假设T
不是一个类型,其内存地址是其状态的属性(例如std::mutex
或std::condition_variable
),这些是这种方法的唯一问题吗?还是有其他可能出错的事情?我想描述未知问题。
我想我有一个&#34;对象重定位语义&#34;已经发展了,但我不想让人们考虑它是否有明显的漏洞。
答案 0 :(得分:4)
&#34;平易可复制的概念&#34;意味着memcpy是安全的。您可以通过std
中的特征测试类型是否可以轻易复制。
它包括摧毁它是一个noop的想法;在你的情况下,你希望破坏不是一个noop,而是在源上完成,而不是在dest上完成。
&#34;移动和破坏源&#34;的概念已经在C ++ 1z标准化过程中提出,独立于&#34;可复制的&#34;概念。建议用于例外安全;有些类型的move-construct不是异常安全的,但是move-construct-and-destroy-source也是如此。并且存在涉及异常和容器分配的棘手问题,使得noexcept move-ctor操作非常有价值。
如果它符合标准,那么如果它被证明有价值的话,那么一个简单的可复制的 - 如果你没有 - 破坏 - 源概念也可以添加到标准中。
它不适用于所有移动语义都可以增强的东西,并且它可能需要程序员的努力(编译器如何能够解决这个问题&#34;可以让驱逐舰消失&#34;是不容易;图灵机行为的所有非平凡的非结构属性都是难以处理的。)
答案 1 :(得分:1)
为什么使用Copy构造函数而不是std::memcpy
?
移动构造函数/移动赋值oeprator为您提供封装的操作,以便在移动对象时执行其他有用的操作 - 记录,清理等。
性能明智 - 在许多情况下,编译器可以将许多移动优化为仅一个(想象许多函数只是简单地从一个对象返回一些对象)。 memcpy
他们的罪行受到更多限制。
最后 - 因为C ++不是关于移动字节 - 它是关于使用对象作为程序的基础。