代碼疑云

代碼疑云(1)-掌握初始化列表


代碼

[cpp] view plaincopy
  1. #include<iostream>??
  2. using?namespace?std;??
  3. class?A??
  4. {??
  5. private:??
  6. ??int?x1;??
  7. ??int?x2;??
  8. public:??
  9. ??A():x2(1),x1(x2++){}?//初始化列表??
  10. ??void?print()??
  11. ??{??
  12. ????cout<<"x1="<<x1<<endl??
  13. ????????<<"x2="<<x2<<endl;??
  14. ??}??
  15. };??
  16. int?main()??
  17. {??
  18. ??A?a;??
  19. ??a.print();??
  20. ??
  21. ??return?0;??
  22. }??

:x1,x2最終被輸出什么值呢?為什么?

解答:上機調試下會發現輸出的結果是:x1是一個隨機數,x2是1。為什么?因為在初始化列表中在給x1賦值為x2++時,這個x2并未初始化,也就是說x2里面什么東西也沒裝。也許你會問我不是在前面已經給x2賦值了嗎,沒錯,但是有一個問題你忽略了,那就是初始化列表的賦值順序是依照x1和x2的聲明順序的順序來初始化的,也就是說在代碼中,程序是先給x1賦值為x2++(此時x2并未初始化),再給x2賦值為1。還有初始化列表里的賦值,是在變量被聲明時進行的,所以多使用初始化列表是可以提升程序效率的。

!!代碼疑云系列由本人在天天唯C論壇下首發


代碼疑云(2)-c函數調用約定

代碼:

[cpp] view plaincopy
  1. #include<iostream>??
  2. using?namespace?std;??
  3. void?foo(int?p1,int?p2,int?p3)??
  4. {??
  5. ??cout<<"p1="<<p1<<endl??
  6. ??????<<"p2="<<p2<<endl??
  7. ??????<<"p3="<<p3<<endl;??
  8. }??
  9. int?main()??
  10. {??
  11. ??int?i;??
  12. ??cout<<"first?call:"<<endl;??
  13. ??i=0;??
  14. ??foo(++i,++i,++i);??
  15. ??cout<<"second?call:"<<endl;??
  16. ??i=0;??
  17. ??foo(++i,i++,i++);??
  18. ??return?0;??
  19. }??

:兩次調用foo函數分別輸出了什么,為什么?

解答:按照cedel函數調用的約定,編譯器使參數從左到右的入棧。第一次調用為什么p1,p2,p3的值全是3呢,原因在此,在foo被call之前三++i 操作將先被操作也就是連續自增了3次,最終結果i 的值是3,然后是編譯器push(i),push(i),push(i)三次入棧,然后call到foo定義處依次出棧并相應地復制給了形參。第二次調用foo時,一開始與第一次一樣先是計算三次++操作,但是所不同的是最后兩個是i++,i++ 剛沒說到它們的計算順序,編譯器計算這些的順序是由右到左的,也就是先i++,再i++,最后是++i,而運算i++是先取值再自增的,編譯器會先把i (這時為0)存入寄存器(cpu中的存儲器),再加1,然后計算下一個i++ 與前一次一樣,所不同的是這次 i 的值是1,因為前面已加1 ,最后++i 。

!!代碼疑云系列由本人在天天唯C論壇下首發



代碼疑云(3)-靜態字符串

代碼:

[cpp] view plaincopy
  1. #include<iostream>??
  2. using?namespace?std;??
  3. int?main()??
  4. {??
  5. ??char?*str1?=?"string";??
  6. ??char?*str2?=?"string";??
  7. ??if(str1?==?str2)??
  8. ????cout<<"str1?is?same?as?str2";??
  9. }??

:str1 的值是否等于 str2 而輸出字符串“str1 is same as str2”呢,為什么? 解答:是的 “str1 is same as srr2”,也就是說str1與str2指向了相同的內存地址,因為"string"是靜態對象,是由編譯器分配給他的內存空間,在代碼中出現了兩次,編譯器并不會給他們分別分配空間,因為如果這樣將會造成不必要的浪費。


代碼疑云(4)-類的sizeof值

代碼:

[cpp] view plaincopy
  1. #include<iostream>??
  2. using?namespace?std;??
  3. class?A??
  4. {??
  5. ??
  6. };??
  7. class?B??
  8. {??
  9. ??char?a;??
  10. ??int?b;??
  11. };??
  12. class?C??
  13. {??
  14. ??void?foo(){};??
  15. };??
  16. class?D??
  17. {??
  18. ??virtual?void?foo(){};??
  19. };??
  20. int?main()??
  21. {??
  22. ??cout<<sizeof(A)<<sizeof(B)<<sizeof(C)<<sizeof(D);??
  23. ??return?0;??
  24. }??

:結果是什么,為什么呢?

