1. 程式人生 > >從C到C++的過渡(2)

從C到C++的過渡(2)

七、C++的動態記憶體分配

malloc/calloc/realloc/free 1、new/delete:對單個變數進行記憶體分配/釋放。 2、new[]/delete[]:對陣列進行記憶體分配/釋放。

#include <iostream>
using namespace std;

int main(){
	//int* pi = (int*)malloc(sizeof(int));
	//free(pi);
	int* pi = new int;
	*pi = 8;
	cout << *pi << endl;
	delete pi;
	pi = NULL;

	pi = new int[10];
	for (int i = 0;i < 10;++i)
		pi[i] = i;
	for (int i = 0;i < 10;++i)
		cout << pi[i] << ' ';
	cout << endl;
	delete[] pi;
	pi = NULL;

	pi = new int(1234);
	cout << *pi << endl;
	delete pi;
	pi = NULL;

	char buf[4] = {0x12,0x34,0x56,0x78};
	pi = new(buf) int;//定位new
	cout << hex << *pi << endl;
	cout << (void*)pi << ' ' << (void*)buf << endl;
	//delete pi;//此處不能delete,new的是棧的記憶體,不能delete

	int (*p)[4] = new int[3][4];
	delete[] p;
	int (*q)[4][5] = new int[3][4][5];
	delete[] q;
	return 0;
}

八、C++的字串

可以直接宣告變數並進行賦值等字串操作。 C沒有字串專門機制,用char型陣列在末尾加’\0’的辦法來處理字串,C++也相容這種“C字串”機制。在C++中則把字串封裝成了一種資料型別string,來專門處理字串,它提供了非常豐富的字串處理功能。而且,string還提供了與“C字串”相互轉換的方法,使用非常靈活。

九、引用

1、引用即別名。 int a = 20; int& b = a; b = 10; cout << a << endl;//10 2、引用必須初始化。 int a; int* p; a = 20; p = &a; int& b;//ERROR int& b = a;//OK 3、引用一旦初始化就不能再引用其他變數。 int a = 20, c = 30; int& b = a; b = c;//ERROR 4、引用的應用場景 (1)引用型引數 a、修改實參 b、避免拷貝,通過加const可以防止在函式中意外的修改實參的值,同時還可以接受擁有常屬性的實參。 (2)引用型返回值 int b = 10; int a = func(b); func(b) = a; 從一個函式中返回引用往往是為了將該函式的返回值作為左值使用。但是,一定要保證函式所返回的引用的目標在該函式返回以後依然有定義,否則將導致不確定的後果。 不要返回區域性變數的引用,可以返回全域性、靜態、成員變數的引用,也可以返回引用型形參變數本身。 5、引用和指標 (1)引用的本質就是指標,很多場合下引用和指標可以互換。 (2)在C++層面上引用和指標存在以下不同: A、指標是實體變數,但是引用不是實體變數。 int& a = b; sizeof(a);//4 double& d = f; sizeof(d);//8 B、指標可以不初始化,但是引用必須初始化。 C、指標的目標可以修改,但是引用的目標不能修改。 D、可以定義指標的指標,但是不能定義引用的指標。 int a; int* p = &a; int** pp = &p;//OK int& r = a; int&* pr = &r;//ERROR E、可以定義指標的引用,但是不能定義引用的引用。 int a; int* p = &a; int*& q = p;//OK int& r = a; int&& s = r;//ERROR F、可以定義指標的陣列,但是不能定義引用的陣列。 int a,b,c; int* parr[] = {&a,&b,&c};//OK int& rarr[] = {a,b,c};//ERROR 可以定義陣列的引用。 int arr[] = {1,2,3}; int (&arr_ref)[3] = arr;//OK

十、顯式型別轉換運算子

C:目標型別變數 = (目標型別)源型別變數; 1、靜態型別轉換 static_cast<目標型別> (源型別變數) 如果在目標型別和源型別之間某一個方向上可以做隱式型別轉換,那麼在兩個方向上都可以做靜態型別轉換。反之如果在兩個方向上都不能做隱式型別轉換,那麼在任意一個方向上也不能做靜態型別轉換。 int* p1 = …; void* p2 = p1; p1 = static_cast<int*> (p2); 如果存在從源型別到目標型別的自定義轉換規則,那麼也可以使用靜態型別轉換。 2、動態型別轉換 dynamic_cast<目標型別> (源型別變數) 用在具有多型性的父子類指標或引用之間。 3、常型別轉換 const_cast<目標型別> (源型別變數) 給一個擁有const屬性的指標或引用去常 const int a = 100; const int* p1 = &a; p1 = 200;//ERROR int

p2 = const_cast<int*> (p1); *p2 = 200;//OK 4、重解釋型別轉換 reinterpret_cast<目標型別> (源型別變數); 在不同型別的指標或引用之間做型別轉換,以及在指標和整數之間做型別轉換。 5、目標型別變數 = 目標型別(源型別變數); int a = int(3.14);

十一、C++之父的建議

1、少用巨集,多用const、enum和inline #define PAI 3.14159 const double PAI = 3.14159;

#define ERROR_FILE -1 #define ERROR_MEM -2 enm{ ERROR_FILE = -1; ERROR_MME = -2; };

#define max(a,b) ((a) > (b) ? (a) : (b)) inline int double max(double a,double b){ return a > b ? a : b; } 2、變數隨用隨宣告同時初始化 3、少用malloc/free,多用new/delete。 4、少用C風格的強制型別轉換,多用型別轉換運算子。 5、少用C風格的字串,多用string。 6、樹立面向物件的程式設計思想。