C++復習

register關鍵字請求“編譯器”將局部變量存儲于寄存器中
C語言中無法取得register變量地址

在C++中依然支持register關鍵字
1、C++編譯器有自己的優化方式,不使用register也可能做優化
2、C++中可以取得register變量的地址
C++編譯器發現程序中需要取register變量的地址時,register對變量的聲明變得無效。

早期C語言編譯器不會對代碼進行優化,因此register變量是一個很好的補充。


C語言的struct定義了一組變量的集合,C編譯器并不認為這是一種新的類型
C++中的struct是一個新類型的定義聲明


理論上bool只占用一個字節,
如果多個bool變量定義在一起,可能會各占一個bit,這取決于編譯器的實現


1)C語言返回變量的值 C++語言是返回變量本身
C語言中的三目運算符返回的是變量值,不能作為左值使用
C++中的三目運算符可直接返回變量本身,因此可以出現在程序的任何地方

2)注意:三目運算符可能返回的值中如果有一個是常量值,則不能作為左值使用
(a < b ? 1 : b )= 30;

3)C語言如何支持類似C++的特性呢?
當左值的條件:要有內存空間;C++編譯器幫助程序員取了一個地址而已


// C語言中 const修飾的變量是一個 常變量,本質還是變量,有自己的地址空間
// C++中 const 變量聲明的是一個真正的常量,不是變量,所以編譯器不會為該常量分配空間
// const 修飾的常量會被放到 符號表 中
const int a = 10;

// 這里對 const 常量取地址,這一步操作會讓編譯器為該變量分配空間,分配的空間并不會被 a 使用
int p = (int )&a;

// 通過指針改變指向的空間的值,這個空間是編譯器為常量分配的空間,但是常量的值并不在這個空間內
// 所以即使通過指針修改了這個空間的值,也不會影響到 a 本身
*p = 5;

// a 的值不變,因為它的值在符號表中,不在程序運行的空間內
printf (“%d, %p\n”, a, *p);


C++中的const常量類似于宏定義
const int c = 5; ≈ #define c 5
C++中的const常量與宏定義不同
const常量是由編譯器處理的,提供類型檢查和作用域檢查
宏定義由預處理器處理,單純的文本替換
在程序運行過程中const變量只有一個拷貝,而#define 所定義的宏變量卻有多個拷貝,所以宏定義在程序運行過程中所消耗的內存要比const變量的大得多;


引用:

void swap1 (int &a, int &b)
{int tmp = a;a = b;b = tmp;
}void swap2 (int *a, int *b)
{int tmp = *a;*a = *b;*b = tmp;
}int main()
{int a = 10;int b = 20;swap2 (&a, &b);swap1 (a, b);printf ("%d, %d\n", a, b);return 0;
}

引用在C++中的內部實現是一個常指針
Type& name ?è Type* const name

C++編譯器在編譯過程中使用常指針作為引用的內部實現,因此引用所占用的空間大小與指針相同。

從使用的角度,引用會讓人誤會其只是一個別名,沒有自己的存儲空間。這是C++為了實用性而做出的細節隱藏

當我們使用引用語法的時,我們不去關心編譯器引用是怎么做的
當我們分析奇怪的語法現象的時,我們才去考慮c++編譯器是怎么做的
若返回棧變量
// 用非引用類型接收函數返回的引用,就等于將函數返回的引用的數據值,復制給了該接收對象
// 效果和返回非引用數據是一樣的
若返回棧變量
不能成為其它引用的初始值
不能作為左值使用
若返回靜態變量或全局變量
可以成為其他引用的初始值
即可作為右值使用,也可作為左值使用
const & int e 相當于 const int * const e
普通引用 相當于 int *const e1
當使用常量(字面量)對const引用進行初始化時,C++編譯器會為常量值分配空間,并將引用名作為這段空間的別名
使用字面量對const引用初始化后,將生成一個只讀變量
普通引用在定義必須要初始化,引用是一塊空間的別名,如果空間不存在,引用 就沒有意義


內聯函數

