本節知識點:
1.關鍵字new與delete:
a.c++中通過new關鍵字進行動態記憶體分配,new是一種基於型別進行的記憶體分配,同時c++使用delete進行記憶體釋放
單個變數記憶體申請與釋放:type* p = new type; delete p;
一段記憶體空間的申請與釋放:type* p = new type [n]; delete p;
示例**如下:
[cpp]
#include
#include
int main()
for(int i = 0; i < 10; i++)
free(p1);
/*使用new申請一段連續的記憶體空間*/
//new出來的這個空間看著像陣列 但它跟陣列有本質區別 這是在堆區的
int *p2 = new int[10];
for(int i = 10; i > 0; i--)
for(int i = 0; i < 10; i++)
delete p2;
return 0;
}
b.new關鍵字與malloc函式的區別:
第一:new關鍵字是c++的一部分,而malloc是由c庫提供的函式
第二:new是以具體型別為單位進行記憶體分配,malloc只能以位元組為單位進行記憶體分配
第三:new在申請單個型別變數時可進行初始化,malloc不具備記憶體初始化的特性,**如下:
[cpp]
#include
int main()
2.c++中的命名空間:
a.命名空間產生的原因:在c語言中只有乙個全域性作用區,所有的全域性識別符號(包括全域性變數、函式)共享同乙個全域性作用區。儘管有static關鍵字的限制,但是在工程中依然存在介面函式名之間,或與庫函式名衝突的現象。所以c++中提出了命名空間的概念,命名空間將全域性作用區分成了若干的命名空間和無名空間(即預設空間,也就是相容c語言的全域性作用區的空間)。
b.命名空間的有效作用域:在c語言中沒有命名空間的概念,導致所有在全域性作用區的全域性識別符號的作用域都是,從這個變數或者函式定義宣告開始一直有效到程式結束(從始至終貫穿著整個程式,所有很容易就衝突了)。而c++中有了命名空間的概念後,一旦在乙個函式中使用using namespace name1; using name1::a;這樣的語句的時候,name1這個命名空間的作用域和name1中a變數的作用域,就是從using命令開始到這個函式結束(也就是說可以通過命名空間來控制全域性變數的作用域了)。如果是在乙個命名空間name2中使用using命令的話,那name1和a的作用域就屬於name2了(即與name2屬於相同作用域)。如果在預設命名空間(無名空間)中使用using命令,name1和a的作用域就變化與c語言一樣的那個全域性作用區了。如果使用name1::a這樣方法直接去控制變數的話,那作用域就是使用瞬間。
c.命名空間的語法:
定義命名空間(要在函式外面定義):
[cpp]
namespace name2 //這個是命名空間的巢狀
} 使用命名空間(有三種方式):
第一:using spacename name1; 開啟name1這個命名空間,可以使用這個命名空間中的所有變數了。
第二:using name1::a; 可以使用name1命名空間中的a變數了。
第三:name1::a = 10; 直接使用name1命名空間的a變數
第四:::a = 10; 或者 a = 10; 直接使用預設命名空間中的變數
d.使用命名空間要注意:
第一:命名空間是可以相互巢狀的,且有乙個巢狀順序的問題,不同巢狀順序的命名空間,即使名稱相同,也是不同的命名空間。因為using的時候,是有順序的。
第二:相同名稱的命名空間,在using的時候,兩個命名空間都會被開啟。只要相同名稱的命名空間中沒有同名變數就可以!否則在使用這個變數的時候,就會出現二義性,編譯會出問題。
第三:不同命名空間中,識別符號可以同名而不會發生衝突!因為在使用的時候,不一定會同時using這兩個命名空間,所以不一定會產生二義性!但是如果同時開啟這兩個命名空間,還去使用了這個同名變數,編譯也會出錯,因為產生二義性!但是當using spacename name1;(name1中有變數a) 並且using name2::a的時候,再使用a變數的時候就沒有二義性了,編譯器預設選擇name2中的a變數使用。**如下:
[cpp]
#include
namespace name1
} namespace name2
int main()
3.c++中的強制型別轉換:
a.c語言中的強制型別轉換:有兩種方式,(type) name 和 type (name) 注意第二種方式不是很常用。
b.c語言中強制型別轉換存在的問題:
第一:過於粗暴,任何型別之間都可以進行轉換,編譯器很難判斷其正確性。
第二:難於定位,在原始碼中無法快速定位所有使用強制型別轉換的語句。
補充:在程式設計理論中強制型別轉換不被推薦,與goto語句一樣,應該進行避免,因為在程式設計過程中,定義變數就應該清楚變數的使用環境,直接定義成有效的型別,避免強制型別轉換。還有就是現代的軟體產品裡面有三個問題是bug的源泉:有運算子的優先順序問題、多執行緒程式設計中各個執行緒的互動、強制型別轉換。
c.c++中將強制型別轉換分成四個型別:
static_cast型別:用於基本型別間的轉換,但不能用於指標型別間的轉換。用於有繼承關係物件之間的轉換和類指標之間的轉換。但是static_cast是編譯期進行的轉換,無法在執行時檢測型別,所以類型別之間的轉換可能存在風險。**如下:
[cpp]
#include
int main()
const_cast型別:用於去除變數的const屬性,注意,它只能去除const int* p或者const int& p這兩種型別中的const屬性。比如int* const p型別中的const屬性是去不掉的,其實不管用什麼手段這個const的屬性都是去不掉的,int* const p = &a; p一旦指向就不能再改變指向,這其實就是引用的實質!!!
const_cast型別有三個常用環境:第一,去除const int &j;的const唯讀屬性、第二,去除const int * j;的const唯讀屬性、第三,去除const int j;的const唯讀屬性。**如下:
[cpp]
#include
int main()
對於上面**有兩點要說明:
第一:const_cast其實唯讀const指標和const引用起作用了,對const常量沒有起作用,因為const常量是儲存在符號表中的。
第二:對於引用的強制型別轉換,int a = 10; (char)a這是將a變數中的值強制型別轉換成char型別,切記此時(char)a不是變數不能當做左值使用。但是(char&)a是將a強制型別轉換成char型別的引用,其實是乙個變數可以當做左值使用!對於const_cast(l) = 17; 來說l常量是存放在符號表中的,而const_cast(l)其實是個有記憶體空間的變數,其實相當於對l取位址的時候,編譯器分配了乙個記憶體空間,這個空間不是用來存放l常量的,而是強制型別轉換後這個引用的記憶體空間,所以說這個17就存放在這個引用的記憶體空間了!!!
reinterpret_cast型別:用於指標型別間的強制型別轉換,用於整數和指標間的強制型別轉換,還用於引用間的強制型別轉換。(注:此處指標引用的強制型別轉換都是沒有const屬性去除過程的,否則優先使用const_cast)
引用間的強制型別轉換(**如下):
[cpp]
#include
int main()
我們仔細說說**中c引用與b引用的關係,不可否定的是abc三個變數,有其中任何乙個變數改變了,都會對另外的兩個起到改變的作用!a與b僅僅是名字不同的問題(其餘完全相同),但是c引用是與b引用變成char型別引用變數後完全相同的。
reinterpret_cast型別用法,**如下:
[cpp]
#include
int main()
reinterpret_cast是直接從二進位制位進行複製,是一種極其不安全的轉換。
dynamic_cast型別:主要用於類層次間的轉換,還可以用於類之間的交叉轉換。dymanic_cast具有型別檢查的功能,比static_cast更安全。這個問題等對類有了理解再回來補充。
c 學習筆記 4 c 中新的關鍵字
1.關鍵字new與delete a.c 中通過new關鍵字進行動態記憶體分配,new是一種基於型別進行的記憶體分配,同時c 使用delete進行記憶體釋放 單個變數記憶體申請與釋放 type p new type delete p 一段記憶體空間的申請與釋放 type p new type n de...
C 筆記 關鍵字
c 關鍵字 and 用法 等同於 的作用 and eq 用法 等同於 的作用 asm 用法 宣告內聯彙編塊 暫時不明白怎麼使用 auto 用法 1.自動儲存期說明符 c 11 前 暫時不明白怎麼使用 2.帶尾隨返回型別的函式宣告 c 11 起 暫時不明白怎麼使用 3.結構化繫結宣告 c 17 起 暫...
C 學習筆記 explicit關鍵字
c 中的explicit 關鍵字用來修飾類的建構函式,表明該建構函式是顯式的,既然有 顯式 那麼必然就有 隱式 那麼什麼是顯示而什麼又是隱式的呢?如果c 類的建構函式有乙個引數,那麼在編譯的時候就會有乙個預設的轉換操作 將該建構函式對應資料型別的資料轉換為該類物件,如下面所示 class mycla...