c++基礎

來源:互聯網
上載者:User

 1.建構函式初始化
Animal::Animal():aget(1),maxLevel(30)
{
}
2.除非友元,否則不允許使用者訪問類中的私人資料成員。
  friend void fun(Animal& a);
  void fun(Animal& a)
  {
   cout<<a.name<<endl;
  }
3.如果參數是指標,且僅作輸入用,則應在類型前加const,以防止該指標在函數體內被意外修改。
例如:
void StringCopy(char *strDestination,const char *strSource);
 如果輸入參數以值傳遞的方式傳遞對象,則宜改用“const &”方式來傳遞,這樣可以省去臨時對象的構造和析構過程,從而提高效率。

4.函數的傳回值是一個對象

如果函數的傳回值是一個對象,有些場合用“引用傳遞”替換“值傳遞”可以提高效率。而有些場合只能用“值傳遞”而不能用“引用傳遞”,否則會出錯。
例如:
class String
{…
 // 賦值函數
 String & operate=(const String &other); 
// 相加函數,如果沒有friend修飾則只許有一個右側參數
friend String   operate+( const String &s1, const String &s2);
private:
 char *m_data;
}

 String的賦值函數operate = 的實現如下:
String & String::operate=(const String &other)
{
 if (this == &other)
  return *this;
 delete m_data;
 m_data = new char[strlen(other.data)+1];
 strcpy(m_data, other.data);
 return *this; // 返回的是 *this的引用,無需拷貝過程
}

對於賦值函數,應當用“引用傳遞”的方式返回String對象。如果用“值傳遞”的方式,雖然功能仍然正確,但由於return語句要把 *this拷貝到儲存傳回值的外部儲存單元之中,增加了不必要的開銷,降低了賦值函數的效率。例如:
 String a,b,c;
 …
 a = b;   // 如果用“值傳遞”,將產生一次 *this 拷貝
 a = b = c;  // 如果用“值傳遞”,將產生兩次 *this 拷貝

 String的相加函數operate + 的實現如下:
String  operate+(const String &s1, const String &s2) 
{
 String temp;
 delete temp.data; // temp.data是僅含‘\0’的字串
  temp.data = new char[strlen(s1.data) + strlen(s2.data) +1];
  strcpy(temp.data, s1.data);
  strcat(temp.data, s2.data);
  return temp;
}

對於相加函數,應當用“值傳遞”的方式返回String對象。如果改用“引用傳遞”,那麼函數傳回值是一個指向局部對象temp的“引用”。由於temp在函數結束時被自動銷毀,將導致返回的“引用”無效。例如:
 c = a + b;
此時 a + b 並不返回期望值,c什麼也得不到,流下了隱患。

5.引用與指標的比較

 

引用是C++中的概念,初學者容易把引用和指標混淆一起。一下程式中,n是m的一個引用(reference),m是被引用物(referent)。
 int m;
 int &n = m;
n相當於m的別名(綽號),對n的任何操作就是對m的操作。例如有人名叫王小毛,他的綽號是“三毛”。說“三毛”怎麼怎麼的,其實就是對王小毛說三道四。所以n既不是m的拷貝,也不是指向m的指標,其實n就是m它自己。
引用的一些規則如下:
(1)引用被建立的同時必須被初始化(指標則可以在任何時候被初始化)。
(2)不能有NULL引用,引用必須與合法的儲存單元關聯(指標則可以是NULL)。
(3)一旦引用被初始化,就不能改變引用的關係(指標則可以隨時改變所指的對象)。
 以下樣本程式中,k被初始化為i的引用。語句k = j並不能將k修改成為j的引用,只是把k的值改變成為6。由於k是i的引用,所以i的值也變成了6。
 int i = 5;
 int j = 6;
 int &k = i;
 k = j; // k和i的值都變成了6;
 上面的程式看起來象在玩文字遊戲,沒有體現出引用的價值。引用的主要功能是傳遞函數的參數和傳回值。C++語言中,函數的參數和傳回值的傳遞方式有三種:值傳遞、指標傳遞和引用傳遞。
 以下是“值傳遞”的樣本程式。由於Func1函數體內的x是外部變數n的一份拷貝,改變x的值不會影響n, 所以n的值仍然是0。
 void Func1(int x)
{
 x = x + 10;
}

int n = 0;
 Func1(n);
 cout << “n = ” << n << endl; // n = 0
 
以下是“指標傳遞”的樣本程式。由於Func2函數體內的x是指向外部變數n的指標,改變該指標的內容將導致n的值改變,所以n的值成為10。
 void Func2(int *x)
{
 (* x) = (* x) + 10;
}

