[英]Hand written move
我写了一个向量 class 来学习移动语义。 我使用移动构造函数来移动 T(注释行)。
我的问题是为什么不只复制 temp object 的所有字节并将 temp object 的所有字节设置为零,就像在 C 中一样?
我知道将为 temp object 调用析构函数,它可能需要一些初始化的成员才能正确析构。 这就是为什么我不能更改 object 的内部表示的原因。
但是如果我 100% 确定我的 ~T() 没有这样的要求,这是一个很好的优化吗?
20 void push_back(T&& val)
21 {
22 check_cap();
23 //new (m_data + m_size) T(std::move(val));
24 for(int i = 0; i < sizeof(T); ++i)
25 {
26 reinterpret_cast<char*> (m_data + m_size)[i] = reinterpret_cast<char*> (&val)[i];
27 reinterpret_cast<char*> (&val)[i] = 0;
28 }
29 m_size++;
30 }
(如果与实际问题无关,请不要告诉任何有关演员阵容及其安全性的内容)
(我知道这不是一个好方法,最好不要在实际项目中使用它。但我只感兴趣从效率的角度来看它有多好。)
你的计划很糟糕。
使用as-if 规则,编译器通常可以计算出 memcpy 和零 - 甚至只是跳过析构函数 - 是合法的。
如果这样的编译器遇到您手工制作的未定义行为,它要么被未定义行为混淆,要么因此无法进一步优化。
有时有充分的理由诉诸未定义的行为。 但他们首先要证明您的解决方案能让事情变得更好,然后用尽符合标准的解决方案。 最后,他们坦诚地讨论了真正的短期、中期和长期风险,以换取短期的保证收益。
你的案子没有这些。
将 move-destroy 优化到 memcpy 是编译器已经对在简单代码流中易于理解的类型进行的操作。 手动操作是 99/100 毫无意义和 90/100 倍有害。
如果您的类型不简单并且代码流易于理解,那么您的优化可能也难以证明是安全的。 如果你简化你的类型和代码流,当你可以可靠地证明你的 memcpy 零是最优的时,你的编译器可能也可以。
坐下来与godbolt一起玩优化编译器output。 这是有教育意义的。
您的优化可能对少数情况有效。 当您的移动构造函数执行特定操作时,它可能会导致问题。
class MyCustomClass : public IObserver
{
Registry ®istry;
// ...
public:
MyCustomClass(MyCustomClass &&rhs)
: registry{rhs.registry}
{
registry.register(*this);
}
// ...
};
如果您按位复制此 class,则移动的实例未在注册表中注册。
通过归零,引用被破坏,原始实例的析构函数很可能在从注册表中注销时崩溃。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.