關鍵詞:表達式、語句
本章的內容比較簡單,基本上沒有什麼理解上的困難,都是知識上的問題。先開始想要不要寫呢,本來是不准備寫的,但是既然讀了書就要做筆記,還是寫一寫,畢竟還是有點點收獲的東西。那麼,我只就一些容易弄糊塗和忽略的地方提出來,為日後變成作參考。
一、表達式
(一)概念
表達式時由一個或者多個運算對象組成的,對一個表達式求值將得到一個結果。把一個運算發和一個或者多個運算對象組合起來可以生成較為復雜的表達式。
作用於一個對象的運算符是一元運算符例如:“&”,“*”等。運用於兩個對象的運算符是二元運算符,例如“+”、“-”、“==”、“!=”等。
在C++中表達式要麼是左值,要麼是右值。左值可以位於賦值語句的左側、右值不能。當一個對象被用作右值的時候,用的是對象的值(內容);當對象被用作左值的史詩,用的是對象的身份(在內存中的位置)。我們熟悉的運算符都是要用到左值的。
使用關鍵則decltype的時候,我們根據左值右值的判斷可以知道decltype得到的類型。如果表達式求值的結果是左值,decltype得到一個引用類型,如果表達式求值結果是右值,則得到一個指針類型。例如int *p;那麼decltype(*p),*p是左值,得到的是int &引用,decltype(&p)得到的結果是指針,int**。
(二)一些值得注意的運算符
取負,一元符號運算是對象值取負後,返回其(提升後)的副本。要注意,無符號型的數和BOOL型的數不能做這樣的運算。無符號型取負值會提升成有符號類型,如果沒有溢出就相安無事,如果溢出了一般會發生“環繞”,跟第一章中間講的溢出差不多的性質。布爾型的數據取負後會提升成int型,我們知道true=1,取負就成了-1。但是對於bool型是非0為true,0為false,所以取負以後還是true。
取模運算“%”,我們規定m%(-n)=m%n,(-m)%n=-(m%n)。簡單的說,取模運算的符號是由前面那個數的符號決定的。所說,(-m)%(-n)=-(m%n)。
遞增運算符(++)和遞減運算符(--),即為對象加1和對象減1。這兩種運算也可以用於不支持算數運算的迭代器。我們以遞增運算符為例,遞減運算符類似,分為前置版本++i,和後置版本i++。前置版本的意思是先對i加1再作為左值返回,後置版本是將對象的原始值的副本作為右值返回,再自加。
int i=0;
int j=i++;
cout<<i<<" "<<j<<endl;
j=++i;
cout<<i<<" "<<j<<endl;
第一個j=i++;是j賦值為i的原始值副本以後,i再自加。第二個++i,是i先自加以後再賦值給j。一般我們更習慣用++i而不采用i++。
另外,還要值得注意的是,++運算符的優先級是高於解引用運算符的。我們假設p是一個指針,那麼*p++的意思是*(p++);把p的值加1,然後返回p的值的初試副本作為其求值結果,解引的值是沒有自加後的結果。
int a[10];
int *p=a;
for(int i=0;i<10;++i)
a[i]=i;
for(int i=0;i<10;++i)
{
cout<<*p++<<" ";
}
條件運算符(?:), 這裡有幾個有趣的例子。
int grade=50;
cout<<((grade<60)?"fail":"pass");
cout<<(grade<60)?"fail":"pass";
cout<<grade<60?"fail":"pass";
第三條cout語句是編譯都通不過的,前面兩條是對的。我們輸出結果看一看。
第一個輸出的是(grade<60)?"fail":"pass"這個語句的值,第二個輸出的是1,其實就是grade<60的值是true。所以當你不清楚優先級的時候最穩妥的方法就是打括號。
位移運算符(<<,>>),按照二進制移動,記住左移<<變大,右移>>變小,多的去掉。我們可以用位移運算符來處理類似於BOOL型的數組問題,這裡不詳述。另外我們熟悉的cout<<,cin>>這種重載版本的IO運算符,IO重載我們會在後面的章節詳述,需要了解的是“cout<<”返回的還是一個cout,cin是一個道理。
Sizeof()運算符,是的它是一個運算符,不是一個函數,它的運算結果部分的依賴於作用的類型。對應用類型執行sizeof()得到的是被引用對象所占空間大小。對指針執行sizeof()運算得到的是指針本身所占的空間。我們可以用下面這種語句來求數組元素的個數:
int a[10]={0};
cout<<"sizeof(a):"<<sizeof(a)<<endl;
cout<<"sizeof(*a):"<<sizeof(*a)<<endl;
cout<<sizeof(a)/sizeof(*a)<<endl;
顯示轉化static_cast。可以消除強制類型轉換的時候報WARNNING
把常量轉化成變量:const_cast;
隱式的類型轉換我們再第一章中已經說過了,不再贅述。
在我們編程的過程中基本上碰到的一些奇怪的操作符就是上面著一些的,如果你的表達式得到的結果並不是你想要的最好的方法就是多試幾遍。
歇口氣,喝口水。如果您覺得這些對您一點點幫助或者寫的有些問題,可以給我留言,來鼓勵鼓勵我吧~如果想抱走的話希望能夠引用我的鏈接~麼麼哒。
二、語句
語句就是我們基本說的條件語句、迭代語句什麼的,平時都很常用,這裡只對一些需要注意的點說明一下。
if-else語句,這種語句我們都很熟悉,唯一需要說明的是,在C++中規定else是跟最近的未匹配的if配對。
if(a) if(b) else c;
這裡的else 是跟if(b)匹配的。不過建議還是用花括號來明確表示吧。
Switch(){case:}語句。Switch內部的變量必須是個常量且為整數,char,int,bool都可以,但是不能是浮點數。另外每一個case對應一個break,如果不寫break的話,會接著做下一條case,且不用滿足下一條case的條件,這個應該都很熟悉了;不能夠跨case聲明變量。也就是
case 1:int a;break;
case 2:a=3;break;
這樣是不行的,原因可以參見一下變量的作用域問題。
跳轉語句break,continue。作用於最近的循環語句。Break是跳出循環,continue是碰到了以後不再做下面的語句,直接進入下一次循環。下面一小段代碼可以說明這個問題:
int a[10];
for(int i=0;i<10;++i)
{
a[i]=i*6-i*i;
cout<<a[i]<<" ";
}
cout<<endl;
for(int i=0;i<10;++i)
{
if(a[i]>7)break;
cout<<a[i]<<" ";
}
cout<<endl;
for(int i=0;i<10;i++)
{
if(a[i]>7)continue;
cout<<a[i]<<" ";
}
Break是碰到大於7的數就跳出循環了。而continue是不輸出大於7的數。
另外還有goto語句,一般都不會用到它,它會造成一些混亂,但是有時候卻有你意想不到的奇效,不過還是能不用盡量不用吧,這屬於高難度動作啦。
最後還有拋出異常語句,簡單的說一下就是try{一段程序,有問題我們就throw一個異常}然後用catch接住這個異常並且做相應的處理。對於程序的健壯性和安全性的處理是件很困難的事情,經驗很重要。
如果有人看是我寫下去的動力啦~當然沒人不看我也會寫的,因為知識和成長是自己的~~~