C++Primer筆記拾零(1)
-----------------------
2本學習C++的書
1.C++程序設計語言<Bjarne Stroustrup>
2.C++Primer中文版 第四版<Stanley B.Lippman>
示例下載
http://www.awprofessional.com/cpp_primer
========================
第2章 變量和基本類型
========================
---------------------------
基本類型表
bool 布爾型
char 字符型
wchar_t 寬字符型
short 短整型
int 整型
long 長整型
float 單精度浮點型
double 雙精度浮點型
long double 擴展精度浮點型
一般來說使用的類型為bool,char,int,double.
-----------------------------------
C++語言定義的常用轉義字符表
/n 換行符
/v 縱向制表符
/t 水平制表符
/b 退格符
/r 回車符
/f 進紙符
/a 報警符
// 反斜線
/? 問號
/' 單引號
/" 雙引號
8進制形式的通用轉義字符示例:
/7 響鈐符
/12 換行符
/40 空格符
/0 空字符
/062 '2'
/115 'M'
------------------------
變量命名規則
標識符不能包含兩個連續的下划線,
不能以下划線開頭后面緊跟一個大寫字母.
在函數外定義的標識符不能以下划線開頭.
命名習慣最重要的是保持一致.
-------------------------
const的注意事項
1.在全局變量中的注意點
在頭文件中可以定義const全局變量,必須要用常量表達式初始化.
在源文件中定義的const變量為當前文件局部變量,如果用extern聲明,則是全局變量.
對于非const全局變量,只要在外部文件里做了聲明,就可以訪問.
如:
//file_1.cc
int counter;//definition
//file_2.cc
extern int counter;//uses counter from file_1
++counter;
但是對于const全局變量,則只存在于定義它的那個文件中,不能被其它文件訪問.如果要在其
它文件里訪問,則必須要在const變里定義處指定為extern.
如:
//file_1.cc
extern const int bufsize=fcn();//defines and initializes
//file_2.cc
extern const int bufsize;//users bufsize from file_1
for(int index=0;index!=bufsize;++index)
//...
2.在引用中的注意點
對Const類型的引用,可以綁定到不同但相關的類型上,必須也要是const類型.
對非const類型的引用,類型必須要相同
例1:
const int dval=45;
const int &ri=dval;//const引用,合法
int &r2=dval;//非const引用,錯誤
例2:
double dval=3.14;
const int &ri=dval;//合法,可以是不同但相關的類型
double &r2=dval;//合法,修改r2后,不會修改dval,r2与dval是不同的啊,所以引用也不一定
是別名.
總之,只要記住.
(1).如果是對常量的引用,必須要是const引用.
(2).不管是不是引用,只要名字不同,那就是不同的變量(不用管什么別名).
(3).const引用可以綁定很多种類型的對象,非const引用只能綁定相同類型的對象.
-----------------------------
枚舉注意點
枚舉成員值可以是不唯一的.
如:
enum Points { point2d=d,point2w,point3d=3,point3w);
----------------------------
struct
用class和struct定義類的唯一區別在于默認訪問級別:默認情況下,struct的成員為public,
而class的成員為private.
======================
第3章 標准庫類型
======================
------------------------------
頭文件
在頭文件中不要用using聲明,而是要用完全限定的標准庫名字.理由是頭文件的內容會被預
處理器复制到程序中.
-------------------------------
string的長度
int main()
{
string st("The expense of spirit/n");
cout<<"The size of "<<st<<"is "<<st.size()<<endl;
return 0;
}
//st.size返回的類型是string::size_type類型,它是unsigned類型(usigned int 或
unsigned long).所以不要把size返回值賦給一個int變量.
使用size_type類型時,必須指出該類型是在哪里定義的.vector類型總是包括vector的元素類型.
vector<int>::size_type //ok
vector::size_type //error
------------------------------
vector操作
v.empty() 如果v為空,則返回true,否則返回false;
v.size() 返回v中元素的個數;
v.push_back(t) 在v的末尾增加一個值為t的元素;
v[n] 返回v中位置為n的元素;
v1=v2 把v1的元素替換為v2中元素的副本.
v1==v2 如果v1与v2相等,則返回true;
!=,<,<=,>,>== 保持這些操作符慣有的含義
---------------------------------
vector使用
下標操作只能用于已存在的元素
vector<int> ivec; //empty vector
for (vector<int>::size_type ix=0;ix!=10;++ix)
ivec[ix]=ix; //error:ivec has no elements
const_iterator對象与const的iterator對象的區別:
1.使用const_iterator類型時,可以對迭代器進行自增以及使用解引用操作符來讀取值,但不
能對該元素值賦值.
for(verctor<string>::const_iterator iter=text.begin();iter!=text.end();++ter)
*iter=" "; //error:*iter is const
2.聲明一個const迭代器時必須初始化.一量初始化,就不能改變它的值,只能用它來改寫其指
向的元素,但不能使它指向任何其它元素.
verctor<int> nums(10); //nums is nonconst
const vector<int>::iterator cit=nums.begin();
*cit=1; //ok:cit can chagne its underlying element
++cit; //error:can't change the value of cit
vector<int>::const_iterator it=nine.begin();
*it=10; //error:*it is const
++it; //ok: it isn't const so we can change its value
3.const_iterator對象可以用于const vector或非const vector,這樣就有四种組合
vector<int>::iterator
const vector<int>::iterator
vector<int>::const_iterator
const vector<int>::const_iterator//本身不能變,元素的值也不能變.用它還不如就只用
一個常量.
---------------------------
bitset
bitset的左邊是低階位,右邊是高階位.
用string初始化bitset時,string對象的最右邊字符用來初始化bitset對象的低階位.
---------------------------
bitset操作
b.any() b中是否存在置為1的二進制位?
b.none() b中不存在置為1的二進制位嗎?
b.count() b中位置為1的二進制位的個數
b.size() b中二進制位的個數
b[pos] 訪問b中在pos處的二進制位
b.test[pos] b中在pos處的進進制位是否為1
b.set() 把b中所有二進制位都置為1
b.set(pos) 把b中在pos處的二進制位置為1
b.reset() 把b中所有二進制位都置為0
b.reset(pos) 把b中在pos處的二進制位置為0
b.flip() 把b中所有二進制位取反
b.flip(pos) 把b中在pos處的二進制位取反
b.to_ulong() 用b中同樣的二進制位返回一個unsigned long值
os<<b 把b中的位集輸出到os流
===========================
第4章 數組和指針
===========================
---------------------------
數組一般不用了.它的功能用vector取代.
--------------------------
指針保存的是一個對象的地址,指針如果是0值,則它不指向任何對象.未初始化的指針是無效
的.
指針不能用變量賦值.但可以用數值0或在編譯時可獲得0值的const量賦給指針.
int ival;
int zero=0;
const int c_ival=0;
int *pi=ival; //error
pi=zero //error
pi=c_ival; //ok
pi=0; //ok
------------------------------
指針与引用的區別
1.引用總是指向某個對象,定義時必須要初始化.
2.賦值行為不同,引用賦值修改的是該引用所關聯的對象的值,而并不是使引用与另一個對象
關聯,引用一經初始化,就始終指向同一個特定對象.
-------------------------------
string s("hello world");
string& ri=s; //此為引用的定義,右邊為值
&ri 地址 //解引用
ri 值
string* sp=&s//此為指針的定義,右邊為地址
*sp 值 //這就叫解指針吧
sp 地址
string** spi=sp //此為指針的指針的定義,右邊為指針
**spi 值
*spi 地址
-------------------------------
將指針初始化為一個數組時,指針將指向數組的第一個元素.
const size_t arr_size=5;
int arr[arr_size]={1,2,3,4,5};
int *p=arr; //ok:p points to arr[0]
int *p2=p+arr_size; //ok:p2 指向數組結尾字符
------------------------------
指向const對象的指針,可以理解為"自以為指向const的指針".
1.指向const對象的指針也必須具有const特性.
如:const double *cptr;//這里const修飾double,而不是cptr本身,所以可以不初始化.
2.把一個const對象的地址賦給一個非const對象的指針也會出錯.
const double pi=3.14;
double *ptr=π //error
const double *cptr=π //ok
3.不能用void*指針保存const對象的地址,而必須要用const void*類型的指針.
const int universe=42;
const void *cpv=&universe; //ok
void *pv=&universe; //error
4.允許把非const對象的地址賦給指向const對象的指針,但是這樣就不能通過指針修改對象
的值了.
double pi=3.14;
const double *cptr=π
cptr=π //ok,but can't change dval through cptr
*pi=6.28;//error
------------------------------
const指針
const指針的值不能修改.
int errNumb=0;
int *const curErr=&errNumb;//指針本身是常量
curErr=cruErr; //error
-----------------------------
指向const對象的const指針,這好像很少用到.
const double pi=3.14159;
const double *const pi_ptr=π
--------------------------------
指針和typedef
typedef string *pstring;
const pstring cstr;//const修飾的是pstring的類型,
//cstr的真正類型為string *const cstr;
//常見錯誤理解:const string *cstr;
string s;
typedef string *pstring;
//以下三种形式等价,都是指向string對象的const指針
const pstring cstr1=&s;
pstring const cstr2=&s;
string *const cstr3=&s;
----------------------------------
動態數組
動態數組在堆中分配空間,在C中使用函數malloc和free,在C++中使用new和delete.
動態分配數組時,如果數組元素具有類類型,將使用該類的默認构造函數實現初始化;如果數
組元素是內置類型,則無初始化.
int *pia=new int[10]; //具有10個元素的數組,未初始化
string *psa=new string[10]; //用构造函數初始化
int *pia2=new int[10](); //用0初始化
定義數組時本來是不可以定義長度為0,但是動態數組的長度卻可以為0.
動態數組的釋放
delete [] pia;//一定要加[],如果遺漏編繹器無法發現.
使用string類型,它會自動調用delete釋放內存.
--------------------------
const對象的動態數組
因為const變量在定義時必須要初始化,而動態數組只能用默認值或构造函數初始化.
const int *pci_bad=new const int[100]; //error
const int *pci_ok=new const int[100]();//ok
const string *pcs=new const string[100];//ok
用const修飾的動態數組其實沒什么用.
--------------------------
指針与多維數組
int ia[3][4]; //array of size 3,each element is an array of ints of size 4
int (*ip)[4]=ia; //ip points to an array of 4 ints
ip=&ia[2]; //ia[2] is an array of 4 ints
用typedef簡化指向多維數組的指針
typedef int int_array[4];
int_array *ip=ia;
for(int_array *p=ia;p!=ia+3;++p)
for(int *q=*p;q!=*p+4;++q)
cout<<*q<<endl;