指針和 const 限定符
double dheight = 100.5;
const double dprice = 10.5;
const double *pd = &dprice; // pd 指向的 dprice 是const 的
pd = &dheight; // pd 可以指向非const 的對象
int ierr = 0;
int *const curErr = &ierr; // 指針 curErr, 是const的
const int iMsg = 10;
const int *const pmsg = &iMsg; // 指針 和 指向的對象,都是const的
原因是:const 限定符可以放在類型前,也可以放在類型後。
就是說, const string a;
也可以寫成: string const a;
typedef string * pstring;
string s("Hello");
const pstring ps = &s;
string *const ps2 = &s; // 與上式,等價
pstring const ps3 = &s; // 與上式,等價
此處,const 修飾的是 pstring 類型,也就是說,const 修飾的是指針。typedef,不是簡單的文本擴展!因此,const pstring ps = &s; 其實等價於: string *const ps = &s;
C風格字符串
字符串字面值 的類型,是字符常量的數組。
也就是,const char 類型的數組。
C++ 從C語言 繼承下來的一種通用結構就是 C風格字符串(C-style character string)
而,字符串面值,就是該類型的實例。
實際上,C風格字符串既不能歸結爲C語言的類型,也不能歸結爲C++語言的類型,
而是以空字符 null 結束的字符數組。
char ca1[] = {'C', '+', '+'};
char ca2[] = {'C', '+', '+', '\0'}; // C風格
char ca3[] = "C++"; // C風格,末尾自動加 null
const char *cp = "C++"; // C風格
char *cp1 = ca1; //
char *cp2 = ca2; // C風格
C++ 通過 (const) char * 類型的指針,來操作C風格字符串。
const char *cp = "some value";
while(*cp)
{
++cp;
}
如果 cp 指向的字符串數組沒有null 字符,則,無法達到預期效果。直到在內存中找到null 字符,循環纔會終止。
strlen(s) | 返回s 長度,不包括結束符 null |
---|---|
strcmp(s1, s2) | s1=s2,返回0; s1>s2,返回正數; s1<s2,返回負數 |
strcat(s1, s2) | 將s2 連接到 s1,然後返回 s1 |
strcpy(s1, s2) | 將s2 複製給 s1,然後返回 s1 |
strncat(s1, s2, n) | 將s2 的前n個字符連接到 s1 後面,並返回 s1 |
strncpy(s1, s2, n) | 將s2 的前n個字符複製給 s1, 並返回 s1 |
注意:C風格字符串的操作容易出錯。
通常使用標準庫類型 string 來代替此類操作
動態數組
動態數組,不必在編譯時知道其長度,可以是在運行時再確定數組長度。
每個程序,執行時都佔用一塊可用內存,用於存放動態分配的對象,
此內存稱爲:自由存儲區(Free Store)或者 堆(Heap)
C++ 使用 new 和
delete 來分配和釋放 自由存儲區。
string *sp = new string[10];
int *ip = new int[20];
size_t n = get_size();
int *ip3 = new int[n];
string *sp2 = new string[30]();
const int *ip2 = new const int[11]();
// char arr[0] 是錯誤的, 然而,動態分配時,長度可以是0,並返回非0 的指針,但該指針不能解引用
char *cp = new char[0];
delete [] ip3;
使用動態數組,通常是因爲,編譯時無法知道數組的準確長度。如:以下場景
const char *noerr = "success";
const char *err188 = "Error Code: 188";
const char *errorText;
if(errorFound)
errorText = err188;
else
errorText = noerr;
int dimension = strlen(errorText) + 1;
char *errMsg = new char[dimension];
strncpy(errMsg, errorText, dimension);
混合使用標準庫類 string 和 C風格字符串
c_str () :返回C風格字符串的表示方法
string str("Hello");
const char *cp = str.c_str(); // C 風格字符串自動轉換爲,指向字符數組首地址的指針
// char *cp = str.c_str(); 錯誤,因爲c_str() 返回的是 const char 類型的數組
// char *cp = str; 錯誤,無法使用 string 對象來初始化 字符指針
// str.c_str() 返回的數組未必永遠有效。因爲 str 有可能被修改。
// 因此,最好是複製 str.c_str() 返回的數組
string s("abcdefg");
// char *a; 錯誤
// char *a = "x";
// 錯誤,"x"的內存是在棧上分配的,棧上的內存無法修改
// 返回的其實是 const char *,而不是 char *, 因此strcpy 將會無法寫入,報錯
char *a = new char[s.length()+1];
strcpy(a, s.c_str());
使用數組初始化 vector
const size_t array_size = 5;
int int_arr[array_size] = {88, 32, 13, 34, 65};
// 實際複製了 int_arr[1], int_arr[2], int_arr[3], int_arr[4]
vector<int> ivec(int_arr + 1, int_arr + array_size);
多維數組,即:數組的數組
int arr_first[2][3] = { {1, 2, 3}, {4, 5, 6} };
// 與上式等價
int arr_second[2][3] = {1, 2, 3, 4, 5, 6};
// 等價於:{ {1, 0, 0}, {2, 0, 0} }
int arr_third[2][3] = { {1}, {2} };
// 等價於:{ {1, 2, 0}, {0, 0, 0} }
int arr_fourth[2][3] = { 1, 2 };
// ip 是數組,長度爲3,數組元素是,指向int 的指針
int *ip[3];
// ip_second 是指針,指向一個長度爲3 的int 數組
int (*ip_second)[3];
typedef int int_array [3];
for(int_array *p_arr = arr_first; p_arr!=arr_first+2; ++p_arr)
for(int *p_int = *p_arr; p_int!=*p_arr+3; ++p_int)
*p_int = 100;
int c = arr_first[0][1];
..