请考虑以下代码:
void foo() {
int arr[1];
*arr; // OK
using T = int[1];
*T{}; // OK for Clang and MSVC
// GCC error: taking address of temporary array
}
我的直觉是*T{}
应该导致数组到指针的转换,并且间接是格式良好的。不过,我对此并不完全确定。
GCC是正确的,还是这是一个bug?这是为了防止开发人员犯错误吗?毕竟,您通常不会取消引用数组。有记录吗?
| 免责声明|
| --|
| CWG Issue 2548已确认**“通过数组纯右值的间接寻址今天也无效”**。@StoryTeller的回答是错误的,并且通过假设这也适用于*T{}
来误解目的地类型的含义,但这个表达式不是指针的初始化。|
- 更多讨论在编辑问题EDIT 6555 *
2条答案
按热度按时间2skhul331#
GCC是正确的,因为间接只能应用于指针。[expr.unary.op]/1:
一元
*
运算符执行间接寻址:它所应用的表达式应该是指向对象类型的指针,或者指向函数类型的指针,结果[...]*arr
是可以的,因为arr
是一个左值,而[basic.lval]/6:当一个左值作为一个运算符的操作数出现时,该操作数需要一个纯右值,左值到右值,数组到指针,或函数到指针的标准转换被应用于将表达式转换为纯右值。
数组到指针转换(conv.array(https://timsong-cpp.github.io/cppwp/n4868/conv.array))应用于
arr
。T{}
已经是一个纯右值(数组类型),并且这里没有必要进行数组到指针转换的措辞,所以*T{}
是不正确的。pengsaosao2#
在我看来,它定义得很好,Clang和MSVC根据需要做了这件事。
[expr.unary.op](强调我的)
1一元
*
运算符执行间接寻址:它所应用的表达式应该是一个指向对象类型的指针,或者是一个指向函数类型的指针,结果是一个左值,指向表达式所指向的对象或函数。然后我们有这个句子,告诉我们何时何地可以应用标准转换序列:
[一般共识]
1标准转换是具有内置含义的隐式转换。[conv]枚举了此类转换的完整集合。* 标准转换序列 * 是按以下顺序进行的标准转换的序列:
...
如果需要将表达式转换为所需的目标类型,将对表达式应用标准转换序列。
它告诉我们,可以应用标准转换序列将操作数转换为表达式所需的类型。这就是
*arr
的工作方式,因此我们只需要检查数组到指针的转换是否可以应用于我们的纯右值数组。[conv.array]
1类型为“array of N T”或“array of unknown bound of T”的左值或右值可以转换为类型为“pointer to T”的纯右值。应用临时实体化转换([conv.rval])。结果是指向数组第一个元素的指针。
它可以,因为标准甚至明确要求一个临时数组来具体化,并让指针指向它的第一个元素。总而言之,GCC拒绝有效代码,所以可以说它有一个bug。