// 內聯函數聲明時inline關鍵字必須和函數定義結合在一起,否則編譯器會直接忽略內聯請求。
inline int func(int a, int b)
{return a < b ? a : b;
}
/*C++編譯器可以將一個函數進行內聯編譯
被C++編譯器內聯編譯的函數叫做內聯函數
內聯函數在最終生成的代碼中是沒有定義的
C++編譯器直接將函數體插入在函數調用的地方 
內聯函數沒有普通函數調用時的額外開銷(壓棧,跳轉,返回)
*/
//**C++編譯器不一定準許函數的內聯請求!
/*內聯函數是一種特殊的函數,具有普通函數的特征(參數檢查,返回類型等)
內聯函數是對編譯器的一種請求,因此編譯器可能拒絕這種請求
內聯函數由 編譯器處理,直接將編譯后的函數體插入調用的地方
宏代碼片段 由預處理器處理, 進行簡單的文本替換,沒有任何編譯過程
*/
/*
現代C++編譯器能夠進行編譯優化,因此一些函數即使沒有inline聲明,也可能被編譯器內聯編譯
另外,一些現代C++編譯器提供了擴展語法,能夠對函數進行強制內聯
如:g++中的__attribute__((always_inline))屬性
*/
/*
C++中內聯編譯的限制:
不能存在任何形式的循環語句    
不能存在過多的條件判斷語句
函數體不能過于龐大
不能對函數進行取址操作
函數內聯聲明必須在調用語句之前
*/
/*
編譯器對于內聯函數的限制并不是絕對的,內聯函數相對于普通函數的優勢只是省去了函數調用時壓棧,跳轉和返回的開銷。因此,當函數體的執行開銷遠大于壓棧,跳轉和返回所用的開銷時,那么內聯將無意義
*/

只有參數列表后面部分的參數才可以提供默認參數值
一旦在一個函數調用中開始使用默認參數值,那么這個參數后的所有參數都必須使用默
將所有同名函數作為候選者
嘗試尋找可行的候選函數:
1 )精確匹配實參
2) 通過默認參數能夠匹配實參
3) 通過默認類型轉換匹配實參
匹配失敗:
1) 最終尋找到的可行候選函數不唯一,則出現二義性,編譯失敗。
2) 無法匹配所有候選者,函數未定義,編譯失敗。

當使用重載函數名對函數指針進行賦值時:
根據重載規則挑選與函數指針參數列表一致的候選者
嚴格匹配候選者的函數類型與函數指針的函數類型

構造
// 一個函數返回一個對象的時候會創建一個匿名對象,拿返回的那個對象
// 對匿名對象進行初始化,會調用拷貝構造
// 如果沒有去接收函數的返回值的話,匿名對象會立馬被銷毀
// test6_1();
// 如果用一個對象去接收函數的返回值,先用函數返回的對象去初始化
// 匿名對象,調用一次拷貝構造,然后拿新的對象的名字去命名這個匿名對象
// 匿名對象從無名轉成有名
// Test6_1 t1 = test6_1();
當對象作為函數參數傳遞的時候會調用拷貝構造
析構的順序和構造的順序相反,先構造的后析構

// 對象初始化列表,在構造函數后面加:,后面加上要初始化的對象
// 對象初始化列表要比當前類的構造函數先執行
// 對象的初始化先后順序和 在對象初始化列表 的順序無關,和在類中的聲明先后順序有關 
Test9_2():m_a(10), m_c(30), m_b(20), m_ca(100)
{printf ("9_2 222222222222構造函數....\n");
}
// 構造函數中調用構造函數 不會達到預期的效果的
Test10_1(int a, int b)
{m_a = a;m_b = b;Test10_1(a, b, 30);  // 匿名對象、臨時對象
}
// 靜態成員函數只能使用靜態成員變量
// 靜態成員變量,屬于類,不屬于某個對象
// 是所有對象共享的,靜態是在數據區分配,只有一個備份
// 靜態變量不能由某個對象進行初始化
// 靜態變量必須在類的外部重新定義并且初始化// 重新定義類的靜態變量并且初始化
int Test11::sm_a = 100; // 類的靜態變量的使用
// 1、通過某一個對象進行引用
t2.sm_a = 30;// 2、通過類名來引用
Test11::sm_a = 60;  

// malloc 和 free:它們本身不是C語言的語法的一部分,是庫函數提供的 函數
// new 和 delete: 它們本身是C++語言的一部分,是 運算符 不是 函數

