被清洗的指针是否会破坏优化机会?

bit*_*ask 8 c++ optimization machine-code language-lawyer stdlaunder

std::launder故意混淆抽象机/编译器的指针的来源,以便源和结果可能具有不同的生命周期和类型。当用于例如(静态)向量情况时,您有一个半大的存储空间来保存多个对象,清洗指向切片的“干”指针会产生适当类型的干净但“湿”的指针(湿的,如清洗过的) :

// appropriately sized and aligned data member
std::byte* const dry = data + some_index;
T* const wet = std::launder(reinterpret_cast<T*>(dry));
Run Code Online (Sandbox Code Playgroud)

这个想法是编译器无法“看到”过去的std::launder. 即使没有实现位于单独的编译单元中。问题是这是否仍然会浪费合理的优化机会。

例如:

T object;
// ...
T* ptr = &object;
ptr->member = 42;
return ptr->member;
Run Code Online (Sandbox Code Playgroud)

据推测,在读取其内容时,不需要单独检索object和的地址,因为它可能仍然位于某个寄存器中。member但是,如果对访问的访问ptr总是被洗白,例如,如果它是从operator[](size_type)必须洗白存储指针的某些地方检索的,则这可能不再成立:

storage[i].member = 42;
return storage[i].member;
// storage[]() launders
Run Code Online (Sandbox Code Playgroud)
  • 我对优化栅栏的理解正确吗?
  • 这是否意味着由于清洗而必须在程序集级别上重新加载(子)对象?
    • 如果没有,为什么不呢?
  • 除了保留对 的引用之外,还有其他方法可以解决此问题吗storage[i]
  • 或者我应该将其视为std::launder一个除了神奇地使 UB 代码变得非 UB 之外什么都不做的函数?

含义:如果这是正确的,则意味着类向量结构(即当您需要最高性能时使用的结构)将因引入std::launder. std::vector<T>就会落后于简单的T*