解答:sizeof(A)為1,而不是0,雖然空類沒有任何成員變量,但其實體提供取地址操作,所以其內存空間不能為0。sizeof(B)為8,編譯器在計算類體或結構體變量的地址時是通過字節對齊的方式進行的,也就是通過加多少偏移量來確認是那個變量。類的偏移量為其最大內存空間的類型的成員變量的長度,其最大內存空間類型成員是int,所以偏移量為4字節,即char a成員需要補上3個字節,才能讓編譯器準確高效地尋址,再加上int的4字節,sizeof(B)就是8了。sizeof(C)為1,類的成員函數在編譯器編譯時,其函數地址就已自動存放,所以不必為其分配額外的空間來存放他,所以它的長度跟空類一樣為1。sizeof(D)為4,因為類D需要構造一虛函數列表來存放函數指針以實現動態調用,一個指針的長度占用4個字節,所以為4.


代碼疑云(5)-類成員函數的thiscall約定

代碼:

[cpp] view plaincopy
  1. #include<iostream>??
  2. using?namespace?std;??
  3. ??
  4. class?A??
  5. {??
  6. private:??
  7. ??int?value;??
  8. public:??
  9. ??A()??
  10. ??{??
  11. ????value=0;??
  12. ??}??
  13. ??void?coutHello()??
  14. ??{??
  15. ????cout<<"hello"<<endl;??
  16. ??}??
  17. ??void?coutValue()??
  18. ??{??
  19. ????cout<<value<<endl;??
  20. ??}??
  21. };??
  22. int?main()??
  23. {??
  24. ??A?*pA=NULL;?//空指針,所指向的內容不可訪問存取??
  25. ??
  26. ??pA->coutHello();??
  27. ??pA->coutValue();??
  28. ??
  29. ??return?0;??
  30. }??

(感謝網友提供的題目)

疑:調用coutHello和coutValue方法有什么問題?
解答: 成員函數的地址在編譯器編譯時給出的,所以是已知的,根據thiscall約定,類的成員函數在編譯時編譯器會傳入一個this指針,通過this指針指向成員變量,在調用couthello時并未用到this指針所以調用正常,而調用coutvalue時,value需要用到this指針,因為此時this是NULL指針,所以會發生內存報錯。



代碼疑云(6)-頭文件的正確定義

代碼:

頭文件print_tools.h

[cpp] view plaincopy
  1. #include<stdio.h>??
  2. void?printStr(const?char?*pStr)??
  3. {??
  4. ??printf("%s\n",pStr);??
  5. }??
  6. void?printtInt(const?int?i)??
  7. {??
  8. ??printf("%d\n",i);??
  9. }??

頭文件counter.h
[cpp] view plaincopy
  1. #include"print_tools.h"??
  2. static?int?sg_value;??
  3. void?counter_init()??
  4. {??
  5. ??sg_value=0;??
  6. }??
  7. void?counter_count()??
  8. {??
  9. ??sg_value++;??
  10. }??
  11. void?counter_out_result()??
  12. {??
  13. ??printStr("the?result?is:");??
  14. ??printtInt(sg_value);??
  15. }??

main.cpp
[cpp] view plaincopy
  1. #include?"print_tools.h"??
  2. #include?"counter.h"??
  3. int?main()??
  4. {??
  5. ??char?ch;??
  6. ??counter_init();??
  7. ??printStr("please?input?some?charactors:");??
  8. ??while((ch=getchar())!='$')??
  9. ????{??
  10. ??????if(ch=='A')??
  11. <span?style="white-space:pre">????</span>counter_count();??
  12. ????}??
  13. ??counter_out_result();??
  14. }??

疑:以上代碼編譯時有何問題嗎,是什么導致的呢?

解答:void printStr(const char*)和'void printtInt(int) 函數redefine了,道理很簡單,因為在counter.h中已包含了print_tools.h,在main.cpp中又包含了print_tools.h頭文件,也就是兩次包含了print_toosl.h,所以也就發生了重定義錯誤,這是初學者常見問題,要避免這個問題,我們必須采取防范措施,就是使用預編譯命令,如下作修改:

頭文件print_tools.h

[cpp] view plaincopy
  1. #ifndef?PRINT_TOOLS_H?//如果未定義?PRINT_TOOLS_H??
  2. #define?PRINT_TOOLS_H?//則定義?然后編譯以下源代碼??
  3. #include<stdio.h>??
  4. void?printStr(const?char?*pStr)??
  5. {??
  6. ??printf("%s\n",pStr);??
  7. }??
  8. void?printtInt(const?int?i)??
  9. {??
  10. ??printf("%d\n",i);??
  11. }??
  12. #endif?//結束?//如此改頭文件就只被編譯器編譯一次了,起到了防范重定義錯誤的作用??