// 創建普通類型變量
int main12_1()
{int *p1 = (int *)malloc(sizeof(int));free(p1);// new + 數據類型int *p2 = new int;*p2 = 10;printf ("*p2 = %d\n", *p2);// 釋放 new 出來的空間delete p2;// new 可以在申請空間進行初始化int *p3 = new int(90);printf ("*p3 = %d\n", *p3);delete p3;return 0;
}// 申請數組
int main12_2()
{int *p = (int *)malloc(sizeof(int) * 10);free(p);// 用 new 申請數組 new + 數據類型[size]int *p1 = new int[10];// deleta釋放數組 必需要加 [] delete [] p1;return 0;
}class Test12
{
public:Test12(int a, int b){m_a = a;m_b = b;printf ("構造函數\n");}~Test12(){printf ("析構函數\n");}
private:int m_a;int m_b;
};// 動態創建對象
int main12_3()
{Test12 *p = (Test12 *)malloc(sizeof(Test12));free(p);// new 在創建對象的時候會自動構造函數進行對象的構建Test12 *p1 = new Test12(10,20);// delete在進行釋放對象的時候會自動調用析構函數進行對象資源的回收delete p1;return 0;
}

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

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

相關文章

Docker 方式安裝 Nginx 、阿里云服務器上裝 Ngnix

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 非 Docker 方式安裝&#xff0c;直接 Linux 安裝見另一文&#xff1a;Linux 上 安裝 nginx 、阿里云服務器上安裝 nginx 1. 直接從鏡像倉…

C#實現A*算法

理解A*尋路算法具體過程 這兩天研究了下 A* 尋路算法, 主要學習了這篇文章, 但這篇翻譯得不是很好, 我花了很久才看明白文章中的各種指代. 特寫此篇博客用來總結, 并寫了尋路算法的代碼, 覺得有用的同學可以看看. 另外因為圖片制作起來比較麻煩, 所以我用的是原文里的圖片. 當…

路考口訣

路考口訣一 一踩&#xff08;踩離合&#xff09;、二掛&#xff08;掛一檔&#xff09;、三看&#xff08;看倒車鏡&#xff09;、四轉&#xff08;轉向燈&#xff09;、五按&#xff08;按喇叭&#xff09;、六手剎、七走 路考口訣二 01.路考之道很輕松&#xff0c;牢…

nfs服務器工作原理

https://www.cnblogs.com/me80/p/7464125.html轉載于:https://www.cnblogs.com/huhuxixi/p/11203049.html

玩轉數據結構——均攤復雜度和防止復雜度的震蕩(筆記)

數據規模 時間復雜度 并不是所有的雙層循環都是O&#xff08;n^2&#xff09;的 復雜度實驗來確定復雜度 // O(N) 兩倍增加 int findMax( int arr[], int n ){assert( n > 0 );int res arr[0];for( int i 1 ; i < n ; i )if( arr[i] > res )res arr[i];return res…

解決:bash: vim: command not found、docker 容器不識別 vi / vim 、docker 容器中安裝 vim

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 在 Docker 容器中編輯文件&#xff0c;報錯如下&#xff1a; bash: vim: command not found2. 安裝 vim &#xff1a; apt-get in…

路考

路考基本項目組成 路考即是科目三&#xff0c;是新增加的一個考試項目&#xff0c;基本項目有13項&#xff0c;包括上車準備、起步、直線行駛、變更車道、通過路口、靠邊停車、通過人行橫道線、通過學校區域、通過公共汽車站、會車、超車、掉頭、夜間行駛。 上車準備 …

OpenDDS通訊rtps_discovery對等發現模式的pub和sub匹配的日志

OpenDDS的通訊體系中&#xff0c;提供了豐富的日志輸出&#xff0c;通過日志輸出可以清晰的看到pub和sub方的主題匹配的過程&#xff0c;是加深對OpenDDS過程了解的一個好方法。 下面的日志&#xff0c;以OpenDDS3.8為基礎&#xff0c;增加了部分日志和時間戳輸出。 rtps_dis…

Developing Web Applications with Apache, MySQL, memcached, and Perl

Developing Web Applications with Apache, MySQL, memcached, and Perl轉載于:https://www.cnblogs.com/gavinhughhu/archive/2009/11/02/1594290.html

