標籤:其它 pointer 指標 #define 機制 童鞋 int change value
最近學習演算法和刷題基本都是用C++寫的程式,在這個過程中,發現C++和Java在文法上有很多相同點,但也有很多不同點,而這些不同點對於已經掌握Java的程式員來說,理解C++代碼可能會有些吃力甚至困難,在踩過了一個又一個坑後,我決定把這些不同記錄下來,可能涵蓋的不是很全,所以本文會持續更新。
零、目錄1. new關鍵字2. C++執行個體化對象的幾種方式3. C++初始設定式4. C++建構函式後的冒號5. C++中難以省略的分號;6. C++中的::7. C++中的*、&、->8. C++函數前或者函數後的const一、new關鍵字
// C++中:MyClass* a = new MyClass();delete a;// Java中:MyClass a = new MyClass();
- C++中new關鍵字執行個體化對象之後返回的是一個對象的指標,所以需要定義指標;而Java中定義對象時返回的其實也是一個指標(引用),但是在Java中不需要顯示的定義指標。
不同點
- C++中通過new關鍵字執行個體化的對象在使用完畢後需要使用delete關鍵字手動釋放記憶體;而Java中由於記憶體回收機制的存在,我們無需手動釋放記憶體。
二、C++執行個體化對象的兩種方式
// 方式一MyClass* a = new MyClass();delete a;// 方式二MyClass b();
- 方式一中new關鍵字做了三件事:首先在堆記憶體上獲得記憶體空間(類似malloc函數),然後調用類的建構函式,最後返回該記憶體空間的指標;因為是在堆記憶體的動態分配的記憶體空間,所以最後需要調用delete函數釋放這一部分記憶體空間。
- 方式二中直接在棧記憶體上分配了儲存空間,類似於基本類型的定義,所以無需手動釋放記憶體空間;但是當對象資訊量較大時,這種做法會佔用很多記憶體,影響程式效率。
三、C++初始設定式
int a(10); // 等效於 int a = 10;
與java不同,C++除了使用指派陳述式初始設定變數之外,還可以使用上述初始設定式對變數進行初始化,其效果相同。
四、C++建構函式後的冒號
// 初始設定式class MyClass { public: const int a; int b; MyClass(int aVal, int bVal):a(aVal), b(bVal) {}};// 非初始設定式,無法通過編譯,編譯時間會報以下錯誤:// ‘const int MyClass::a‘ should be initializedclass MyClass { public: const int a; int b; MyClass(int aVal, int bVal) { a = aVal; b = bVal; }};
這個文法其實就是上述第四點中的初始設定式,但這裡我們看到下面這種賦值方式在建構函式裡面會報錯,這又是為什麼呢?因為這裡我們的冒號初始化和指派陳述式乾的事情不太一樣:在冒號初始化時,只有冒號後面有相應變數的初始設定式,就會在為成員變數分配記憶體時進行初始化,所以常量a在分配記憶體時做了初始化操作,之後也沒有被改變值,所以不會報錯;而在使用指派陳述式時,建構函式在執行到函數體時已經為a分配了記憶體但卻沒有對其進行初始化,因此就會報should be initialized編譯錯誤了。
這種神奇的寫法我第一次見的時候也是驚訝了一波。
五、C++中難以省略的分號;
在上面例子中我們看到了C++類的定義後面也要加分號;我們知道在Java中類定義的大括弧後面都無需加分號。
之後查資料發現:
在C++中,除函數,及先行編譯指令外,其它的語句或程式碼片段結尾都必須要加分號。其中先行編譯指令是指,以#開頭的語句。常見的有,#include ,#define, #ifdef, #if, #elif, #else,#endif等。
六、C++中的::(範圍符)
C++的範圍符::用法有三,一一介紹如下
全域範圍符
int a = 3;void test() { int a = ::a; cout << a << endl;}
這裡就是將全域變數a的值通過全域範圍符的方式訪問到,然後將其值賦給test函數中的局部變數a。
類範圍符
class MyClass { public:void sayHello();};void MyClass::sayHello() { cout << "hello world!" << endl;}
這裡有點類似Java中定義介面和對介面進行實現;首先在類的定義中定義了一個函數sayHello,但是沒有具體函數體,然後在類的定義外,通過範圍符,在函數sayHello前加了一個MyClass::,相當於告訴編譯器,這個函數就是MyClass類的sayHello方法的具體實現。
命名空間範圍符
std::cout << "hello world!" << endl;
這裡std就是命名空間,這樣的用法相當於using namespace std;
七、C++中的*、&、->
class MyClass { public: int a; MyClass(int aVal):a(aVal){}};int main () { MyClass obj(5); MyClass* objPointer = new MyClass(3); // 常規操作 cout << obj.a << endl; // 取指標操作 cout << (*objPointer).a << endl; // ->操作 cout << objPointer->a << endl; // 取地址操作 cout << (&obj)->a << endl; // new出來的對象別忘了釋放記憶體哦 delete objPointer; return 0;}
在C++中:
- *表示訪問指標a指向的變數;
- &表示取得變數的地址;
- .表示訪問對象的的成員變數或者函數;(與Java相同)
->表示訪問指標指向的對象的成員變數或者函數;
指標內容實在太多,這裡就不贅述了,有興趣的童鞋可以參考菜鳥教程
八、C++函數名前或者函數名後的const
函數名前的const
const int getVal() { const int a = 3; return a;}int main() { cout << getVal() << endl;}
就是定義函數的傳回型別,規定返回變數類型必須為const。
函數名後的const(用於類的成員函數中)
class MyClass { public:int a;MyClass(int aVal):a(aVal){}void sayHello() const { cout << "a value is: " << a << endl;}// 編譯報錯:assignment of member ‘MyClass::a‘ in read-only objectvoid changeA() const { a = 5;}};
函數名後面的const表示是該函數為常成員函數,該函數不能修改對象內的任何成員變數,只能發生讀操作,不能發生寫操作。這樣可以對成員變數起到保護作用。
C++與Java文法上的不同