日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

精解C++的switch语句

發(fā)布時間:2025/3/20 c/c++ 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 精解C++的switch语句 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?入門書籍對switch語句的介紹相對較淺,我也因此而產生了很多想當然的誤解。為解惑而寫了以下一小篇精解switch語句,相信會對很多朋友有所幫助,同時順便補充一些相關知識。

  先拋出個題目,見下程序:

//原代碼出自《C語言參考手冊(原書第5版)》

//為了表達我的意圖,特做了部分改動

switch(x)

{

??? default:

??? if(prime(x))

??? {

?????? case 2: case 3: case 5: case 7:

?????????? process_prime(x);

??? }

??? else

??? {

?????? case 4: case 6: case 8: case 9: case 10:

?????????? process_composite(x);

??? }

}

  你能說出它如何執(zhí)行嗎?

  switch語句的格式為:

switch(條件)語句

  其中,條件的類型可以是整數類型,枚舉類型,或者類類型(但該類需要有單一的轉換到整數類型或(可以是字符類型,但不能是浮點類型、字符串、指針類型等),語句部分不一定非得是一條復合語句。因此,switch("123"[2]+(int)3.1);是條合法的switch語句,switch(j)case 5:i++;也是條合法的switch語句。如果switch的語句部分是一條非復合語句,則其內定義的變量作用域,效果上等同于該條語句加上了{}。如int i=3;switch(i)int i=4;,相當于int i=3;switch(i){int i=4;},因此這并不會導致同一局部域下的重復定義錯誤。

  如果條件為類類型,則該類內要有一個用戶定義的類型轉換操作符重載函數。如下邊代碼:

#include <iostream>

using namespace std;

class CTest

{

public:

??? operator int(){cout<<"int"<<endl;return data;}

??? operator char(){cout<<"int"<<endl;return static_cast<char>(data);}

??? CTest(int i):data(i){}

??? CTest(char c):data(c){}

private:

??? int data;

};

int main()

{

??? CTest x1(3);

??? CTest x2('5');

??? switch(x1)

??? {

??? case '5':break;

??? case 3:break;

??? }

??? return 0;

}

在VC++6下,編譯器會報如下錯誤信息:

error C2450: switch expression of type 'class CTest' is illegal Ambiguous user-defined-conversion

因為類型轉換函數有兩個都是整數類型,編譯器無法判斷該去調用哪一個進行轉換。

  條件也可以是int i=3這樣的初始化,其結果就是i的值。其作用域從聲明處開始,直至switch語句的結束。可以理解成在switch外再加上了{}。int i=3,j=4這樣的多個初始化,在C++標準中,不是條件。

  語句部分,可以出現多個case標號以及一個default標號,它們的出現順序隨意。一個case標號或default標號,與屬于其上層最近的switch語句,如:

switch(i)

{

case 1:

case 2:

??? if(a>5)

??? {

case 3:

case 4:

?????? b=4;

?????? switch(j)

?????? {

?????? case 5:

?????? default:;

?????? }

default:;

??? }

}

中,case 3:、case 4:,以及最后一個default:,屬于外層switch,雖然它們在if語句內。注意在上面的代碼中,}前的最后一個標號,后面至少要出現一條語句,因此如果沒有內容的情況下,也至少要以一個空語句;作為結束。

  case標號后為一個整數類型的常量表達式,因此int i=3;switch(i){case 3:;}合法,而int i=3;switch(3){case i:;}不合法,因為case i:的i不是個靜態(tài)表達式。如果將int i=3;換成const int i=3;則后者在C++中就合法了,但在C中仍然不合法。原因是C和C++對const的處理不同,在C中,const限定的量是不能直接去修改的,但它本身并不是常量表達式;在C++中,const限定的量,如果其值能在編譯時確定,則其可出現在必須使用常量表達式之處。

  同一個switch的各個case標號的值不能夠相互重復。要注意的是,case標號在實現中是有上限的:C89標準要求至少257個,這保證了ASCII被switch列舉一遍。

  雖然要求case標號是常量表達式,看起來似乎不是很零活方便(比如對比VB的Select Case),但是這樣的設計可以保證更高的效率,而效率則是C和C++最為看重的因素。因為case標號的值是編譯時可確定的整數類型,又因為其不可有重復,因此編譯器可以進行優(yōu)化。比如以下代碼:

switch(b)

{

case 0: ...

case 1: ...

...

case 255: ...

}

不用被翻譯成

if(b==0)

...

else if(b==1)

...

else if(b==255)

...

這樣當b為255的情況,將最慢被執(zhí)行到。而如果編譯器對256個數字進行了優(yōu)化,它可以根據比較的頻率及重要性,產生這樣的代碼:

if(b<128)

{

??? if(b<64)

??? ...

}

else

{

??? if(b<192)

??? ...

}

這樣的折半法,會減少每個比較經歷的步數,在一個多層循環(huán)中的switch語句的執(zhí)行效率會因此而得到提高。當然,前提是你要知道什么時候適合用它比較好,如命令行參數的解析。如果條件相對復雜,就使用if else而不是switch。

  對switch比較常見的誤解,就是把switch理解成if,把:

