1.
int a =3;
decltype(f()) b =a;
书上说编译器分析表达式的值,却不实际计算表达式的值,编译器并不实际调用函数f,而是使用当调用发生时f的返回值类型作为b的类型。那如果代码中没有调用f,decltype是如何获取类型的呢?
比如代码:
#include<iostream>
using namespace std;
int f()
{
return 1;
}
int main()
{
int a = 3;
decltype(f()) b = a; //这里的decltype是如何获取表达式类型的?
return 0;
}
2 .
decltype(*p) c;//错误,c是int&,必须被初始化
书上说“如果表达式的内容是解引用操作,则decltype将得到引用类型。解引用指针可以得到指针所指的对象,而且还能给
这个对象赋值。因此,decltype(*p)
的结果类型就是int&
,而非int
”
但是这个解释好像也没说明白为什么“c是int&
”,int&
声明的c可以被赋值,int
声明的c也是可以赋值的 啊,为什么非要强调是int&
呢?
ps. 参考的书籍是c++primer第五版(中文版)
以上问题在中文版page63,英文版page71附近。
恳求各位给予答疑,非常感谢!
伊谢尔伦2017-04-17 11:46:19
1) 你说为什么编译器是如何获取到类型的,首先你要了解声明的本质是什么?
A declaration is a statement in a program that communicates this
information to the compiler.
- 摘自 Stanford 语义分析 - Types and Declarations
直白的说,你的 f()
在声明的那一刻,编译器就已经记住了你所声明的类型。你用 decltype
的时候,仅仅是直接用了这个结果而已。
这个问题,超出了 C Primer 的范畴,你需要学习编译原理。
2) 显然,你没搞清楚 int
与 int&
的差别。请回到 2.3.1 References 这一节。
A reference defines an alternative name for an object.
A reference must be initialized.
简单说,int&
是引用,引用是什么?别名。别名是什么?另一个名字。你必须先有一个对象,才能有另一个名字。所以,你可以写:
int i;
但是你不可以写:
int& ri; // error!!! a reference must be initialized.
回到你的问题。如果是 int
,decltype(*p) c;
不会报错;如果是 int&
,会报错。
所以强调。
@王子亭 提醒我题主可能是不清楚为何返回的是 int&
, 这个可能看过书就比较清楚了,为了更清楚的描述题主的疑问,我将书上这部分代码在此补全:
cpp
int i = 42, *p = &i, &r = i; decltype(r + 0) b; // ok decltype(*p) c; // error: c is int& and must be initialized.
书上的解释:(抱歉,我只有英文版)
As we've seen, when we dereference a pointer, we get the object to which the pointer points. Moreover, we can assign to that object. Thus, the type deduced by decltype(*p) is int&, not plain int.
故,decltype(*p) <==> decltype(&i)
, 你明白这个即可。
据我所知,如果你只看到此书的这个地方,应该还不了解左值和右值的。所以,尽量不要想太多。
若你非要打破沙锅问到底,如 @王子亭 所言,C 11 标准(draft N3690)中是规定这个了的:
7.1.6.2/4
The type denoted by decltype(e) is defined as follows:
- 如果 e 是不带括号的 id 表达式或不带括号的类成员访问 (5.2.5),则 decltype(e) 是 e 命名的实体的类型。如果不存在这样的实体,或者如果 e 命名了一组重载函数,则程序格式错误;
- 否则,如果 e 是 xvalue,则 decltype(e) 是 T&&,其中 T 是 e 的类型;
- 否则,如果 e 是左值,则 decltype(e) 是 T&,其中 T 是 e 的类型;
- 否则,decltype(e) 是 e 的类型。
decltype 说明符的操作数是未计算的操作数(第 5 条)。
ringa_lee2017-04-17 11:46:19
(没看过 C Primer)
int f()
这里不是已经写了 f 的返回值是 int 类型嘛,编译时当然可以分析出 f()
的类型是 int.
decltype 的性质就和 sizeof 是类似的,sizeof(f())
也是可以在编译时求值的。
「如果 decltype 的对象是一个表达式且是一个左值,则结果是它的引用类型」这只是一个规定,我也说不太清楚设计者的逻辑,但可以看一下维基百科的这个页面,上面有一些比较细致的讨论 http://zh.wikipedia.org/wiki/Decltype