【问题标题】:c++ why decltype(*pointer) yields a reference?c++ 为什么 decltype(*pointer) 会产生引用?
【发布时间】:2018-12-25 14:10:48
【问题描述】:

我想知道为什么,当我使用decltype (* pointer) 时,它将变量的类型定义为引用。例如:

int i = 42, * p = & i;
decltype (* p) c = i;

现在c 是一个参考(链接到i)。为什么它是参考而不是整数?我正在读《Cpp Primer 5th》这本书。版。 P. 110 这么说,我不明白为什么。

【问题讨论】:

  • 因为解引用运算符被定义为返回一个T&。那是C++。如果要删除引用,请使用 std::remove_reference_t
  • @DeiDei 谢谢!对我来说,返回引用的指针没有意义,我迷路了,但在书中说,我正在阅读这里,谢谢!
  • 试试decltype(+*p)
  • @curiousguy 我的心智模型是,只有声明为T 类型的对象才是T 类型。所以对于int i;i 的类型是int。但是任何其他以任何其他名称引用i 的都是int &。这对我来说似乎很优雅,但我敢打赌,有些细节会使这种模型不切实际。

标签: c++ pointers reference language-lawyer decltype


【解决方案1】:

与显然流行的看法相反,*p 的类型为 int。来自[expr.unary.op]

一元 * 运算符执行间接:应用它的表达式应该是指向对象类型的指针,或指向函数类型的指针,结果是一个左值,指向表达式指向的对象或函数.如果表达式的类型是“指向 T 的指针”,结果的类型是“T”

decltype(*p) 产生int& 的原因在于decltype 的工作方式。来自[dcl.type.simple]

对于表达式 e,由 decltype(e) 表示的类型定义如下:[...]

  • 否则,如果 e 是无括号的 id 表达式或无括号的类成员访问,则 decltype(e) 是由 e 命名的实体的类型。如果没有这样的实体,或者如果 e 命名了一组重载函数,则程序是非良构的;

  • 否则,如果e是一个xvalue,则decltype(e)是T&&,其中T是e的类型;

  • 否则,如果e是左值,则decltype(e)是T&,其中T是e的类型; [...]

这里的 id-expression 表示完全由可能带括号的名称组成的表达式。

由于*pint 类型的左值表达式,而不是未加括号的id 表达式或类成员访问,因此适用第三个项目符号,decltype(*p)int&

值得注意的是i 是一个没有括号的id 表达式,因此第一个项目符号适用,decltype(i)int

【讨论】:

  • "与明显流行的看法相反,*p 具有 int 类型。" 不仅仅是指针取消引用,所有“普遍认为”具有 int& 类型的 C++ 表达式实际上有类型int;就像在 C 中一样(现代 C++ 中的值类别略有不同,但原理相同)
【解决方案2】:

decltype(expr) 给你的类型取决于表达式的value category。如果expr 不只是一个id-expression(即直接是事物的名称),那么规则基本上是:

  • 如果exprT 类型的xvalue,那么decltype(expr) 将是 T&&
  • 如果exprT 类型的左值,那么decltype(expr) 将 是T&
  • 否则,decltype(expr) 将是 T

在您的情况下,*pint 类型的左值。因此decltype(*p) 被定义为int&。如果您希望decltype 给您int,则必须使表达式成为纯右值,例如通过应用@Cheers 和hth 建议的一元+ 运算符。 - 阿尔夫在上面的评论中。然而,在实际代码中最好避免这种神秘的结构。为了便于阅读,最好只使用std::remove_reference_t<decltype(*p)>

【讨论】:

  • IOW, decltype 不是该表达式声明的 type。它是用值类别修饰的类型。糟糕的关键字选择!
猜你喜欢
  • 2018-02-09
  • 2014-10-08
  • 2022-11-17
  • 2012-05-29
  • 2015-07-29
  • 1970-01-01
  • 2020-03-01
  • 2020-06-08
  • 1970-01-01
相关资源
最近更新 更多