switch(b)

{

case 1: ... ;break;

case 2: ... ;break;

case 3: ... ;break;

default: ... ;break;

}

理解成它其實就是:

if(b==1)

{

??? ...

}

else if(b==2)

{

??? ...

}

else if(b==3)

{

??? ...

}

else

{

??? ...

}

沒錯,以上兩段代碼執(zhí)行的效果的確等價,但是:

switch(b)

{

case 1: ...

case 2: ...

case 3: ...

default: ...

}

并不等價于:

if(b==1)

{

??? ...

}

else if(b==2)

{

??? ...

}

else if(b==3)

{

??? ...

}

else

{

??? ...

} //如果代碼如此生成,則不僅不使用break的分支要多生成一條goto,而且對條件值的比較,也分散到了多個地方,低效!

  如果每個標號后面,沒有加break,則switch代碼的執(zhí)行會發(fā)生下落。上面的switch代碼應該理解成:

//偽代碼

{

??? if(b==1)goto case 1;

??? else if(b==2)goto case 2;

??? else if(b==3)goto case 3;

??? else goto default;

??? goto end_of_switch //如果沒有default的話

??? {

??? case 1: ...

??? case 2: ...

??? case 3: ...

??? default: ...

??? end_of_switch:

??? }

}

而switch語句內最外層的break本身,作用就相當于偽代碼的goto end_of_switch。這解釋了各標號后的代碼執(zhí)行順序,進而明白下落的具體原理。它也解釋了標號順序為何可以隨意。

  switch的執(zhí)行方式:switch對條件求值,然后對所有的case標號(如果有的話)進行比較(可能被優(yōu)化過比較順序,或者被比較的條件值一直放在某個寄存器中,用CMP這樣的匯編指令以提高效率),符合哪個就像goto一樣跳到指定的標號。如果沒成功,就會去goto default。如果程序沒寫default,則跳到switch語句下一條的位置。case標號和default標號,本身與普通標號類似,并不會在其出現處,設置else if進行條件判斷,因此也不會影響下落。比較并轉移到相應標號的代碼,可以理解成完全是switch(條件)自己一句所生成的。

  回到文章開始的那個題目,我們將其轉換成對應的偽代碼:

{

??? if(x==2)goto case 2; //實際匯編代碼可能做優(yōu)化

??? else if(x==3)goto case 3;

??? else if(x==5)goto case 5;

??? else if(x==7)goto case 7;

??? else if(x==4)goto case 4;

??? else if(x==6)goto case 6;

??? else if(x==8)goto case 8;

??? else if(x==9)goto case 9;

??? else if(x==10)goto case 10;

??? else goto default;

??? goto end_of_switch; //此句無用,有default時無產生的必要

??? {

??? default:

??????? if(!prime(x))goto part_of_else;//為了方便理解,將if語句也轉換了

??? case 2:

??? case 3:

??? case 5:

??? case 7:

?????????? process_prime(x);

??????? goto end_of_if;

??????? part_of_else:

??? case 4:

??? case 6:

??? case 8:

??? case 9:

??? case 10:

??????????? process_composite(x);

??????? end_of_if:;

??? end_of_switch:;

??? }

}

  該程序的if部分,用prime()函數來求x值是否為質數,如果是則調用process_prime(),否則去調用process_composite()。但是,其他部分的因素,在于大多數情況下,要判斷的數<=10。如果對<=10的情況,也要完全靠調用prime(),則無疑會降低效率。為此,該switch會先行對2至10范圍內的情況進行判斷,并跳轉相應位置進行處理。如果不在2至10范圍的,則跳轉到default,往下再調用prime進行判斷。

?????? 當switch(x)int i=3;

  最后要強調的問題是,C++中goto不能從前往后跳過變量定義,因此switch內出現的變量定義語句,最好放在復合語句{}中包起來。

請看以下代碼:

switch(x)

{

case 0: f0(); break;

case 1:CTest i(3); f1(); break;

default: fdef();

}

其偽代碼為:

{

??? if(x==0)goto case 0;

??? else if(x==1)goto case 1;

??? else goto default;

??? {

??? case 0:

?????? f0();goto end_of_switch;

??? case 1:

?????? CTest i(3);

?????? f1();

?????? goto end_of_switch;

??? default:

?????? fdef();

??? end_of_switch:

?????? CTest::~CTest();

??? }

}

當x為0或1時,不會有問題,問題是當轉到default時,相當于從外層直接跳過了i的構造,然后在default自己的代碼執(zhí)行完畢后,還要執(zhí)行i的析構。改成:

switch(x)

{

case 0: f0(); break;

case 1:{CTest i(3); f1(); break;}

default: fdef();

}

則i的作用域被限制在{}中,不會再出現未構造就析構的問題。

?

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/myliupp/archive/2009/08/07/4420792.aspx

總結

以上是生活随笔為你收集整理的精解C++的switch语句的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。