为什么 C++ 标准为纯右值的 `sizeof` 运算符指定临时对象具体化?

问题描述 投票:0回答:1

C++ ISO/IEC JTC1 SC22 WG21 N4860 标准规定,只有必要时才创建临时对象。它列出了临时对象被物化的情况,包括

sizeof
运算符:

[类.临时]

The materialization of a temporary object is generally delayed as long as possible in order to avoid creating unnecessary temporary objects. [Note: Temporary objects are materialized:
(2.1) — when binding a reference to a prvalue (9.4.3, 7.6.1.3, 7.6.1.6, 7.6.1.8, 7.6.1.10, 7.6.3),
(2.2) — when performing member access on a class prvalue (7.6.1.4, 7.6.4),
(2.3) — when performing an array-to-pointer conversion or subscripting on an array prvalue (7.3.2, 7.6.1.1),
(2.4) — when initializing an object of type std::initializer_list<T> from a braced-init-list (9.4.4),
(2.5) — for certain unevaluated operands (7.6.1.7, 7.6.2.4),
(2.6) — when a prvalue that has type other than cv void appears as a discarded-value expression (7.2).

[expr.sizeof]

If the operand is a prvalue, the temporary materialization conversion (7.3.4) is applied.

为什么我们必须在运行时创建一个临时对象来计算像

Foo{}
(
sizeof(Foo{})
) 这样的纯右值,而
sizeof
可以在编译时确定?

c++ sizeof prvalue
1个回答
0
投票

如果

sizeof
的操作数是纯右值,那么它当然不会“实际”实现,因为操作数未被评估。然而,说临时物化转换是操作数(未评估)评估的一部分保留了 C++14 行为。 在 C++11 和 C++14 中,如果

sizeof(expr)

是无效表达式(或者如果它是不允许询问其大小的类型,即,函数类型或不完整类型)。如果

expr
是纯右值,例如函数调用
expr
,其中
foo()
按值返回
foo
,则表达式
T
被视为包含临时
foo() 的销毁,作为其最后一步
对象即返回值。因此,如果
T
的析构函数不可访问或被删除,则会发生替换失败。
在 C++17 中,计算纯右值不会“自动”创建临时对象;而是创建临时对象。该标准必须明确地“说”执行临时物化转换,这会根据纯右值创建一个临时对象。为了保留 C++14 行为,即在 
T
是其类型具有已删除或不可访问析构函数的纯右值的情况下,

sizeof(expr)

会导致替换失败,有必要说发生了临时物化转换,这使析构函数调用成为表达式的一部分。 (顺便说一句,请注意,当 C++11 中引入 expr 时,它被指定为

not
要求类类型的纯右值操作数具有不可删除的、可访问的析构函数,甚至是完整的因此,在 C++17 及更高版本中,
decltype
被指定为

not

进行临时物化转换,这再次保留了之前的行为。)

    
© www.soinside.com 2019 - 2024. All rights reserved.