c++ - 关于decltype获取表达式类型的问题以及decltype和引用
天蓬老师
天蓬老师 2017-04-17 11:44:19
0
2
575

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附近。
恳求各位给予答疑,非常感谢!

天蓬老师
天蓬老师

欢迎选择我的课程,让我们一起见证您的进步~~

全部回覆(2)
伊谢尔伦

1) 你說為什麼編譯器是如何取得到類型的,首先你要了解宣告的本質是什麼?

declaration is a statement in a program that communicates this 
information to the compiler
.

  • 摘自 Stanford 語意分析 - Types and Declarations

直白的說,你的 f() 在聲明的那一刻,編譯器就已經記住了你所聲明的類型。你用 decltype 的時候,只是直接用了這個結果而已。

這個問題,超出了 C++ Primer 的範疇,你需要學習編譯原理。

2) 顯然,你沒搞清楚 intint& 的差別。請回到 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.

回到你的問題。如果是 intdecltype(*p) c; 不會報錯;如果是 int&,會報錯。

所以強調。


@王子亭提醒我題主可能是不清楚為何返回的是int&, 這個可能看過書就比較清楚了,為了更清楚的描述題主的疑問,我將書上這部分代碼在此補全:

cppint 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 條)。

左手右手慢动作

(沒看過 C++ Primer)

  1. int f() 這裡不是已經寫了 f 的回傳值是 int 型別嘛,編譯時當然可以分析出 f() 的型別是 int.
    decltype 的性質就和 sizeof 是類似的,sizeof(f()) 也是可以在編譯時求值的。

「如果decltype 的物件是一個表達式且是一個左值,則結果是它的引用類型」這只是一個規定,我也說不太清楚設計者的邏輯,但可以看一下維基百科的這個頁面,上面有一些比較細緻的討論http://zh.wikipedia.org/wiki/Decltype

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板