std::swap 丢失了 Type-Based 别名分析使用的信息?

std::swap loses information used by Type-Based Alias Analysis?

通过检查 vector class 在 GCC headers (stl_vector.h) 中的实现,我在 vector base 实现中发现了以下两个成员函数 class(我在示例中将其重命名为 Data_Class 以避免使用 long_and_weird 名称)。

    void
    _M_copy_data(Data_Class const& __x) _GLIBCXX_NOEXCEPT
    {
      _M_start = __x._M_start;
      _M_finish = __x._M_finish;
      _M_end_of_storage = __x._M_end_of_storage;
    }

    void
    _M_swap_data(Data_Class& __x) _GLIBCXX_NOEXCEPT
    {
      // Do not use std::swap(_M_start, __x._M_start), etc as it loses
      // information used by TBAA.
      Data_Class __tmp;
      __tmp._M_copy_data(*this);
      _M_copy_data(__x);
      __x._M_copy_data(__tmp);
    }

成员 (_M_start_M_finish_M_end_of_storage) 只是某种类型的指针,并且是 class.

中唯一的成员

这里的问题是第二个函数中出现注释的原因是什么? 可能是出于同样的原因,但为什么不使用 std::swap 用于两个 Data_Class objects 或者至少使用一个自动生成的 operator= 来进行复制?

我觉得这可以做得更简单。

对于 std::vector 对象,包含的三个指针永远不会寻址与另一个 std::vector 中的指针相同的内存 - 每个管理自己的连续内存区域。这种洞察力可用于 type-based 别名优化,如果以编译器能够遵循和推理的方式移动各个指针,则这种优化将继续成为可能。

std::swap 可能会使用一些 in-place 按位欺骗来实现,这样编译器就无法执行该跟踪(参见 here),因此最好避免。

当然,没有什么本质上会阻止优化器能够跟踪 swap 所做的任何事情并将其识别为与 __tmp-using 代码相同的逻辑操作,但无论谁发表了评论并且选择不使用 std::swap 可能观察到或推断出它在 至少 他们使用的编译器的一个版本上也没有针对某种优化级别进行优化。不过,更糟糕的优化可能很常见。

相同类型的 observation/reasoning 可能导致他们避免默认 operator=。例如,假设他们的编译器上的实现可能类似于 memcpy - 如果您将数据视为具有 char 类型,那么您可以安全地避免别名错误(同样的方式,您只能安全地排序访问不同的 union 成员是 charchar[]),但那是因为别名优化被抑制了。