棧內存:在函數中定義的一些基本類型的變量和對象的引用變量都在函數的棧內存中分配,存取速度比堆要快,僅次於直接位於CPU中的寄存器。但缺點是,存在棧中的數據大小與生存期必須是確定的,缺乏靈活性。
堆內存:用來存放由new創建的對象和數組。在堆中分配的內存,由Java虛擬機的自動垃圾回收器來管理。
C++ 動態內存
棧:在函數內部聲明的所有變量都將佔用棧內存。
堆:這是程序中未使用的內存,在程序運行時可用於動態分配內存。
很多時候,您無法提前預知需要多少內存來存儲某個定義變量中的特定信息,所需內存的大小需要在運行時才能確定。
在 C++ 中,您可以使用特殊的運算符為給定類型的變量在運行時分配堆內的內存,這會返回所分配的空間地址。這種運算符即 new 運算符。
如果您不再需要動態分配的內存空間,可以使用 delete 運算符,刪除之前由 new 運算符分配的內存。
new 和 delete 運算符
== 與equal,簡單的說「equal」比較的是指基本類型比較的是指針最終指向的是數值,"=="比較的是對象地址。這是根本的區別。
複合函數:由兩個函數複合而成的複合函數,當裡層的函數是偶函數時,複合函數的偶函數,不論外層是怎樣的函數;當裡層的函數是奇函數、外層的函數也是奇函數時,複合函數是奇函數,當裡層的函數是奇函數、外層的函數是偶函數時,複合函數是偶函數。只有奇奇是奇奇,別的都是偶。
三角函數:
sin^2(x)+cos^2(x)=1;
1+tan^2(x)=sec^2(x);
1+cot^2(x)=csc^2(x);
cos(2x)=1-2sin^2 (x) = 2cos^2x-1 = cos^2(x)-sin^2(x);
(tan(x))'=sec^2(x) = 1+tan^2(x);
sin(2x)=2sin(x)cos(x);
虛函數和純虛函數:就是java中的抽象,純虛函數只有聲明沒有具體實現就是空方法,在子類中必須重新寫,虛函數就是在基類中寫了有實現。他們都得用關鍵字 virtual(虛擬的) 聲明的函數
1. 虛函數和純虛函數可以定義在同一個類(class)中,含有純虛函數的類被稱為抽象類(abstract class),而只含有虛函數的類(class)不能被稱為抽象類(abstract class)。
2. 虛函數可以被直接使用,也可以被子類(sub class)重載以後以多態的形式調用,而純虛函數必須在子類(sub class)中實現該函數才可以使用,因為純虛函數在基類(base class)只有聲明而沒有定義
3. 虛函數和純虛函數都可以在子類(sub class)中被重載,以多態的形式被調用。
4. 虛函數和純虛函數通常存在於抽象基類(abstract base class -ABC)之中,被繼承的子類重載,目的是提供一個統一的接口。
C++ 中的運算符重載
重載的運算符是帶有特殊名稱的函數,函數名是由關鍵字 operator和其後要重載的運算符符號構成的。與其他函數一樣,重載運算符有一個返回類型和一個參數列表。
Box operator+(const Box&);
聲明加法運算符用於把兩個 Box 對象相加,返回最終的 Box 對象。大多數的重載運算符可被定義為普通的非成員函數或者被定義為類成員函數。如果我們定義上面的函數為類的非成員函數,那麼我們需要為每次操作傳遞兩個參數,如下所示:
Box operator+(const Box&, const Box&);
數據封裝是一種把數據和操作數據的函數捆綁在一起的機制
數據抽象是一種僅向用戶暴露接口而把具體的實現細節隱藏起來的機制
C++ 接口(抽象類):
如果類中至少有一個函數被聲明為純虛函數,則這個類就是抽象類。純虛函數是通過在聲明中使用 "= 0" 來指定的,如下所示:
class Box { public: // 純虛函數
virtual double getVolume() = 0;
#和##運算符
#是預處理?是的,你可以這麼認為。那怎麼用它呢? 別急,先看下面例子:
#define SQR(x) printf("The square of x is %d.\n", ((x)*(x)));
The square of x is 64.
注意到沒有,引號中的字符 x 被當作普通文本來處理,而不是被當作一個可以被替換的語言符號。
假如你確實希望在字符串中包含宏參數,那我們就可以使用「#」 ,它可以把語言符號轉
化為字符串。上面的例子改一改:
#define SQR(x) printf("The square of "#x" is %d.\n", ((x)*(x)));
The square of 8 is 64.
##運算符可以用於宏函數的替換部分。這個運算符把兩個語言符號組合成單個語言符號。看例子:
#define XNAME(n) x ## n
則會被展開成這樣:
x8
也就是說,##就是個粘合劑,將前後兩部分粘合起來
const const 類型的對象在程序執行期間不能被修改改變。
volatile 修飾符 volatile 告訴編譯器不需要優化volatile聲明的變量,讓程序可以直接從內存中讀取變量。對於一般的變量編譯器會對變量進行優化,將內存中的變量值放在寄存器中以加快讀寫效率。
restrict 由 restrict 修飾的指針是唯一一種訪問它所指向的對象的方式。只有 C99 增加了新的類型限定符 restrict。
總結排序:認準1.數組規模。2.數組是否基本有序3.是否要求穩定
記住:冒泡以及歸併是穩定的。
快排不穩定,基本就能解決問題
(1)若n較小(如n≤50),可採用直接插入或直接選擇排序。
當記錄規模較小時,直接插入排序較好;否則因為直接選擇移動的記錄數少於直接插人,應選直接選擇排序為宜。
(2)若文件初始狀態基本有序(指正序),則應選用直接插人、冒泡或隨機的快速排序為宜;
(3)若n較大,則應採用時間複雜度為O(nlgn)的排序方法:快速排序、堆排序或歸併排序。
快速排序是目前基於比較的內部排序中被認為是最好的方法,當待排序的關鍵字是隨機分布時,快速排序的平均時間最短;
堆排序所需的輔助空間少於快速排序,並且不會出現快速排序可能出現的最壞情況。這兩種排序都是不穩定的。
若要求排序穩定,則可選用歸併排序。但本章介紹的從單個記錄起進行兩兩歸併的 排序算法並不值得提倡,通常可以將它和直接插入排序結合在一起使用。先利用直接插入排序求得較長的有序子文件,然後再兩兩歸併之。因為直接插入排序是穩定 的,所以改進後的歸併排序仍是穩定的。
計算機原理中的位向量表示集合:
a=[01101001]表示{0,3,5,6}
b=[01010101]表示{0,2,4,6}
最終a&b={01000001}={0,6}
以題目的例子來講,a=[01101001],從右邊數起,第0、3、5、6位是1,所以就表示了0、3、5、6這4個數,b的話同理,對應的是0、2、4、6這4個數。之後的併集就不用再說了吧。
結構體解釋:
typedef struct LNode{ //此行的LNode是一個結構標籤
ElemType data;
struct LNode *next;
}LNode,*LinkList; //此行的LNode是結構體struct LNode的一個別名
//*LinkList也是結構體struct LNode的一個別名
//換言之LinkList是結構體struct LNode類型的指針的別名
//也就是說 struct LNode *p;這條語句等同於LinkList p;使用:p->date
逗號運算符和逗號表達式
3+5,6+8上式稱為逗號表達式。逗號表達式的一般形式為
表達式1,表達式2
逗號表達式的求解過程是:先求解表達式1,再求解表達式2。整個逗號表達式的值是表達式2的值
switch的default問題。不同位置結果不同
#include <iostream>
using namespace std;
int main()
{
int a=1,b=2,c=3,d=4,y=10;
switch(y){
case 1:a++;break;
default:d=1;
case 2:b++;break;//b是可以跑進去的
case 4:c++;break;
}
cout << a<<b<<c<<d<< endl;
return 0;
}
結果:
1331
友元不是成員函數,只有成員函數才可以是虛擬的,因此友元不能是虛擬函數。但可以通過讓友元函數調用虛擬成員函數來解決友元的虛擬問題。
析構函數(destructor) 與構造函數相反,當對象結束其生命周期,如對象所在的函數已調用完畢時,系統自動執行析構函數。析構函數往往用來做「清理善後」 的工作(例如在建立對象時用new開闢了一片內存空間,delete會自動調用析構函數後釋放內存)。
析構函數應當是虛函數,將調用相應對象類型的析構函數,因此,如果指針指向的是子類對象,將調用子類的析構函數,然後自動調用基類的析構函數。