宣告還是表示式?二義性?如何避免?

2021-06-10 00:52:59 字數 1523 閱讀 4730

通過乙個例項來引出本文要闡述的問題。具體的**為:

dequetest;

copy(istream_iterator(cin), istream_iterator(), back_inserter(test)); 

上面的**很明顯是先宣告了乙個名為test的deque容器,並將其初始化為空。然後,將從標準輸入流(cin)中讀入的以空格的乙個個string推入容器,直到沒有更多可用的輸入為止。它等效於:

dequetest;

istream_iteratorfirst(cin) , last;

copy(first, last, back_inserter(test));

再看看使用下面的語句來宣告乙個同樣的名為test的deque容器。           

dequetest(istream_iterator(cin),istream_iterator());

我們寫出上面的語句的本意與之前的本意一樣,從標準輸入流(cin)中讀入的以空格的乙個個string推入容器,直到沒有更多可用的輸入為止。不過我們是想通過呼叫deque的接受一對迭代器為引數的建構函式來實現其功能。那麼它能完成我們設想的功能嗎?

其實」dequetest(istream_iterator(cin),istream_iterator());「 的功能只是宣告乙個名為test的函式,並且其返回值型別為deque,而需要傳入的引數有兩個,第乙個是型別為 istream_iterator而名為cin的引數,第二個為不接受任何引數的無名引數。它並沒有實現我們想要的「宣告乙個名為test的deque物件,並通過傳入的一對迭代器將其初始化」。為什麼會出現這種情況呢?

引用c++ 03標準的原話:當宣告和表示式語句兩者的語法形式之間可能出現二義性,即乙個函式風格的顯式型別轉換作為其最左端的子表示式的表示式語句和乙個其第乙個宣告子以「(」開頭的宣告語句可能會無法區分開。在這種情況下,該語句被解釋為宣告。

簡而言之就是當出現了宣告與表示式二義性時,編譯器總是會將其決議為宣告。

那麼如何能夠避免出現這種問題呢?

既然這是由語法形式之間的二義性導致的,那麼就可以將該語句「修飾」為非法的宣告的語句從而消除其二義性。而想徹底的擺脫二義性,就不要使用那些會讓有些編譯器誤認為時宣告的語法形式。一般有兩種方法:

1.避免讓編譯器將其識別為乙個函式宣告,直接的做法就是:

dequetest((istream_iterator(cin)),(istream_iterator()));

通過給引數新增額外的括號,提示編譯器我們這裡提供的是建構函式而非引數宣告。冗餘的括號使得這種形式的**不可能被解釋為合法的宣告語句

2.使用具名變數作為建構函式的引數,徹底避免宣告語句產生二義性。

istream_iteratorfirst(cin) , last;

dequetest(first , last);

顯然方法2的**更佳清晰,而且更加便於維護。所以最好使用方法2來避免宣告與語句的二義性。

函式宣告與表示式

1.函式的呼叫方式 2.函式的建立有兩種常用的方式 函式宣告和函式表示式,還有一種不常見的叫函式構造器 2.1.函式宣告 2.2.函式表示式 有以下幾種定義方式。最後一種叫命名函式表示式,不常用,遞迴時可能用到。函式宣告和函式表示式最大的區別是函式宣告會被前置。左側的函式宣告可以執行,右側的函式表示...

Quartz Cron 表示式(二)

本文主要介紹quartz cron 表示式,關於quartz 請看這裡quartz 基礎知識及示例 一 quartz cron 表示式被空格分開形成7個子表示式 欄位名允許的值 允許的特殊字元 秒0 59 分0 59 時0 23 日1 31 l w c 月1 12 or jan dec 星期1 7 ...

表示式 表示式樹 表示式求值

總時間限制 1000ms 記憶體限制 65535kb 描述 眾所周知,任何乙個表示式,都可以用一棵表示式樹來表示。例如,表示式a b c,可以表示為如下的表示式樹 a b c 現在,給你乙個中綴表示式,這個中綴表示式用變數來表示 不含數字 請你將這個中綴表示式用表示式二叉樹的形式輸出出來。輸入輸入分...