int n = 0;
 Func2(&n);
 cout << “n = ” << n << endl;  // n = 10

 以下是“引用傳遞”的樣本程式。由於Func3函數體內的x是外部變數n的引用,x和n是同一個東西,改變x等於改變n,所以n的值成為10。
 void Func3(int &x)
{
 x = x + 10;
}

int n = 0;
 Func3(n);
 cout << “n = ” << n << endl;  // n = 10

 對比上述三個樣本程式,會發現“引用傳遞”的性質象“指標傳遞”,而書寫方式象“值傳遞”。實際上“引用”可以做的任何事情“指標”也都能夠做,為什麼還要“引用”這東西?
答案是“用適當的工具做恰如其分的工作”。
 指標能夠毫無約束地操作記憶體中的如何東西,儘管指標功能強大,但是非常危險。就象一把刀,它可以用來砍樹、裁紙、修指甲、理髮等等,誰敢這樣用?
如果的確只需要借用一下某個對象的“別名”,那麼就用“引用”,而不要用“指標”,以免發生意外。比如說,某人需要一份證明,本來在檔案上蓋上公章的印子就行了,如果把取公章的鑰匙交給他,那麼他就獲得了不該有的權利。

 

6. && 左右兩邊均為true 時為true , || 左右兩邊一個為true 即為 true.
   false 在算術運算式中為0, true 為1.
7. 算術運算優先順序
   邏輯運算子號 NOT
   算術運算子(*,/,%)
   算術運算子(+,-)
   相對關聯運算子 (== ,!=) 
   邏輯運算子號 AND
   邏輯運算子號 OR
   賦值運算子
8. continue 終止迴圈的current iteration
   string word;
   const int min_size = 4;
   while (cin >>word)
   {
     if(word.size()<min_size)
      //結束此次迭代
     continue;
     //程式執行到此,則輸入長度都大於或等於 min_size 個字元
     process_text(word);
   }
9. const int seq_size = 18;
   #include<vector>
   vector<int>pell_seq(seq_size)  // pell_sql 定義為一個vector object,可儲存18個int元素,每個元素初值為0.
   for(int ix= 2;ix< seq_size; ++ix)
   pell_sql[ix] = pell_seq[ix-2] + 2*pell_seq[ix-1];
   // vector 初始化
    vector<int>elem_seq(sql_size);
    elem_sql[0] = 1;
    elem_sql[1] = 2;
   或:
     利用一個已初始化的array 作為 vector 的初值

   int elem_vals[seq_size] = {
   1,2,3
  };
    vector<int>elem_seq(elem_vals,elem_vals+seq_size);

 

9.初始化:
  int ival(1024)  直接初始化 更靈活且效率更高
  int ival = 1024 複製初始化
10.extern
  extern int i;聲明不是定義
  extern int i=65535 ;定義
 程式中變數可以聲明多次,但只能定義一次。

11:
  引用:
  引用必須用與該引用同類型的對象初始化.
   int ival = 1024;
   int &refVal = ival ; //ok:refVal refers to ival
   int &refVal2 ; // error:a reference must be initialized
   int &refVal3 = 10 ; // error: initalizer must be an object
  const 引用: 指向const對象的引用:
   const int ival = 1024 ;
   const int &refVal = ival ; //ok:both reference and object are const;
   int &ival = ival ;//error:non const reference to a const object;
   可以讀取但不能修改refVal;
  const 引用可以初始化為不同類型的對象或者初始化為右值。
    int i= 42;
    const int &r = 42 ; // legar for const references only
    cont  int &re = r+i;

   double dval = 3.14 ;
   const int &ri = dval;
   編譯器會轉成如下形式:
   int temp  = dval;
   const  int &ri = dval;
   
 //非const 引用只能綁定到與該引用同類型的對象。
   const 引用則可以綁定到不同但相關的類型的對象或綁定到右值。

12:  枚舉
 
 枚舉成員值可以是不唯一的:
  enum  Points{point2d = 2, point2w, point3d = 3, point3w};
  point2w預設初始化,為3.  point3w 為4.
 枚舉對象的初始化或賦值,只能通過其枚舉成員或同一枚舉類型的其他對象進行。
  Points pt3d = point3d; // ok:point3d is a points enumerator;
  Points  pt2w = 3 ; // error: pt2w initialized whit int
  pt2w =  polygon ; // error: polygon is  not a Points enumerator
  pt2w  = pt3d ;// ok: both are objects of points enum type
  把3賦給Points 對象是非法的,即使3與一個points枚舉成員相關聯。

13: 類類型
   用class 和struct 關鍵字定義類的唯一差別在於預設存取層級,預設情況下,
struct 的成員為public,而class的成員為private;

14: 標頭檔用於聲明而不是用於定義
    extern int ival = 10;  //  initializer, so it's a definition
    double fica_rate  ;    // no extern ,so it's a definition
    因為標頭檔包含在多個源檔案中,所以不應該含有變數或函數的定義。

