reinterpret_cast,只读访问,简单的可复制类型,会出什么问题?

reinterpret_cast, read-only access, trivially copyable types, what can go wrong?

本文关键字:类型 什么 问题 可复制 cast 读访问 简单 reinterpret      更新时间:2023-10-16

众所周知,访问reinterpret_cast<pointer/reference>(obj)的结果是未定义的行为(少数情况除外(。

现在,假设您只在 reinterpret_cast 变量的生命周期内对obj进行只读访问:

TypeA *a = ...;
{
const TypeB *b = reinterpret_cast<const TypeB*>(a);
// b's lifetime is this scope
// I know, that accessing the object pointed by 'b' is UB
// but what can go wrong in practice in this scope,
// if the code uses 'a' and 'b' only in a read-only manner,
// for example:
cout << a->something;
cout << b->otherSomething;
}

(TypeATypeB是微不足道的可复制和不相关的;假设我们这里没有一致性问题(

我的主要问题:如果标准允许,我们会失去任何优化潜力吗?

我的意思是,如果通过b的可访问内存将在b的生命周期内(以任何方式(实际修改,则这只是 UB,而不是当前的原则。

这是一个明智的想法吗?


例如,这个想法可能有用:

  • 有一个char8_t提案,它将在标准中加入一个新的字符类型,不允许别名。现在假设代码库更改为此类型。还有一个遗留库,由这个代码库使用,它一直使用char来存储 utf-8。现在,如果我们想避免 UB,我们需要 在charchar8_t之间复制.但这些在内存中实际上是相同的,所以reinterpret_cast应该完成这项工作。
  • 一个简单的reinterpret_cast<const uint32_t&>(some_float)可以用这个想法很好地定义。不需要bit_cast.

混叠限制简化了编译和优化。假设您有以下代码:

TypeA *a = ...;
{
const TypeB *b = reinterpret_cast<const TypeB*>(a);
cout << a->something;
cout << b->otherSomething;
}
a->modifier();

编译器需要知道*b*a的别名,以便它不会重新排序为:

TypeA *a = ...;
const TypeB *b = reinterpret_cast<const TypeB*>(a);
cout << a->something;
a->modifier();
cout << b->otherSomething;

在这种情况下,分析很容易,但想象一下,人们宣布了一个void f(TypeA* a, const TypeB* b)。在f体内,先前的重新排序将是一场灾难。编译器是否应该拒绝调用任何带有ab作为参数的函数?或者我们应该通知编译器f的第一个参数可能被别名:void f(TypeA* __unrestricted a, const TypeB* __unrestricted b)

我相信这将是无休止的讨论的开始。此外,它不在时尚趋势中(见 Rust(。