c++ - 在 Type 和 Wrapper<Type> 之间 reinterpret_cast 是否安全?

标签 c++ language-lawyer undefined-behavior reinterpret-cast strict-aliasing

假设我们有类模板 Wrapper像这样:

template <class T>
struct Wrapper { T wrapped; };
reinterpret_cast 哪些类型安全之间Type和一个 Wrapper<Type> ?没有任何?标准布局?全部?
假设我们创建了其中一个( TypeWrapper<Type> )的对象,并通过另一个读取和写入该对象。示例( live on godbolt.org ):
void F1() {
    std::stringstream ss;
    ss << "Hello";
    reinterpret_cast<Wrapper<std::stringstream>&>(ss).wrapped << " world";
}

void F2() {
    Wrapper<std::stringstream> ss;
    ss.wrapped << "Hello";
    reinterpret_cast<std::stringstream&>(ss) << " world";
}
阅读 this answer 的评论这个领域在标准中似乎不是很明确。我认为所有编译器都会生成一个按预期工作的代码(即一种类型的值可以转换为另一种类型),但标准目前可能无法保证这一点。如果没有,问题就出现了:标准能否保证这些强制转换的定义明确的行为,或者在这种情况下保证任何事情是不可能/不切实际的?
因为我很确定,这些类型转换实际上会起作用。

最佳答案

重新诠释 T (那不是 Wrapper<T> 的成员)作为 Wrapper<T>永远不允许(F1 示例)。
另一方面,我相信重新诠释 Wrapper<T>T允许用于标准布局类:(F2 示例)

[basic.compound]/4.3

Two objects a and b are pointer-interconvertible if:

— one is a standard-layout class object and the other is the first non-static data member of that object, or ...


就在下面:

If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_­cast. ...


请注意,虽然此规则是对称的,但它要求两个对象都实际存在。如果您有引用 T指向Wrapper<T>的成员,那么您可以将其重新解释为 Wrapper<T> (反之亦然)。但是如果它指向一个 T不是 Wrapper<T> 成员的对象,那么就是UB。

免责声明:“不允许这样那样的重新解释”是指访问 reinterpret_cast 的结果。会导致UB。类型转换本身不应该导致 UB。

关于c++ - 在 Type 和 Wrapper<Type> 之间 reinterpret_cast 是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62765714/

相关文章:

c - POSIX 在 stdint.h 中的 "two' s 补码表示是什么意思?

c++ - 为什么 PRIVATE 成员函数不能成为另一个类的友元函数?

c - 为什么这些构造使用增量前和增量后未定义的行为?

c++ - 未定义的行为或可能与 memset 有关

c++ - 读取dll文件中的文本文件

java - Android 上的小区广播支持?

c++ - HDF5 - C++ - 打开文件读取内容失败

c++ - 在 C++ 中使用 fstream 读取对象

c++ - 从作为模板参数传递的 const 类型继承

c++ - 编译器如何知道 C++ constexpr 计算不会触发未定义的行为?