【发布时间】:2021-04-07 00:30:32
【问题描述】:
我写了一个向量类来学习移动语义。 我使用移动构造函数来移动 T(注释行)。
我的问题是为什么不直接复制临时对象的所有字节并将临时对象的所有字节设置为零,就像在 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 }
(如果与实际问题无关,请不要透露有关演员阵容及其安全性的任何信息)
(我知道这不是一个好方法,最好不要在实际项目中使用它。但我只感兴趣从效率的角度来看它有多好。)
【问题讨论】:
-
您会在 stackoverflow.com 上找到很多问题,人们想知道为什么在他们
memcpy他们的 C++ 对象之后,从这里到那里,一切都乱套了。这就是最终在这里发生的事情。这只会以眼泪收场。您不能期望简单地逐字节复制 C++ 对象,然后每个人都会过上幸福的生活。 C++ 不能以这种方式工作。 -
您只能对 trivially-copyable 类型的内存进行内存复制。一旦一个类型有一个用户提供的移动构造函数,它就不再是简单的可复制的了。
-
您是否尝试测量这两个版本,看看有什么区别?
-
当然。这是一个简单的例子。一个典型的
std::string是一个指针和一个字符串的大小。您只是逐字节复制它。伟大的!现在你有两个std::strings 指向同一个内部缓冲区,它们的两个析构函数(最终)都会尝试delete[]相同的精确指针。希拉里随之而来。现在您的代码中完全不相关的部分出现了神秘的崩溃和内存损坏,迫使您在 Stackoverflow 上写另一篇文章,想知道这是怎么回事?那么,最终证明这比正确的移动语义更“有效”吗? -
这个问题意味着对 C++ 中的运动缺乏了解。
标签: c++ c++11 move-semantics memcpy