我编写了一个向量类来学习移动语义。我使用move构造函数移动T(注释行)。
我的问题是,为什么不复制temp对象的所有字节,并将temp对象的所有字节设置为零,就像C中的那样?
我知道会为temp对象调用析构函数,它可能需要一些初始化的成员才能正确地进行析构。这可能是我不能更改对象的内部表示形式的原因。
但是如果我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 }(如果它与实际问题无关,请不要告诉任何关于转换及其安全性的信息)
(我知道这不是一个很好的方法,最好不要在实际项目中使用它。但我只想知道从效率的角度看它有多好。)。
发布于 2020-12-30 14:20:50
发布于 2020-12-30 17:27:08
你的计划很糟糕。
编译器可以使用如果规则计算出一个memcpy和一个零--甚至只是跳过析构函数--是合法的。
如果这样的编译器运行在手工构建的未定义行为中,它要么会被未定义的行为弄糊涂,要么会因此而无法进一步优化。
有时有充分的理由诉诸于不明确的行为。但是他们首先证明了您的解决方案使更好,并且耗尽了标准的兼容解决方案。最后,他们坦率地讨论了真正的短期、中期和长期风险,以换取短期的有保障的利益。
你的案子跟这一切无关。
优化移动-破坏到memcpy是编译器已经做的类型,很容易理解在简单的代码流。手工操作是无意义的99/100,90/100倍有害。
如果您的类型并不简单,而且代码流易于理解,那么您的优化可能也很难证明是安全的。如果您简化了类型和代码流,那么当您能够可靠地证明memcpy 0是最佳时,您的编译器可能也可以。
坐下来,然后使用优化的编译器输出。是有教育意义的。
发布于 2020-12-30 14:40:18
您的优化可以在一些情况下有效。当移动构造函数执行特定的操作时,它可能会导致问题。
class MyCustomClass : public IObserver
{
Registry ®istry;
// ...
public:
MyCustomClass(MyCustomClass &&rhs)
: registry{rhs.registry}
{
registry.register(*this);
}
// ...
};如果您按位复制这个类,则所移动的实例没有在注册表中注册。
通过将引用归零,引用将被破坏,原始实例的析构函数很可能会在从注册表中取消注册时崩溃。
https://stackoverflow.com/questions/65508044
复制相似问题