static
static變數只能初始化一次:
#include #include using namespace std;
void fun(int i)
int main()
輸出為:
0
00
因為static變數只初始化一次,static int value = i這句話只執行一次,也就是fun(0)的時候執行。之後這條語句就不再執行。所以value一直為0。
#include #include using namespace std;
void fun(int i)
int main()
輸出:
1
23
const
const修飾指標:
const char * p; const 在*之前(等價char const * p) 指向常量,指標所指內容不可改,但指標可指向別處。
char * const p; const 在*之後
指標不可改(即不可指向別處),但所指內容可以修改。
const char * const p;指標本身和所指內容都不可改
#include #include using namespace std;
int main()
輸出:
22 2
2 22
常引用:
常引用可用右值初始化
#include #include using namespace std;
int main()
輸出:
3
3 3 1
volatile"
volatile的作用是: 作為指令
關鍵字,確保本條指令不會因
編譯器的優化而省略,且要求每次直接讀值.
簡單地說就是防止
編譯器對**進行優化.比如如下程式:
1
2
3
4
xbyte[2]=0x55;
xbyte[2]=0x56;
xbyte[2]=0x57;
xbyte[2]=0x58;
對外部硬體而言,上述四條語句分別表示不同的操作,會產生四種不同的動作,但是編譯器卻會對上述四條語句進行優化,認為只有
xbyte[2]=0x58(即忽略前三條語句,只產生一條機器**)。如果鍵入volatile,則編譯器會逐一的進行編譯並產生相應的機器**(產生四條
**).
1). 乙個引數既可以是const還可以是volatile嗎?解釋為什麼。
2). 乙個指標可以是volatile 嗎?解釋為什麼。
3). 下面的函式被用來計算某個整數的平方,它能實現預期設計目標嗎?如果不能,試回答存在什麼問題: 1
2
3
4
int
square(
volatile
int
*ptr)
下面是答案:
1). 是的。乙個例子是唯讀的
狀態暫存器。它是volatile因為它可能被意想不到地改變。它是const因為程式不應該試圖去修改它。
2). 是的。儘管這並不很常見。乙個例子是當乙個中斷服務子程式修改乙個指向乙個buffer的
指標時。
3). 這段**是個惡作劇。這段**的目的是用來返
指標*ptr指向值的平方,但是,由於*ptr指向乙個volatile型引數,
編譯器將產生類似下面的**: 1
2
3
4
5
6
7
int
square(
volatile
int
*ptr)
由於*ptr的值可能在兩次取值語句之間發生改變,因此a和b可能是不同的。結果,這段**可能返回的不是你所期望的平方值!正確的**如下: 1
2
3
4
5
6
long
square(
volatile
int
*ptr)
下面我們來乙個個說明。
考慮下面的**:
**:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
classgadget
}
void
wakeup()
//...
private
:
bool
flag_;
};
上面**中gadget::wait的目的是每過一秒鐘去檢查一下flag_成員
變數,當flag_被另乙個執行緒設為true時,該函式才會返回。至少這是程式作者的意圖,然而,這個wait函式是錯誤的。
假設 編譯器發現sleep(1000)是呼叫乙個外部的庫函式,它不會改變成員
變數flag_,那麼編譯器就可以斷定它可以把flag_快取在
暫存器中,以後可以訪問該暫存器來代替訪問較慢的主機板上的記憶體。這對於
單執行緒**來說是乙個很好的優化,但是在現在這種情況下,它破壞了程式的正確性:當你呼叫了某個gadget的wait函式後,即使另乙個執行緒呼叫了wakeup,wait還是會一直迴圈下去。這是因為flag_的改變沒有反映到快取它的暫存器中去。
編譯器的優化未免有點太……樂觀了。
在大多數情況下,把
變數快取在暫存器中是乙個非常有價值的優化方法,如果不用的話很可惜。c和c++給你提供了顯式禁用這種快取優化的機會。如果你宣告
變數是使用了volatile
修飾符,
編譯器就不會把這個
變數快取在
暫存器裡——每次訪問都將去訪問變數在記憶體中的實際位置。這樣你要對gadget的wait/wakeup做的修改就是給flag_加上正確的修飾:
1
2
3
4
5
6
7
class
gadget
;
"
複習知識點
題目 class aclass bextends aclass cextends aclass dextends ba obj newd system.out.println obj instanceofb system.out.println obj instanceofc system.out....
知識點複習
scanf d用於輸入十進位制數 u無符號十進位制輸入 o用於輸入8進製數 c用於輸入單個字元 s用於輸入字串 非空格開始,空格結束,字串變數以 0 結尾 f,lf用於輸入實數,一般使用double,lf 表示對應的輸入量不賦給乙個變數 d printf d帶符號十進位制輸出 u無符號十進位制輸出 ...
C 知識點複習(二)
昨天的複習讓自己有不小的收穫,對一些基礎知識也有了更加深刻的理解,所以今天在昨天的複習基礎上繼續往 後複習,鞏固 1 繼承時的名字遮攔 派生類的成員和基類中的成員重名,那麼就會遮攔從基類繼承過來的成員,派生類在使用該成員時,實際上是派 生類新增的成員,不是從基類中繼承來的 在基類和派生類中,不管是成...