使用初始化列表初始化內(nèi)置類型的時候,編譯器會做更加嚴(yán)格的檢查。
按書上的說法j和k都會有編譯錯誤。而i可能不會有編譯錯誤,雖然現(xiàn)在大多數(shù)的編譯器在i的時候都會報錯。所以個人覺得對于內(nèi)置類型也使用初始化列表來初始化不是個強(qiáng)制要求,因為代碼看起來不舒服,還要多打幾個字母。
int i = 1.1;
int j{ 1.1 };
int k = { 1.1 };
任何顯式的初始化都會把聲明變成定義。
extern int g_i = 0;這是個定義。
聲明其實(shí)也可以寫在函數(shù)內(nèi)。
比如在調(diào)試程序的時候,我喜歡寫下面這樣的代碼。目的在于懶得跳到函數(shù)的最前面寫上extern int g_i,跳來跳去麻煩,回頭要刪除代碼的時候,也要刪兩處。而直接在用的地方這么寫就方便多了。當(dāng)然在正式的產(chǎn)品代碼中,不推薦這么寫。
int foo(){
extern int g_i;
g_i = 10;
}
P33 如何表示類型的最大最小值。
如果想知道各個類型的最大最小值,在C下應(yīng)該查看三個頭文件:limits.h,float.h,stdint.h。其中規(guī)定了諸如INT_MAX,ULONG_MAX的宏。
在C語言出生的那個年代,處理器各種各樣,為了保證C語言的可移植性,C語言的標(biāo)準(zhǔn)甚至連char bit都是用宏來定義的。
define CHAR_BIT 8 /* number of bits in a char */
在C++語言下使用頭文件limits(沒有.h的版本)里面的std::numeric_limits。
std::numeric_limits<int>::lowest()
std::numeric_limits<int>::max()
不太熟悉和用的不多的C++關(guān)鍵字 P43
- alignas
- alignof
- noexcept
- constexpr
- thread_local
操作符替代名 P43
其實(shí)挺喜歡用not代替!,因為!有時候太小了,常常忘記沒看到。用not就可讀多了,不過似乎沒人這么用,那就算了吧。
#include <iso646.h>
int foo(int *p){
if (!p){}
if (not p){}
}
內(nèi)置類 P45
沒聽過這個詞,
constexpr
這個東西后面的章節(jié)還要提,暫時這里就不去深究了。constexpr指的是一種在編譯階段就能計算出值的表達(dá)式,在某些特定場合,比如說聲明數(shù)組的時候,都必須使用編譯期常量,因為編譯器必須知道數(shù)組的長度。比如說下面的代碼是可行的。
const int a = 10;
int b[a + 20] = { 0 };
但是在C++03的時代,一個常量是否被當(dāng)成編譯期常量完全是編譯器自己憑感覺。比如說下面size()明顯就是個常量,但是編譯器并不會把它當(dāng)成一個常量。
int size(){ return 10; }
int c[size()] = { 0 }; //error here
所以直覺上c++11引入這個新的東西的目的就是告訴編譯器這里需要一個編譯期常量,請試圖去計算這個表達(dá)式。比如說下面這段代碼是正確的,編譯器是會在編譯階段來計算sum(10)的值。PS: VS2013還沒有很好的支持constexpr,所以要嘗試下面的代碼,可以試試GCC或者Clang
constexpr int sum(int n) {
return n <= 1 ? 1 : n + sum(n - 1);
};
int d[sum(10)] = { 0 };
constexpr指針
如果嚴(yán)謹(jǐn)?shù)恼f,consexpr不一定都是編譯期就能及計算出來的值,比如說constexpr指針。從下面這段代碼為例,p1的值必須等到運(yùn)行階段才能知道,所以p2 - p1就不可能是一個constexpr了
//global
int i, j;
constexpr int * p1 = &i;
constexpr int * p2 = &j;
constexpr int c1 = p2 - p1; // wrong here
某些情況下編譯器也能比較聰明的處理下面這種情況。
int a[10];
constexpr int *p = &a[1];
constexpr int *pp = &a[5];
constexpr int c = pp - p; // correct
類型別名 P60
初略的查了一下資料,using和typedef是等價的,所以應(yīng)該用using來替代掉typedef。主要目的是可讀性比較好。
指針,常量和類型別名 P61
書上提到了把pstring展開后來理解類型是不對的,cstr和cstr1其實(shí)是不一樣的類型。
typedef char* pstring;
const pstring cstr = 0; // cstr is const pointer to char type
const char* cstr2 = 0; // cstr2 is pointer to const char type
這里想了個小技巧,沒有特別細(xì)究,但估計是正確的方法。當(dāng)遇到const T的情況,把前置的const寫到類型后面,如T const。這樣在做展開就沒錯了。
pstring const cstr = 0; // const pointer to char type;
char * const cstr2 = 0; // const pointer to char type;
當(dāng)把const放到后面以后,解讀類型就可以方便的從右到左的讀出來。
把&替換成reference to,把*替換成pointer to;那就是很自然的話了。
char *p;
char const * const & k = p; // K is reference to const pointer to const char;
top-level const和low-level const
如果把const放到了類型的右邊,那么top-level const就是直接靠近變量的標(biāo)識符的const,這個const限制的是變量本身不能改變。為什么會用top-level和low-level這兩個詞呢,估計是從編譯原理里面的語法樹分析借鑒來的。
auto關(guān)鍵字。
auto關(guān)鍵字有兩個特點(diǎn),頂層的引用屬性和const屬性會被去掉。
const int ci = 10;
const int &r = 10;
auto a = &ci;
const auto &b = r;
&c的類型是int const *,所以沒有top-level const。那么a的類型就是int const *
&r的類型是int const &,去掉頂層的引用變成int const,那么b的類型就是(int const) const & b; 兩個const都修飾左邊的int。也就是int const & b
decltype就沒有講透,需要進(jìn)一步的細(xì)化。
這個東西在寫模板的時候很有用處,所以需要仔細(xì)的了解。
關(guān)于表達(dá)式i=10的類型
在練習(xí)2.37 P64也提到了i=x的類型是int&,所以下面這段代碼是可行的。但只是在C++下可行,在C下是不可行的。
int i, *p;
(i = 10) = 20;
p = &(i = 1);
當(dāng)使用字符串初始化std::string時,如果字符串中間包含了'\0'字符,如何繞過去。
如例子s2,可以使用另外一個構(gòu)造函數(shù)Constructs the string with the contents of the range [first, last).
int main(){
char s[] = "first\0second";
string s1(s); // only get "first "
cout << s1.length() << " : " << s1 << endl;
string s2(s, s + sizeof(s));
cout << s2.length() << " : " << s2 << endl;
}
輸出是
5 : first
13 : first second