在平凡可复制的结构之间使用类型双关会有多邪恶?
How evil would it be to use type punning between trivially copyable structs?
我有一个带有隐藏 C++ 层的 Swift 接口的库。在 C++ 中,我有 struct A { ...}
。我希望 Swift 传递此结构的按值副本(出于各种复杂的原因)。 Swift 理解 C 声明但不理解 C++,因此我需要为其声明一些具有相同大小的虚拟 C 结构,例如struct FakeA { char data[/* size of A */]; }
。然后,我可以使用类型双关语来回切换。由于 A
可以轻松复制,所以我认为没关系。但是,在 cppreference.com 它指出,"Unlike in C, however, objects with trivial default constructors cannot be created by simply reinterpreting suitably aligned storage, such as memory allocated with std::malloc: placement-new is required to formally introduce a new object and avoid potential undefined behavior."
undefined 我们在谈什么?它真的会导致问题吗,比如说,当使用 Clang 为 arm64 和 x86_64 编译时?
C++ 抽象了 lifetime 的概念,即使对于没有构造函数的 pods,C++ 也用特定的术语定义了对象的生命周期开始和结束时间,这就是为什么你不能只是重新解释内存中的字节,即使您知道它们的布局匹配。这是未定义的行为,因为那不是对象生命周期的开始。
实际上,这是人们仍在使用的 UB 类型,因为没有等效的非 UB 选项。
std::start_lifetime_as<T>
和 new (p) std::byte[n]
(以前的 std::bless
)将是解决这个问题的完美方法(http://wg21.link/p0593),但遗憾的是现在不是。
我有一个带有隐藏 C++ 层的 Swift 接口的库。在 C++ 中,我有 struct A { ...}
。我希望 Swift 传递此结构的按值副本(出于各种复杂的原因)。 Swift 理解 C 声明但不理解 C++,因此我需要为其声明一些具有相同大小的虚拟 C 结构,例如struct FakeA { char data[/* size of A */]; }
。然后,我可以使用类型双关语来回切换。由于 A
可以轻松复制,所以我认为没关系。但是,在 cppreference.com 它指出,"Unlike in C, however, objects with trivial default constructors cannot be created by simply reinterpreting suitably aligned storage, such as memory allocated with std::malloc: placement-new is required to formally introduce a new object and avoid potential undefined behavior."
undefined 我们在谈什么?它真的会导致问题吗,比如说,当使用 Clang 为 arm64 和 x86_64 编译时?
C++ 抽象了 lifetime 的概念,即使对于没有构造函数的 pods,C++ 也用特定的术语定义了对象的生命周期开始和结束时间,这就是为什么你不能只是重新解释内存中的字节,即使您知道它们的布局匹配。这是未定义的行为,因为那不是对象生命周期的开始。
实际上,这是人们仍在使用的 UB 类型,因为没有等效的非 UB 选项。
std::start_lifetime_as<T>
和 new (p) std::byte[n]
(以前的 std::bless
)将是解决这个问题的完美方法(http://wg21.link/p0593),但遗憾的是现在不是。