c++ 交换两个不同类型对象的位的标准兼容方式

x7rlezfr  于 2023-10-21  发布在  其他
关注(0)|答案(1)|浏览(124)

考虑以下两个函数:

  1. template<typename T, typename S>
  2. void swap1(T* t, S* s)
  3. {
  4. static_assert(sizeof(T) == sizeof(S));
  5. char tmp[sizeof(T)];
  6. std::memcpy(tmp, t, sizeof(T));
  7. std::memcpy(t, s, sizeof(T));
  8. std::memcpy(s, tmp, sizeof(T));
  9. }

  1. template<typename T, typename S>
  2. void swap2(T* t, S* s)
  3. {
  4. static_assert(sizeof(T) == sizeof(S));
  5. char *tc = (char*)t, *sc = (char*)s;
  6. std::swap_ranges(tc, tc + sizeof(T), sc);
  7. }

哪一个违反了严格的别名规则?这两个人都违反了规则吗?如果两者都有,如何达到目标而不违反?
我从C标准中所能看到的是,我们可以使用某些类型的指针,包括char*来指向任意对象,并访问其存储值。access是什么意思是还是读+写**?
我没有从What is the Strict Aliasing Rule and Why do we care?找到答案。关于Hacker News - memcpy certainly violates aliasing rules的讨论让我更加困惑。
但是通过阅读Understanding C/C++ Strict Aliasing的“memcpy版本,符合C和C
规范和高效”部分,似乎至少swap2是完全好的。

fdbelqdn

fdbelqdn1#

这两种实现都没有违反 * 严格的别名规则 *。规则禁止通过U*阅读或写入T*,除非U*char*/unsigned char*/std::byte*。通过char*进行阅读和写是完全标准的C++。
这个对象最终是否有价值是另一回事。我不认为标准保证任何东西,除非TU是相同的类型。也许除了一些算术转换。但我不确定。
如果你只有一个简单的可复制类型T,[basic.types]/2说(省略一些细节):
对于任何物体…可复制的T字体底层的字节可以将组成对象的数组复制到char.如果该数组的内容被复制回对象,则该对象随后将保持其原始值。

相关问题