std::bit_cast and std::start_lifetime_as are two different functions in C++ with distinct purposes. std::bit_cast is used to reinterpret the underlying binary representation of an object as another type, without changing its value. It is commonly used for type punning or low-level bit manipulation. On the other hand, std::start_lifetime_as is used to explicitly indicate the start of the lifetime of an object, usually in situations where the object's lifetime needs to be managed manually, such as in placement new or custom memory management scenarios. In summary, while std::bit_cast is used for type reinterpretation, std::start_lifetime_as is used for managing object lifetimes.

15

std::bit_cast 显然在 c++20 中被引入。而 std::start_lifetime_as 则被提议用于 c++23(来自P0593R5)。由于它们似乎都要求所涉及的数据类型是平凡的,一旦后者被引入,前者还有必要吗?

提前为这些新特性未提供更多信息向大家道歉。我刚刚在观看 cppcon 2019 上关于类型转换的演讲后才听说它们,而且我在谷歌上找不到关于 start_lifetime_as 的太多信息。我希望看到这个的其他人可能会知道更多。


1
你的意思是,除了其中一个已经成为C++20工作草案的完全采纳部分之外,另一个是一个提案,仍在变化中,尚未成为任何标准的一部分,因此可能永远不会成为标准? - Nicol Bolas
据我所知,@NicolBolas提议在C++23中引入start_lifetime_as - markt1964
1
@NicolBolas 已添加链接。 - Barry
2个回答

27
答案很简单: bit_cast 返回值,而start_lifetime_as“更改”内存(以存在于抽象机器中但不会影响任何物理位的方式)。您可以使用前者将现有对象一次性解释为一组位;您可以使用后者将现有位永久地解释为一个对象。

start_lifetime_as 执行结束后,源对象的生命周期是否结束?如果是,那么尝试使用旧指针变量进行引用(提及)是否不合法,或者仅仅访问是不合法的? - sandthorn
1
@sandthorn:任何对象的生命周期,如果其存储与新对象的存储重叠,则结束([basic.life]/1.5),除非新对象嵌套在其中(因为您精确地重新创建了子对象或涉及存储数组:[intro.object]/4)。指向超出生命周期对象的指针有特殊规则([basic.life]/6)。 - Davis Herring
如果新的 start_lifetime_as 取决于 UB 生命周期规则,那就有点可怕了。 [LIVE] 这意味着编译器无法帮助那些可能会忘记生命周期规则的人。如果 start_lifetime_as 在被误用时能够调用非法形式,那将更加安全。 - sandthorn
1
@sandthorn:如果能够实现这个,我们一开始就不需要这个函数了。 - Davis Herring

14

std::bit_cast 将其参数的位复制到不同类型的新值中。

float myFloat = 3.14;
auto asUint = std::bit_cast<uint32_t>(myFloat);
auto asBytes = std::bit_cast<std::array<char,4>>(myFloat);

myFloatasUintasBytes是具有不同地址的独立变量。编译器可能能够完全优化它们,但从逻辑上讲,它们是完全不同的值,只是恰好具有相同的大小和位。

std::start_lifetime_as没有做任何事情。它只是告诉编译器,可以将一段内存视为包含指定类型数组的范围。这样,开发人员就可以将该内存用作数组,而不会触发未定义行为。它不会物理修改传递给它的内存,也不会返回任何内容。它仅用于C++对象模型的记录。

编辑:Robert Leahy拥有一个出色的演示文稿,解释了这些函数被创建来解决哪些问题以及它们如何实现。


这是否意味着,例如,如果存在两个相同大小的平凡类型的联合体,其中一个的位模式是另一个有效的位模式,那么您可以为联合体分配一个成员,在其上调用std::start_lifetime_as以获取另一种类型的实例,并从第二个成员访问它而不会出现未定义行为? - markt1964

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接