交换不同类型的两个对象的位的符合标准的方式

问题描述 投票:0回答:1

考虑以下两个函数:

template<typename T, typename S>
template<typename T, typename S>
void swap1(T* t, S* s)
{
  static_assert(sizeof(T) == sizeof(S));
  char tmp[sizeof(T)];
  std::memcpy(tmp, t, sizeof(T));
  std::memcpy(t,  s, sizeof(T));
  std::memcpy(s, tmp, sizeof(T));
}

template<typename T, typename S>
void swap2(T* t, S* s)
{
  static_assert(sizeof(T) == sizeof(S));
  char *tc = t, *sc = s;
  std::swap_ranges(tc, tc + sizeof(T), sc);
}

其中哪一个违反了严格的别名规则?两人都违反规定了吗?如果两者兼而有之,如何在不违规的情况下达到目的?

我从C++标准中可以看到的是,我们可以使用某些类型的指针,包括

char*
来指向任意对象,并访问其存储的值。 访问是什么意思?只是还是读+写

我没有从这篇文章中找到明确的答案。

关于这篇文章的讨论让我更加困惑。

但是通过阅读这篇文章的“memcpy版本,符合C和C++规范并且高效”部分,看起来至少

swap2
是完全没问题的。

c++ language-lawyer strict-aliasing
1个回答
0
投票

这两种实现都没有违反严格的别名规则。该规则禁止通过

T*
读取或写入
U*
,除非
U*
char*
/
unsigned char*
/
std::byte*
。通过
char*
进行读写是完美的标准 C++。

该对象最终是否具有一定的价值则完全是另一回事。我认为标准不能保证任何事情,除非

T
U
是同一类型。也许禁止一些算术转换。但我不确定。

如果你只有一个简单的可复制类型

T
[basic.types]/2说(省略一些细节):

对于任何可普通复制类型的对象...

T
...组成对象的底层字节...可以复制到
char
...的数组中 如果该数组的内容被复制回对象中,则该对象随后应保留其原始值。

© www.soinside.com 2019 - 2024. All rights reserved.