awk 中 {print $1} 什么意思

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 舉個例子 echo "aa bb cc" | awk -F {print $1} 結果就是aa&#xff0c;意思是把字符串按空格分割&#xff0c;取第一個。aw…

有駕照不等于會開車,教你開車技巧27招

當今有車的人真的是越來越多了&#xff0c;不要以為自己有駕照就是會開車了哦&#xff0c;其實開車還是有很多技巧的。下面就跟小編看下學會那些招數才真算會開車吧。 1、上車先看車 上車前繞車轉一圈&#xff0c;看車的外況、輪胎、車底下有沒有漏油漏水。一個星期還得揭開蓋子…

OpenDDS通訊中rtps_discovery對等發現的基本配置和說明

OpenDDS的對等發現模式中&#xff0c;可以采用組播或單播方式進行發現和基于主題的DataReader和DataWriter的匹配&#xff0c;下面是一個簡單的配置樣例&#xff1a; [common] DCPSGlobalTransportConfig$file ORBDebugLevel0 DCPSDebugLevel3 DCPSTransportDebugLevel0 ORBLo…

用戶使用協議

知乎協議&#xff08;草案&#xff09; 歡迎您來到知乎。 請您仔細閱讀以下條款&#xff0c;如果您對本協議的任何條款表示異議&#xff0c;您可以選擇不進入知乎。當您注冊成功&#xff0c;無論是進入知乎&#xff0c;還是在知乎上發布任何內容&#xff08;即「內容」&#xf…

解決: bash: unzip: command not found、linux 安裝 zip 命令

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 執行解壓命令報錯&#xff1a; bash: unzip: command not found 2. 安裝 zip&#xff1a; yum install -y unzip zip 3. 重試成功…

基于OpenDDS開發發布訂閱HelloMsg程序的過程(Windows)

基于OpenDDS的應用開發&#xff0c;主要分兩個部分的工作&#xff1a; &#xff08;1&#xff09;定義自己的IDL文件&#xff0c;并編譯成消息數據類型通訊動態庫&#xff1b; &#xff08;2&#xff09;分別編寫pub和sub程序&#xff0c;運行 具體步驟&#xff0c;有以下幾…

面試后的總結

面試中的收獲&#xff1a; 優點&#xff1a; 1. 設計用例考慮較為全面。 2. 自動化&#xff0c;性能都有涉獵&#xff0c;但不深入。 3. 對業務理解較深入。 缺點&#xff1a; 1. 接口自動化停留在初級階段。 2. UI自動化了解較少。 3. 性能壓測缺少數據清洗等步驟。 4. 算法還…

怎樣正確使用車燈?

當我們被對面來車明晃晃的遠光燈照得意識模糊時&#xff0c;當你快速接近一輛摩托車卻發現那是一輛壞了一盞尾燈的卡車時&#xff0c;或是當你前方的小車忽然亮起倒車燈卻在往前行駛&#xff0c;最后意識到那只是因為剎車燈與倒車燈線路顛倒時&#xff0c;你就會發現在人們都認…

如何配置DDS以使用多個網絡接口?How do I configure DDS to work with multiple network interfaces?

最近在使用OpenDDS的時候遇到一個問題&#xff1a;存在多個虛擬網卡時&#xff0c;發布&#xff08;訂閱&#xff09;端重新連接時會阻塞幾分鐘&#xff0c;在外網找到一篇與此相關的文章。 You cannot specify which NICs DDS will use to send data. You can restrict the NI…

oracle賦予一個用戶查詢另一個用戶中所有表

說明&#xff1a;讓用戶selame能夠查詢用戶ame中的所有表&#xff08;不能添加和刪除&#xff09;1.創建用戶selamecreate user selame identified by Password;2.設置用戶selame系統權限grant connect,resource to selame; 3.設置用戶selame對象權限 grant select any table t…

使用可靠多播與OPENDDS進行數據分發

介紹 也許應用程序設計人員在創建分布式系統時面臨的最關鍵決策之一是如何在感興趣的各方之間交換數據。通常&#xff0c;這涉及選擇一個或多個通信協議并確定向每個端點分派數據的最有效手段。實現較低級別的通信軟件可能是耗時的&#xff0c;昂貴的并且容易出錯。很多時候&a…