15: 避免多重包含
  
#ifndef XXX_H
#define XXX_H
#endif

16: string

  string 對象的定義和初始化
  string s1;  //預設建構函式,s1為空白串
  string s2(s1);  //將s2 初始化為s1的一個副本。
  string s3("value"); //將s3初始化為一個字串字面值副本
  string s4(n,'c') ;  //將s4初始化為字元'c'的n個副本
  警告:  字串字面值與標準庫string 類型不是同一種類型.

  *和字串字面值的串連:
  當進行string 對象和字串字面值混合串連操作時,+操作符的左右運算元必須至少一個是string類型。  string s1 = "hello" ;
  string s2 =  "world";
  string s3 = s1+",";  //ok:adding a string and literal
  string s4 = "hello"+"," ; //error: no string operand
  string s5 = s1+ "," +" world"; //ok:each+ has string operand
  string s6 = "hello"+","+s2; //error:cant add string literals ;
  *從string 對象擷取字元
  string str("some string");
  for(string::size_type ix = 0 ;ix != str.size(); ++ix)
  cout << str[ix] << endl;
  * 下標操作可用作左值
   for(string::size_type ix = 0; ix != str.size(); ++ix)
   str[ix] = '*';
    *cctype 標頭檔中的字元處理
   isalnum(c)字母或數字
   isalpha(c) 字母
   iscntrl(c) 控制字元
   isdigit(c) 數字
   isgraph(c) 不是空格,但可以列印
   islower(c) 小寫字母
   isprint(c) 可列印的字元
   ispunct(c) 標點符號
   isspace(c) 空白字元
   isupper(c) 大寫字母
   isxdigit(c) 十六進值
   tolower(c) 大寫字母,則返回其小寫字母,否則直接返回c
   toupper(c) 小寫字母,則返回其大寫字母,否則直接返回c
// 給定對象中標點符號的個數
string s("hello word!!!");
string::size_type punct_cnt = 0;
for(string::size_type index=0; index != s.size();++index)
if(ispunct(s[index]))
  ++punct_cnt;
cout << punct_cnt;

17:  標準庫vector 類型 

   vector(容器)是同一種類型的對象的集合,每個對象都有一個對應的整數索引值。
   vector不是一種資料類型,而只是一個類模板,可以來定義和初始化vector對象。

  幾種初始化vector對象的方式
  vector<T>  v1;  vector保持類型為T的對象,預設建構函式v1為空白。
  vector<T>  v2(v1) ; v2 是v1的一個副本。
  vector<T>  v3(n,i); v3包含n個值為i的元素.
  vector<T>  v4(n) ;  v4含有值初始化的元素的n個副本。
  1.建立確定個數的元素。
 如果複製,兩個vector必須儲存同一種元素類型
  vector<int> ivec1 ; // ivec holds objects of type int
  vector<int> ivec2(ivec1);//ok:copy elements of ivec1 into ivec2
  vector<string> svec(ivec1); //error:svec holds strings, not  ints

   vector<int> ivec4(10,-1); // 10 elements ,each initialized to -1
   vector<string> svec(10,"hi!"); // strings, each initialized to "hi"
   2.值初始化
   vector<int> fvec(10);   // 10 elements ,each initialized to 0
   vector<string> svec(10);// 10 elements, each an empty string
  vector  對象的操作  
  1.vector 對象的size 
     vector<int>::size_type  //ok
     vector::size_type  // erro
   size_type:必須指出該類型是在那定義的.
  2. 向vector 添加元素
    string word; 
    vector<string> text;
    while( cin >> word)
     {
     text.push_back(word);
     }
  3. vector 的下標操作
    for(vector<int>::size_type  ix = 0;ix != ivec.size(); ++ix)
         ivec[ix] = 0;
  4. 下標操作不添加元素 
     vector<int> ivec;
     for( vector<int>::size_type ix = 0 ; ix != 10 ; ++ix)
       ivec[ix] = ix;
      下標操作只能擷取已存在的元素
    正確寫法:
        for( vector<int>::size_type ix = 0 ; ix != 10 ; ++ix)
         ivec.push_back(ix);

   警告:只能對確知已存在的元素進行下標操作
           vector<int> ivec;  //empty vector
           cout<< ivec[0]     //error: ivec has no elements !

           vector<int> ivec2(10);  //vector with 10 elements
           cout<< ivec[10] ;       //error: ivec has elements 0...9