頭文件counter.h
[cpp] view plaincopy
  1. #ifndef?COUNTER_H??//??
  2. #define?COUNTER_H??//??
  3. #include"print_tools.h"??
  4. static?int?sg_value;??
  5. void?counter_init()??
  6. {??
  7. ??sg_value=0;??
  8. }??
  9. void?counter_count()??
  10. {??
  11. ??sg_value++;??
  12. }??
  13. void?counter_out_result()??
  14. {??
  15. ??printStr("the?result?is:");??
  16. ??printtInt(sg_value);??
  17. }??
  18. #endif?//??

在一個工程項目中頭文件眾多繁雜,采用這個方法可以很好的避免,所以每當我們定義一個頭文件時要養成如此的良好習慣。


代碼疑云(7)-構造函數在類繼承時

代碼

[cpp] view plaincopy
  1. #include?<iostream>??
  2. using?namespace?std;??
  3. class?A??
  4. {??
  5. public:??
  6. ??A()??
  7. ??{??
  8. ????Print();??
  9. ??}??
  10. ??virtual?void?Print()??
  11. ??{??
  12. ????cout<<"A?is?constructed.\n";??
  13. ??}??
  14. };??
  15. ??
  16. class?B:?public?A??
  17. {??
  18. public:??
  19. ??B()??
  20. ??{??
  21. ????Print();??
  22. ??}??
  23. ??
  24. ??virtual?void?Print()??
  25. ??{??
  26. ????cout<<"B?is?constructed.\n";??
  27. ??}??
  28. };??
  29. ??
  30. int?main()??
  31. {??
  32. ??A*?pA?=?new?B();??
  33. ??delete?pA;??
  34. ??
  35. ??return?0;??
  36. }??
(感謝網友提供的題目)

以上代碼輸出結果是?

輸出結果如下:
A is constructed.
B is constructed.
解釋:當new B()時,因為B繼承了A,所以編譯器首先調用A的構造函數,A的構造函數里是調用A類里的Print(),所以首先輸出A is constructed ,然后調用的是B的構造函數,此時Print虛函數指針已指向B的void print(),所以輸出B is constructed。





本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/453276.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/453276.shtml
英文地址,請注明出處:http://en.pswp.cn/news/453276.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

網絡擁塞

擁塞&#xff08;Congestion&#xff09;指的是在包交換網絡中由于傳送的包數目太多&#xff0c;而存貯轉發節點的資源有限而造成網絡傳輸性能下降的情況。擁塞的一種極端情況是死鎖&#xff08;Deadlock&#xff09;&#xff0c;退出死鎖往往需要網絡復位操作。

android 多線程future,多線程FutureTask的使用方法和使用實例

FutureTask是一種可以取消的異步的計算任務。它的計算是通過Callable實現的&#xff0c;它等價于可以攜帶結果的Runnable&#xff0c;并且有三個狀態&#xff1a;等待、運行和完成。完成包括所有計算以任意的方式結束&#xff0c;包括正常結束、取消和異常。Future有個get方法而…

2017.12.26

轉載于:https://www.cnblogs.com/dyh-air/p/8118961.html

mac 下安裝pip

pip是常用的python包管理工具&#xff0c;類似于java的maven。用python的同學&#xff0c;都離不開pip。 在新mac中想用home-brew安裝pip時&#xff0c;遇到了一些小問題&#xff1a; bogon:~ wanglei$ brew install pip Error: No available formula with the name "pip&…

IT職場人生系列

IT職場人生系列之一&#xff1a;序言及找誰占卜 本文是IT職場人生系列的第一篇。 時間流逝&#xff0c;漸漸從之前在公司里邊的小弟變成大哥了&#xff0c;當年身邊比我大的程序員們都不見了&#xff0c;既沒有當領導也沒有去創業&#xff0c;就這么消失了。 年輕的程序員或…

RS-232協議

計算機與計算機或計算機與終端之間的數據傳送可以采用串行通訊和并行通訊二種方式。由于串行通訊方式具有使用線路少、成本低&#xff0c;特別是在遠程傳輸時&#xff0c;避免了多條線路特性的不一致而被廣泛采用。 在串行通訊時&#xff0c;要求通訊雙方都采用一個標準接口&am…

linux sed 找出前后三行,Linux Sed 使用示例

環境&#xff1a;CentOS鑒于語句描述蒼白無力&#xff0c;用例子直接說明。mytxt文件內容&#xff1a;zilzhang 19881110 jiangxi 18 filmzhagnsan 21321 sichuan 100 cardlisi 3435 hunan 65 TV1. 找出文件第二行$ sed -n ‘2p‘ mytxtzhagnsan 21321 sichua…

MessageBox 彈框

