从C++ 17开始,使用std :: launder"验证"非"指向对象的指针"指针值

Oli*_*liv 19 c++ pointers c++17

根据这个答案,从C++ 17开始,即使指针具有正确的地址,并且正确的类型解除引用它也会导致未定义的行为.

 alignas(int) unsigned char buffer[2*sizeof(int)];
 auto p1=new(buffer) int{};
 auto p2=new(p1+1) int{};
 *(p1+1)=10; // UB since c++17
Run Code Online (Sandbox Code Playgroud)

原因是指针值p1+1一个指针过去的对象.可以使用以下示例将此示例恢复为已定义的行为std::launder:

 *std::launder(p1+1)=10; // still UB?  
Run Code Online (Sandbox Code Playgroud)

其次,在下列情况下它是否也有用?

alignas(int) unsigned char buffer[3*sizeof(int)];
auto pi = new (buffer) int{};
auto pc = reinterpret_cast<unsigned char*>(pi);//not a "pointer to" an element of buffer 
                                               //since buffer[0] and *pc 
                                               //are not pointer interconvertible
//pc+2*sizeof(int) would be UB
auto pc_valid = std::launder(pc) //pc_valid is a pointer to an element of buffer
auto pc_valid2 = pc_valid+2*sizeof(int); //not UB thanks to std::launder
auto pi2 = new (pc_valid2) int{};
Run Code Online (Sandbox Code Playgroud)

T.C*_*.C. 12

号构成的字节int对象p2 指向不可达的通过p1+1.


"可达"规则基本上意味着launder不允许您访问通过原始指针无法合法访问的存储.由于不透明函数可能launder指向它想要的多少,因此允许这种类型的恶作剧将基本上抑制逃逸分析.