18. 迭代器簡介

  1. 容器的iterator 類型  
    vector<int>::iterator iter;
  2. begin 和end  操作
   vector<int>::iterator iter = ivec.begin();
  3. 解引用運算
   迭代器類型可以使用解引用操作符(*操作符)來訪問迭代器所指向的元素。
    *iter = 0;
  4. 樣本
  下標操作法:
    for( vector<int>::size_type ix = 0 ; ix != ivec.size() ; ++ix)
     ivec[ix] = 0;
  迭代器:
    for(vector<int>::iterator iter = ivec.begin(); iter !=ivec.end();++iter)
   *iter = 0;  5. const_iterator
   5.唯讀容器內元素。
    for(vector<string>::const_iterator iter = text.begin(); iter != text.end(); ++iter)
   cout<< *iter <<endl;
   6. 不要把const_iterator 對象與const 的iterator 對象混淆起來,聲明一個const 迭代器時,必須初始化迭代器,一但初始化,就不能改變它的值。
    vector<int> nums(10) ;// nums is nonconst;
    const vector<int>::iterator cit = nums.begin();
    *cit = 1;  // ok: cit can change its underlying element
    ++cit;     // error: can't change the value of cit
   7. const_iterator 對象可以用於const vector 或非const vector.
     const vector<int> nines(10,9); // cannot change elements in nines
     // error: cit2 could change the element it refers to  and nines is const
     const vector<int>::iterator cit2 = nines.begin();

    //ok: it can't change an element value , so it can be used with a      const vector<int>
      vector<int>::const_iterator it = nines.begin();
     *it = 10 ; // error:*it is const ;
     ++it;      // ok: it isn't const so we can change its value
    註解: 
   //an iterator that cannot write elements
    vector<int>::const_iterator
  // an iterator whose value cannot change
   const vector<int>::iterator
   8. 迭代器的算術運算
     1. iter + n
        iter - n
       位置在所指元素之前或之後(+,-)n個元素的位置。
     2. iter1 - iter2  difference_type 的signed 類型的值.
        定位於 vector 的中間元素
       vector<int>::iterator mid = vi.begin()+ vi.size()/2
      任何改變vector長度的操作都會使已存在的迭代器失效,列如,在調用push_back 之後,就不能再信指向vector的迭代器的值了。
 

19.  標準庫  bitset 類型
     處理二進值位的有序集。
     #include<bitset>
     using std::bitset;
   1.定義和初始化
     bitset<32> bitvec ; // 32bits ,all zero
    bitset<n> b ; // b有n位,每位都為0
    bitset<n> b(u) ; //b是unsigned long 型u的一個副本
    bitset<n> b(s); //b是string對象s中含有的位串的副本
    bitset<n> b(s,pos,n) //b是s中從位置pos開始的n個位的副本
  2.用unsigned 值初始化bitset對象
   當用unsigned long 值作為bitset對象的初始值時,該值將轉化為二進值的位元模式。而bitset對象中的位集作為這種模式的副本.如果bitset長度大於unsigned long 值的二進位位,則其餘高階位將置為0,如果小於,則只用低階位,超過bitset的高階位將被丟棄。 
   十六進位0Xffff 表示為二進位就是十六個1和十六個0(每個0xf可表示為1111),可以用0xffff初始化bitset對象。
   //bitvec1 is smaller than  the initializer
   bitset<16> bitvec1(0xffff);  // bits 0...15 are set to 1
   //bitvec2 same size as initializer
   bitset<32> bitvec2(0xfffff); // bits 0...15 are set to ; 16...31 are 0
  // on  a 32-bit machine ,bits 0 to 31 initialized from 0xffff
   bitset<128> bitvec3(0xfffff);//bits 32 through 127 initialize to zero
   3.用string 對象初始化bitset對象
   從string讀入位集的順序從右向左。
   string strval("1100");
   bitset<32> bitvec4(strval); 
   bitvec4 的位元模式中第2和3的位置為1,其餘為0。如果string 對象的字元個數小於bitset類型長度,則高階位將置為0 .

  string str("111111000011110000");
  bitset<32> bitvec5(str,5,4);// 4 bits starting at str[5],1100
  bitset<32> bitvec6(str,str.size()-4);// use last 4 characters

  4. bitset  對象上的操作
    b.any() 是否存在置為1的二進位
    b.none() 不存在置為1的二進位位嗎?
    b.count()  置為1的二進位位的個數
    b.size()   二進位的個數
    b[pos]    訪問b中在pos處的二進位位
    b.test[pos]  b中在pos處的二進位位是否為1
    b.set()   所有二進位位都設定為1
    b.set(pos)  把b中在pos 處二進位置為1
    b.reset()   把b中所有二進位都置為0
    b.reset(pos)  把b中在pos 處的二進位位置為0
    b.flip()     二進位逐位取反
    b.flip(pos)    pos 處取反
    b.to_ulong()  用b中同樣的二進位返回一個unsingned long 值
    os << b  把b中的位集輸出到 os 流

    數組和指標

   

   

 

   
 
   
    
   

  

 

 

 
  

  
  
 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.