模擬系統的消息提示框而實現的一套模態對話框組件&#xff0c;用于消息提示、確認消息和提交內容。 從場景上說&#xff0c;MessageBox 的作用是美化系統自帶的 alert、confirm 和 prompt&#xff0c;因此適合展示較為簡單的內容。如果需要彈出較為復雜的內容&#xff0c;請使用…

什么是同軸電纜

同軸電纜從用途上分可分為基帶同軸電纜和寬帶同軸電纜&#xff08;即網絡同軸電纜和視頻同軸電纜&#xff09;。同軸電纜分50Ω 基帶電纜和75Ω寬帶電纜兩類。基帶電纜又分細同軸電纜和粗同軸電纜。基帶電纜僅僅用于數字傳輸&#xff0c;數據率可達10Mbps。同軸電纜(Coaxial Ca…

android textview表情,Android開發(16)-TextView顯示表情圖像和文字

從這個案例中我們可以學到當我們美化圖片美化界面的時候可以在某一區域輸入圖片和文字混搭信息,第三張圖片按比例縮小&#xff0c;第四張圖像有超鏈接布局文件MainActivity.javapackage com.example.textview3;import java.lang.reflect.Field;import android.os.Bundle;import…

Rating

題目鏈接 題意&#xff1a; 起始狀態是&#xff08;0。0&#xff09;&#xff0c;每次轉移的時候都是對兩個數中的較小的數操作。1&#xff09;以概率p轉向&#xff08;min&#xff08;a 50&#xff0c;1000&#xff09;。b&#xff09; 2&#xff09;以概率1-p轉向&#x…

linux的apache2.4限定某個目錄禁止解析PHP及user_agent與PHP相關配置

限定某個目錄禁止解析PHP 對于使用PHP語言編寫的網站&#xff0c;有一些目錄是有需求上傳文件的&#xff0c;比如服務器可以上傳圖片&#xff0c;并且沒有做防盜鏈&#xff0c;所以就會被人家當成了一個圖片存儲服務器&#xff0c;并且盜用帶寬流量。如果網站代碼有漏洞&#x…

什么是光纜

光纜(optical fiber cable)是為了滿足光學、機械或環境的性能規范而制造的&#xff0c;它是利用置于包復護套中的一根或多根光纖作為傳輸媒質并可以單獨或成組使用的通信線纜組件。光纜主要是由光導纖維&#xff08;細如頭發的玻璃絲&#xff09;和塑料保護套管及塑料外皮構成&…

js調用android播放器,js調用android本地方法

8種機械鍵盤軸體對比本人程序員&#xff0c;要買一個寫代碼的鍵盤&#xff0c;請問紅軸和茶軸怎么選&#xff1f;昨天自己錄了一個android本地調用h5中js方法&#xff0c;可能是因為視頻比較耗費流量&#xff0c;結果看的人不是很多&#xff0c;所以決定還是先寫文章&#xff0…

linux之分區的水深(標準分區方式)

1.首先創建boot分區(200M即可) boot分區作為linux啟動相關信息的存儲介質&#xff0c;不論boot分區什么時候&#xff0c;它都會排在整個硬盤的起始段&#xff0c;方便系統啟動獲取相關信息&#xff0c;用戶盡量不去更改boot分區的掛載點順序。 2.接著創建swap分區&#xff08;應…

doxygen相關問題

doxygen相關問題 我主要的設置有 現在 wizard對話框中大體設置下,然后 export設置: project->DOXYFILE_ENCODINGGBK project->OUTPUT_LANGUAGEchinese input->INPUT_ENCODINGGBK Dot->HAVE_DOT Dot-> UML_LOOK Dot->CALL_GRAPH Dot->CALLER_GRAPH http…

前端之JavaScript 02

一、函數 // 最基礎的函數定義 function f1() {console.log(hello world!); } f1(); // hello world!// 帶參數的函數 function f2(name,age) {console.log("姓名 : " name " 年齡&#xff1a;" age); } f2("jassin",18); // 姓名 : jassi…

什么是雙絞線

雙絞線&#xff08;twisted pair&#xff0c;TP&#xff09;是一種綜合布線工程中最常用的傳輸介質&#xff0c;是由兩根具有絕緣保護層的銅導線組成的。把兩根絕緣的銅導線按一定密度互相絞在一起&#xff0c;每一根導線在傳輸中輻射出來的電波會被另一根線上發出的電波抵消&a…

Android蒙版倒計時,【倒計時海報設計】- 虎課網

我們在大街上經常會看到各種宣傳海報&#xff0c;有時商家為了達到促銷的目的會在醒目的地方張貼一張倒計時海報&#xff0c;為的就是吸引群眾的眼睛&#xff0c;大家了解PS倒計時海報設計的制作過程嗎&#xff1f;如果對這方面操作不太了解的話&#xff0c;大家可以關注一下下…

linkit-smart-7688-feed 安裝筆錄

轉載于:https://www.cnblogs.com/orangezs/p/8571791.html