简体   繁体   English

std::swap 丢失了基于类型的别名分析使用的信息?

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

By examining the implementation of the vector class in the GCC headers ( stl_vector.h ), I found the following two member functions inside the vector base implementation class (Which I renamed in the example as Data_Class to avoid long_and_weird name).通过检查 GCC 头文件 ( stl_vector.h ) 中vector类的实现,我在向量基实现类中发现了以下两个成员函数(我在示例Data_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);
    }

The members ( _M_start , _M_finish , _M_end_of_storage ) are just pointers of some type and are the only members in the class.成员( _M_start_M_finish_M_end_of_storage )只是某种类型的指针,并且是类中唯一的成员。

The question here is what is the reason for the comment in the second function?这里的问题是第二个函数中注释的原因是什么? It may be for the same reason, but why not use std::swap for two Data_Class objects or maybe at least an automatically generated operator= to do the copying?可能出于同样的原因,但为什么不对两个Data_Class对象使用std::swap或者至少使用一个自动生成的operator=来进行复制?

I feel like this could be done simpler.我觉得这可以做得更简单。

For a std::vector object, the three contained pointers will never address the same memory as the pointers in another std::vector - each manages its own contiguous memory region.对于std::vector对象,三个包含的指针永远不会与另一个std::vector的指针寻址相同的内存——每个指针都管理自己的连续内存区域。 This insight can be used for type-based aliasing optimisations, which continue to be possible if the individual pointers are moved around in a way the compiler's able to follow and reason about.这种洞察力可用于基于类型的别名优化,如果单个指针以编译器能够遵循和推理的方式移动,这将继续成为可能。

std::swap may be implemented using some in-place bitwise trickery such that the compiler can't perform that tracking (see here ), so is best avoided. std::swap可以使用一些就地按位技巧来实现,这样编译器就无法执行该跟踪(请参阅此处),因此最好避免。

Of course, there's nothing inherently preventing an optimiser from being able to track whatever swap does and recognising it as the same logical operation as the __tmp -using code, but whomever made that comment and the choice not to use std::swap probably observed or deduced that it wasn't optimised as well on at least one version of the compiler they used, for some optimisation level.当然,没有什么本质上阻止优化器能够跟踪swap所做的任何事情并将其识别为与__tmp使用代码相同的逻辑操作,但是__tmp谁提出该评论并选择不使用std::swap可能观察到或推断它没有他们使用的至少一个版本的编译器上针对某些优化级别进行优化。 Worse optimisation could be quite common though.不过,更糟糕的优化可能很常见。

The same type of observation/reasoning may have led them to avoid a default operator= .相同类型的观察/推理可能导致他们避免使用默认的operator= For example, say the implementation on their compiler may have been akin to a memcpy - if you treat the data as having char type then you're safe against aliasing bugs (same way you can only safely sequence access to distinct union members is one is a char or char[] ), but that's because aliasing optimisations are suppressed.例如,假设他们的编译器上的实现可能类似于memcpy - 如果您将数据视为具有char类型,那么您就可以安全地避免别名错误(同样,您只能安全地对不同union成员的访问进行排序是一个charchar[] ),但这是因为别名优化被抑制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM