为什么"move semantics"而不是简单的memcpy?
Why "move semantics" rather than simply memcpy?
给定以下代码:
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
),这些是这种方法的唯一问题吗?或者还有其他可能出错的地方吗?我想听听你对未知问题的描述。
我想我已经开发了一个"对象重定位语义",但如果它有一个明显的漏洞,我宁愿不要求人们考虑它。
"trivial copyable"的概念暗示内存是安全的。你可以通过std
中的trait来测试一个类型是否可复制。
它包含了破坏它是一个noop的想法;在您的情况下,您希望销毁不是一个noop,而不是在源上执行,而在目标上执行。
move & destroy-source的概念已在c++ 1z标准化过程中提出,独立于"平凡的可复制"。的概念。它是为了异常安全而提出的;有些类型的move-construct不是异常安全的,但是move-construct-and-destroy-source可以。还有一些棘手的问题涉及异常和容器分配,这使得noexcept move- tor操作非常有价值。
如果这被纳入标准,那么如果证明是有价值的,那么一个微不足道的"如果你不破坏源代码,就可以复制"的概念也可以被添加到标准中。
它不会适用于所有移动语义可以增强的东西,并且它可能需要程序员的努力(编译器如何能够计算出"省略销毁器"是可以的);这并不容易;图灵机行为的所有非平凡非结构性质都是难以处理的
为什么使用复制构造函数而不是std::memcpy
?
Move构造函数/Move赋值操作符为您提供了在移动对象时做一些其他有用的事情的封装机会-日志记录,清理等。
性能方面——在许多情况下,编译器可以将多次移动优化为一次(想象一下,许多函数只是相互返回某个对象)。对于memcpy
,它们的能力受到更多限制。
最后-因为c++不是关于移动字节-它是关于使用对象作为你的程序的基础。
- 在c++中用vector填充一个简单的动态数组
- (C++)分析树以计算返回错误值的简单算术表达式
- 我的简单if-else语句是如何无法访问的代码
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 一种在C++中读取TXT配置文件的简单方法
- 关于简单C++函数(is_palindrome)的逻辑的问题
- 显示错误输出的简单数组排序程序
- 当无法使用模板和宏时,生成类型变体C++代码的最简单方法是什么?
- 退出简单while循环时出现问题
- 为什么简单的算术减法在"if"条件下不起作用?
- C++-字符串是否包含一个带有简单循环的单词
- 关于 c++ 函数中指针赋值的简单问题
- 从函数返回任意简单类型的数据
- 如何在没有函数的情况下编写此代码并使C++更简单?
- 有没有办法简单地从 GPU 调用多个 cpp 输出文件?
- 怎么能用memcpy复制工会简单的成员?
- 简单的MPI_GATHER测试带有memcpy错误
- 为什么"move semantics"而不是简单的memcpy?
- 复制简单结构体时memcpy和'='的区别