2016-01-29 29 views
38

經常想到的一個示例是:什麼是C++中未評估的上下文?

sizeof表達式,它不評估表達式,而是通過靜態類型確定大小。例如:

int func(); 
sizeof(func()); 

這是我的思維極限,所以如果還有其他未評估的上下文,那麼它們是什麼?

+9

我真的很驚訝,這個問題之前沒有問過(或者我沒有找到它)。這是一個很好的。除了'sizeof'之外,我只知道'decltype'和'noexcept'。 – 5gon12eder

+0

'auto'關鍵字用於聲明和定義變量時? – CinCout

+2

@HappyCoder我想你混淆的東西。 – bolov

回答

33

幸運的是,標準具有那些的一個方便的列表(第5 [EXPR]¶8):

在一些上下文中,不計算操作數出現(5.2.8,5.3.3,5.3.7, 7.1.6.2)。未評估的操作數未被評估。一個未評估的操作數被認爲是一個完整的表達式。

讓我們來詳細看看這些。

我將在我的示例中使用以下聲明。聲明的函數從未在任何地方定義過,因此如果調用它們出現在評估的上下文中,則該程序不合格,我們將得到鏈接時錯誤。然而,在沒有評估的情況下調用它們是很好的。

int foo(); // never defined anywhere 

struct widget 
{ 
    virtual ~widget(); 
    static widget& get_instance(); // never defined anywhere 
}; 

typeid

§5.2.8 [expr.typeid]¶3:

typeid施加到其他的表達比一個多態類類型的glvalue,所述結果指的是表示表達式的靜態類型的對象std::type_info。左值到右值(4.1),數組到指針(4.2)和函數到指針(4.3)的轉換不適用於表達式。如果表達式的類型是一個類的類型,那麼該類應該被完全定義。 該表達式是未評估的操作數 (第5章)。

注爲多態類的強調異常(一個class與至少一種virtual構件)。

因此,這是正常的

typeid(foo()) 

,併產生一個std::type_info對象int,而這

typeid(widget::get_instance()) 

不和可能會產生一個鏈接時錯誤。它必須評估操作數,因爲動態類型是通過在運行時查找vptr來確定的。

<rant>我覺得很令人困惑的是,操作數的靜態類型是否是多態的這一事實改變了操作符的語義,如此戲劇性但又微妙的方式。 < /咆哮>

sizeof

§5.3.3 [expr.sizeof]¶1:

sizeof操作者產生在其操作數的對象表示的字節數。 該操作數是任一種的表達,這是一個未計算的操作數(第5章)或括號型-ID。所述sizeof操作者不得應用於具有功能或不完整的類型的表達式,爲枚舉類型,其基礎類型是不固定的其所有統計員之前已經聲明,這種類型的帶括號的名稱,或一個glvalue,它指定待位字段。

以下

sizeof(foo()) 

是完全沒有與相當於sizeof(int)

sizeof(widget::get_instance()) 

也是允許的。但是請注意,這是相當於sizeof(widget),因此可能不是非常的多態return類型有用。

noexcept

§5.3.7 [expr.unary.noexcept]¶1:

noexcept操作員確定是否它的操作數,這是一個未計算的操作數的評價(第5章),可以拋出異常(15.1)。

表達

noexcept(foo()) 

是有效的,計算結果爲false

這裏是一個更現實的例子,這也是有效的。

void bar() noexcept(noexcept(widget::get_instance())); 

請注意,只有內部noexcept是運算符,而外部是說明符。

decltype

§7.1.6.2 [dcl.type.simple]¶4.4:

decltype說明符的操作數是一個未計算的操作數(第5章)。

聲明

decltype(foo()) n = 42; 

聲明int類型的變量n並與值42

auto baz() -> decltype(widget::get_instance()); 

初始化聲明的函數baz,它沒有參數和return SA widget&

這就是所有的(就像C++ 14一樣)。

+1

評論中還有一點是'auto'也涉及到的。另一個答案也提到'auto',但不清楚。是這樣嗎? – bolov

+2

'auto'與'decltype'在同一部分中引入,但我不明白這是一個未評估的上下文。它甚至不需要操作數。 「7.1.6.2」中出現「未評估」這個詞的唯一情況是在我的答案中引用的段落中。但IANAL。 – 5gon12eder

+0

@ 5gon12eder爲什麼'typeid(* singleton :: get_instance())'工作? – vsoftco

6

標準項是未計算的操作數,您可以在[EXPR]

在某些情況下,未評估的操作數出現(5.2.8,5.3.3,5.3.7,7.1中找到它。 6.2)。未評估的操作數未被評估。一個未評估的操作數被認爲是一個完整的表達式。 [注意:在未評估操作數中,非靜態類成員可能被命名爲(5.1),而對象或函數的命名本身並不要求提供定義(3.2)。末端音符]

  • 5.2.8覆蓋typeid
  • 5.3.3覆蓋sizeof
  • 5.3.7覆蓋noexcept
  • 7.1.6.2覆蓋簡單類型說明符如autodecltype和POD類型如int,char,double
相關問題