Chapter 3: 標準庫類型linux
Chapter 7 函數express
using
聲明,而不用 std::
,訪問標準庫中名字的方法,從新編寫第 2.3 節的程序,計算一給定數的給定次冪的結果。#include <iostream> using std::cin; using std::cout; using std::endl; int main() { int base,exponent; long result=1; cout<<"Enter base and exponent:"<<endl; cin>>base>>exponent; if(exponent<0) { cout<<"Exponent can't be smaller than 0"<<endl; return -1; } else { for(int cnt=1;cnt<=exponent;++cnt) { result*=base; } } cout<<base<<" raised to the power of "<<exponent<<":"<<result<<endl; //cout << "Hello world!" << endl; return 0; }
//讀入一行 #include<iostream> using namespace std; int main() { string word; while(getline(cin,word)) { cout<<word<<endl; } return 0; } //讀入單詞 #include<iostream> using namespace std; int main() { string word; while(cin>>word) { cout<<word<<endl; } return 0; }
#include<iostream> using namespace std; int main() { string result_str,str; cin>>result_str; while(cin>>str) result_str=result_str+" "+str; cout<<result_str<<endl; return 0; }
#include<iostream> using namespace std; int main() { bool has_punct=false; string s,result_str; cout<<"Enter a String:"<<endl; getline(cin,s); for(string::size_type index=0;index!=s.size();++index) { if(ispunct(s[index])) { has_punct=true; } else { result_str+=s[index]; } } if(has_punct) cout<<"Result:"<<result_str<<endl; else { cout<<"No punctuation character in the string"<<endl; return -1; } return 0; }
#include<iostream> #include<vector> using namespace std; int main() { vector<int> ivec; vector<int> sum; int ival; cout << "Enter numbers(Ctrl+Z to end):" << endl; while(cin>>ival) ivec.push_back(ival); if(ivec.size()==0) { cout<<"No elements"<<endl; } for (vector<int>::size_type index=0;index<ivec.size()-1;index=index+2) { if(ivec.size()%2!=0) { if(index<ivec.size()-1) { sum.push_back(ivec[index]+ivec[index+1]); //sum.push_back(ivec[index]+ivec[ivec.size()-2-index]); } } else { sum.push_back(ivec[index]+ivec[index+1]); // sum.push_back(ivec[index]+ivec[ivec.size()-1-index]); } } if(ivec.size()%2!=0) { cout<<"Last element is not computed:"<<endl; } cout << "Sum of each pair of adjacent elements in the vector:"<<endl; for (vector<int>::size_type index=0;index!=sum.size();++index) { cout<<sum[index]<<" "; } cout<<endl; return 0; }
#include<iostream> #include<vector> #include<string> #include<cctype> using namespace std; int main() { cout<<"Enter some words:"<<endl; vector <string> istr; string iword; while(cin>>iword) istr.push_back(iword); cout<<"After transformation:"<<endl; for (vector<string>::size_type index=0;index<istr.size();++index) { for (string::size_type index2 = 0; index2 != istr[index].size(); ++index2) { istr[index][index2]=toupper(istr[index][index2]); } cout<<istr[index]<<"\t"; if((index%8==0)&&(index>0)) { cout<<endl; } } return 0; }
#include<iostream> #include<vector> using namespace std; int main() { vector<int> ivec; vector<int> sum; int ival; cout << "Enter numbers(Ctrl+Z to end):" << endl; while(cin>>ival) ivec.push_back(ival); if(ivec.size()==0) { cout<<"No elements"<<endl; } for(vector<int>::iterator it=ivec.begin();it!=ivec.end()-1;it=it+2) { if(ivec.size()%2!=0) { if(it<ivec.end()-2) { sum.push_back((*it)+*(it+1)); } } else { sum.push_back((*it)+*(it+1)); } } if(ivec.size()%2!=0) { cout<<"Last element is not computed:"<<endl; } cout << "Sum of each pair of adjacent elements in the vector:"<<endl; for(vector<int>::iterator it2=sum.begin();it2!=sum.end();++it2) { cout<<*it2<<" "; } cout<<endl; return 0; }
#include<iostream> #include<vector> #include<string> #include<cctype> using namespace std; int main() { cout<<"Enter some words:"<<endl; vector <string> istr; string iword; while(cin>>iword) istr.push_back(iword); cout<<"After transformation:"<<endl; for(vector<string>::iterator it=istr.begin();it!=istr.end();++it) { for(string::iterator it2=(*it).begin();it2!=(*it).end();++it2) { *it2=toupper(*it2); } cout<<*it<<"\t"; if((it-istr.begin())%8==0&&it>istr.begin()) { cout<<endl; } } return 0; }
#include<iostream> #include<vector> using namespace std; int main() { vector<int> ivec(10,42); for (vector<int>::iterator it=ivec.begin();it!=ivec.end();++it) { *it=*it*2; } for (vector<int>::iterator it=ivec.begin();it!=ivec.end();++it) { cout<<*it<<"\t"; } return 0; }
#include<iostream> #include<string> #include<cstring> using namespace std; int main() { const int str_size=80; char *str1,*str2; str1=new char[str_size]; str2=new char[str_size]; if(str1==NULL||str2==NULL) { cout<<"No enough Memory"<<endl; return -1; } cout<<"Enter two strings:"<<endl; cin>>str1>>str2; int result; result=strcmp(str1,str2); if(result>0) cout << "\"" << str1 << "\"" << " is bigger than "<< "\"" << str2 << "\"" << endl; else if (result < 0) cout << "\"" << str2 << "\"" << " is bigger than "<< "\"" << str1 << "\"" << endl; else cout << "They are equal" << endl; delete[] str1; delete[] str2; return 0; }
#include<iostream> #include<string> #include<cstring> using namespace std; int main() { const char *pc = "a very long literal string"; const size_t len = strlen(pc +1); // space to for (size_t ix = 0; ix != 1000000; ++ix) { char *pc2 = new char[len + 1]; // allocate the space strcpy(pc2, pc); // do the copy if (strcmp(pc2, pc)) // use the new string ; // do nothing delete [] pc2; // free the memory } string str("a very long literal string"); // performance test on string allocation and copy for (int ix = 0; ix != 1000000; ++ix) { string str2 = str; // do the copy, automatically allocated if (str != str2) // use the new string ; // do nothing } return 0; }
#include <cstring> int main() { const char *cp1 = "Mary and Linda "; const char *cp2 = "are firends."; size_t len = strlen(cp1) + strlen(cp2); char *result_str = new char[len+1]; strcpy(result_str, cp1); strcat(result_str, cp2); delete [] result_str; return 0; }
#include <string> using namespace std; int main() { const string str1("Mary and Linda "); const string str2("are firends."); string result_str; result_str = str1; result_str += str2; return 0; }
#include <iostream> #include <string> #include <cstring> using namespace std; int main() { string in_str;// 用於讀入字符串的string 對象 const size_t str_size = 10; char result_str[str_size+1];// 讀入字符串 cout << "Enter a string(<=" << str_size<< " characters):" << endl; cin >> in_str;// 計算需複製的字符的數目 size_t len = strlen(in_str.c_str()); if (len > str_size) { len = str_size; cout << "String is longer than " << str_size<< " characters and is stored only " << str_size << " characters!" << endl; } // 複製len 個字符至字符數組result_str strncpy(result_str, in_str.c_str(), len); // 在末尾加上一個空字符(null 字符) result_str[len+1] = '\0'; return 0; }
//int數組賦值給vector<int> #include <iostream> #include <vector> using namespace std; int main() { const size_t arr_size = 8; int int_arr[arr_size];// 輸入數組元素 cout << "Enter " << arr_size << " numbers:" << endl; for (size_t ix = 0; ix != arr_size; ++ix) cin >> int_arr[ix];// 用int 型數組初始化vector 對象 vector<int> ivec(int_arr, int_arr + arr_size); return 0; } //vector<int>賦值給int數組 #include <iostream> #include <vector> using namespace std; int main() { vector<int> ivec; int ival;// 輸入vector 元素 cout << "Enter numbers: (Ctrl+Z to end)" << endl; while (cin >> ival) ivec.push_back(ival);// 建立數組 int *parr = new int[ivec.size()];// 複製元素 size_t ix = 0; for (vector<int>::iterator iter = ivec.begin();iter != ivec.end(); ++iter, ++ix) parr[ix] = *iter;// 釋放數組 delete [] parr; return 0; }
#include <iostream> #include <string> #include <cstring> #include <vector> using namespace std; int main() { vector<string> ivec; string str; cout<<"Enter strings:"<<endl; while(cin>>str) ivec.push_back(str); char **s2ptr=new char*[ivec.size()]; size_t ix=0; for (vector<string>::iterator it=ivec.begin();it!=ivec.end();++it,++ix) { char *strptr=new char[(*it).size()+1]; strcpy(strptr,(*it).c_str()); s2ptr[ix]=strptr; // *s2ptr=strptr; // s2ptr=s2ptr+1; } cout << "Content of character arrays:" << endl; for (ix =0; ix != ivec.size(); ++ix) cout << *(s2ptr+ix) << endl; // 釋放各個字符數組 for (ix =0; ix != ivec.size(); ++ix) delete [] s2ptr[ix]; // 釋放字符指針數組 delete [] s2ptr; return 0; }
預測下列程序的輸出是,並解釋你的理由。而後運行該程序,輸出的結果和你的預測的同樣嗎?若是不同,爲何?
int x[10]; int *p = x; cout << sizeof(x)/sizeof(*x) << endl; cout << sizeof(p)/sizeof(*p) << endl;
Answer:在表達式sizeof(x)
中,x 是數組名,該表達式的結果爲數組x 所佔據的存儲空間的字節數,爲10 個int
型元素所佔據的字節數。表達式sizeof(*x)
的結果是指針常量x 所指向的對象(數組中第一個int 型元素)所佔據的存儲空間的字節數。
表達式sizeof(p)
的結果是指針變量p 所佔據的存儲空間的字節數。
表達式sizeof(*p)
的結果是指針變量p 所指向的對象(一個int 型數據)所佔據的存儲空間的字節數。各類數據類型在不一樣的系統中所佔據的字節數不必定相同所以在不一樣的系統中運行上述程序段獲得的結果不必定相同。在Microsoft Visual C++ .NET 2003系統中,一個int 型數據佔據4 個字節,一個指針型數據也佔據4 個字節,所以運行上述程序獲得的輸出結果爲:101
(a) vector<string> svec(10); (b) vector<string> *pvec1 = new vector<string>(10); (c) vector<string> **pvec2 = new vector<string>[10]; (d) vector<string> *pv1 = &svec; (e) vector<string> *pv2 = pvec1; (f) delete svec; (g) delete pvec1; (h) delete [] pvec2; (i) delete pv1; (j) delete pv2;
#include<string> #include<iostream> #include<vector> using namespace std; int main(void) { vector<string> svec(10);// vector<string> *pvec1 = new vector<string>(10); //建立一個字符串數組(vector<string>),用10初始化,這個數組含有10個string vector<string> *pvec2 = new vector<string>[10]; //建立十個字符串數組(vector<string>),數組初始大小爲默認(0) vector<string> *pv1 = &svec; vector<string> *pv2 = pvec1; cout<<sizeof(svec)<<endl; cout<<sizeof(*pvec1)<<endl; cout<<sizeof(*pvec2)<<endl; cout<<sizeof(pv1)<<endl; cout<<sizeof(pv2)<<endl; delete pvec1;//只有一個對象 用delete delete [] pvec2;//有十個對象 用delete []; delete pv1; delete pv2; }
【解答】 形參是在函數定義的形參表中進行定義,是一個變量,其做用域爲整個函數。而實參出如今函數調用中,是一個表達式。進行函數調用時,用傳遞給函數的實參對形參進行初始化。
#include<iostream> using namespace std; int sum1(const int *begin,const int *end ) { int sum=0; while(begin!=end) sum+=*begin++; return sum; } int sum2(int a[],size_t size) { int sum=0; for(size_t ix=0;ix!=size;ix++) { sum+=a[ix]; } return sum; } int sum3(int *begin,size_t size) { int sum=0; int*p=begin; while(p!=begin+size) { sum+=*p++; } return sum; } int sum4(const int (&a)[4]) { int sum=0; for(size_t ix=0;ix!=4;ix++) { sum+=a[ix]; } return sum; } int main() { int ia[]={1,2,3,4}; int *p=ia;//等價於int *p=&ia[0] cout<<sizeof(ia)<<endl;//sizeof() cout<<(unsigned int)(&ia+1)-(unsigned int)(&ia)<<endl;// cout<<sizeof(p)<<endl;//sizeof(int *) //當數組做爲函數的參數進行傳遞時,該數組自動退化爲同類型的指針。下面是個例子 //不論數組a 的容量是多少,sizeof(a)始終等於sizeof(char *) cout<<"sum1 is :"<<sum1(ia,ia+4)<<endl;//數組頭和數組尾 cout<<"sum2 is :"<<sum2(ia,4)<<endl;//數組形參和數組長度 cout<<"sum3 is :"<<sum3(ia,4)<<endl;//指針形參和數組長度 cout<<"sum3 is :"<<sum4(ia)<<endl;//數組引用形參 return 0; } //例子: #include <iostream> using namespace std; void foe(int[]); int main() { int myarray[] = {0,1,2,3,4,5}; cout << sizeof(myarray) / sizeof(*myarray) << endl; foe(myarray); return 0; } void foe(int a[]){ cout << sizeof(a) / sizeof(*a) << endl; }
(1) 形參的做用域爲整個函數體,而普通(非靜態)局部變量和靜態局部變量的做用域 爲:從定義處到包含該變量定義的塊的結束處。
(2) 形參由調用函數時所傳遞的實參初始化;而普通(非靜態)局部變量和靜態局部變量 一般用初始化式進行初始化,且均在程序執行流程第一次通過該對象的定義語句時進行初始化。靜態局部變量的初始化在整個程序執行過程當中進行一次。
(3) 形參和普通(非靜態)局部變量均屬自動變量,在每次調用函數時建立,並在函數 結束時撤銷;而靜態局部變量的生命期卻跨越了函數的屢次調用,它在建立後直到程序結束時才撤銷。
#include <iostream> using namespace std; void func(); int n=1; //全局變量 int main() { static int a; // 靜態局部變量 int b= -10; // 局部變量 cout <<"a:" <<a<<" b:" <<b<<" n:" <<n <<endl; b+=4; func(); cout <<"a:" <<a<<" b:" <<b<<" n:" <<n <<endl; n+=10; func(); return 0; } void func() { static int a=2; // 靜態局部變量 int b=5; // 局部變量 a+=2; n+=12; b+=5; cout <<"a:" <<a<<" b:" <<b<<" n:" <<n <<endl; }
sales_item.h
#ifndef SALESITEM_H #define SALESITEM_H #include <iostream> #include <string> class sales_item { public: std::istream& input(std::istream &in); std::ostream& output(std::ostream &out) const; double avg_price()const; bool same_isbn(const sales_item &rhs) const { return isbn==rhs.isbn; } sales_item():units_sold(0),revenue(0.0){} private: std::string isbn; unsigned int units_sold; double revenue; }; #endif
sales_item.cpp
#include "main.h" #include <iostream> std::istream& sales_item::input(std::istream& in) { double price; in>>isbn>>units_sold>>price; if(in) { revenue=units_sold*price; } else { units_sold=0; revenue=0; } return in; } std::ostream& sales_item::output(std::ostream& out) const { out<<"isbn:"<<isbn<<"\t"<<"units_sold:"<<units_sold<<"\t" <<"revenue:"<<revenue<<"\t"<<"ave_price:"<<avg_price(); return out; } double sales_item::avg_price() const { if(units_sold) return revenue/units_sold; else return 0; } using namespace std; int main() { sales_item item; cout<<"the transaction readed is:"<<endl; while(item.input(cin)) { item.output(cout); cout<<endl; } return 0; }
ostream print(ostream os);
答:標準庫類型不容許作複製或賦值操做。形參或返回類型不能爲流類型,因此上句代碼錯誤,由於它把流類型的對象當作了形參。應改成傳遞指向該對象的指針或引用:
ostream &print( ostream &os );
#include <iostream> #include <stdexcept> using namespace std; istream& f(istream& in) { int ival; while(in>>ival,!in.eof()) { if(in.bad()) throw runtime_error("IO stream corrupted"); if(in.fail()) { cerr<<"bad data,try again:"; in.clear(); in.setstate(istream::eofbit); continue; } cout<<ival<<endl; } in.clear(); return in; } int main() { cout<<"Input some numbers(ctrl+z end):\n"; f(cin); return 0; }
#include <iostream> #include <fstream> #include <stdexcept> using namespace std; istream& f(istream& in) { string ival; while(in>>ival,!in.eof()) { if(in.bad()) throw runtime_error("IO stream corrupted"); if(in.fail()) { cerr<<"bad data,try again:"; in.clear(); in.setstate(istream::eofbit); continue; } cout<<ival<<endl; } in.clear(); return in; } int main() { string filename; cout<<"Input name of file(ctrl z end):\n"; cin>>filename; ifstream readname; readname.open(filename.c_str(),ios::app); if(!readname) { cerr<<"error:cnannot open the input file:"<<filename<<endl; return -1; } f(readname); return 0; }
( 在保證程序的可靠性時常常遇到的問題 )
C和C++的標準裏歷來沒有定義過
fflush(stdin)
。也許有人會說:「但是我用fflush(stdin)
解決了這個問題,你怎麼能說是錯的呢?」的確,某些編譯器(如VC6)支持用fflush(stdin)
來清空輸入緩衝,可是並不是全部編譯器都要支持這個功能(linux
下的gcc
就不支持),由於標準中根本沒有定義fflush(stdin)
。MSDN 文檔裏也清楚地寫着fflush on input stream is an extension to the C standard(fflush
操做輸入流是對 C 標準的擴充)。
固然,若是你絕不在意程序的移植性,用 fflush(stdin)
也沒什麼大問題。如下是 C99 對 fflush
函數的定義:
/* * 流狀態的查詢和控制 * 2010-3-26 wcdj */ #include <iostream> #include <stdexcept> #include "stdio.h" using namespace std; void way1_cleario(); void way2_cleario(); int main() { int ival; cout<<"Enter an interger:"; // read cin and test only for EOF; // loop is executed even if there are other IO failures while (cin>>ival, !cin.eof()) { // input stream is corrupted; bail out if (cin.bad()) { throw runtime_error("IO stream corrupted"); } // bad input if (cin.fail()) { cerr<<"bad data, try again/n";// warn the user // reset the stream //cin.clear(istream::failbit);// error, why? cin.clear();// ok way2_cleario();// eat excess bad stream //way2_cleario(); continue;// get next input } // ok, to process ival cout<<"ok, to process ival"<<endl; } return 0; } void way1_cleario() { int ival=0; fflush(stdin); //不良代碼,C++ codeblock下運行經過,下面代碼輸入要帶空格 // 在C中,刷新緩衝區可使用下面這樣的代碼 // 經過 while 循環把輸入流中的餘留數據「吃」掉 //一種移植性比較高的清空輸入緩衝區辦法 // while((ival=getchar())!='/n'&&ival!=EOF); // clearerr( stdin ); } void way2_cleario() { cin.ignore(200,' ');// 輸入的數據必須以空格分開,輸入數據必定要有空格 }
#include <iostream> #include <fstream> #include <stdexcept> using namespace std; istream& f(istream& in) { string ival; while(in>>ival,!in.eof()) { if(in.bad()) throw runtime_error("IO stream corrupted"); if(in.fail()) { cerr<<"bad data,try again:"; in.clear(); in.setstate(istream::eofbit); continue; } cout<<ival<<endl; } in.clear(); return in; } bool open_file(const string &file) { fstream fopen; fopen.clear(); fopen.open(file.c_str()); if(!fopen) { cerr<<"cannot open the file"<<endl; return -1; } string s; // while(fopen>>s) // { // cout<<s<<" "; // } f(fopen); fopen.close(); return 1; } int main() { cout<<"input name of file is: \n"; string fName; cin>>fName; open_file(fName); return 0; }
#include <iostream> #include <fstream> #include <sstream> #include <string> #include <vector> using namespace std; int main() { string line,word; ifstream input("out.txt"); if(!input) { cerr<<"error:can not open input file:"<<endl; return -1; } // 打開後,將文件內容讀入string類型的vector容器,每一行存儲爲 // 該容器對象的一個元素。 vector<string> fileword; while(getline(input,line)) { fileword.push_back(line); input.clear(); } input.close(); vector<string>::const_iterator it =fileword.begin(); while(it!=fileword.end()) { istringstream divword(*it); while (divword>>word) { cout<<word<<","; } cout<<endl; ++it; } return 0; }
#include <fstream> #include <iostream> using namespace std; const char * filename = "out.txt"; int main() { ofstream out;//寫入文件處理 out.open("out.txt",ios_base::app); if (out.is_open()) { out << "This is a line."; out << "This is another line.\n"; out.close(); out.clear(); } char buffer0[256]; ifstream in("out.txt");//讀取文件處理 if (! in.is_open()) { cout << "Error opening file"; return 0; } while (!in.eof() ) { in.getline (buffer0,100); cout << buffer0 << endl; } }
#include <sstream> #include <iostream> using namespace std; int main() { int val1=512,val2=1024; ostringstream format_message; format_message<<"val1:"<<val1<<"~"<<"val2:"<<val2<<"\n"; //format_message<<"val1:"<<val1<<"\n"<<"val2:"<<val2<<"\n";//這種輸出,獲得val1爲0 istringstream input_istring(format_message.str()); cout <<format_message.str(); string dump; input_istring >> dump >> val1 >> dump >> val2; cout << val1 << " " << val2 << endl; // prints 512 1024 return 0; }
#include <iostream> #include <vector> using namespace std; typedef vector <int>::iterator ITER; bool find_int(ITER begin,ITER end,int i) { // assert( begin <= end ); if ( begin > end ) cout << " iterator error." << endl; for (ITER it=begin;it!=end;++it) { if ((*it)==i) { return true; } } return false; } int main() { int ia[]={0,1,2,3,4,5}; vector<int> ivec(ia,ia+6); bool find=false; find=find_int(ivec.begin(),ivec.end(),3); if(find) { cout<<"we got 3 in ia[]."<<endl; } else cout<< "there is no 3 in ia[]."<<endl; }
#include <iostream> #include <vector> using namespace std; typedef vector <int>::iterator ITER; ITER find_int(ITER begin,ITER end,int i,ITER &ref) { // assert( begin <= end ); if ( begin > end ) cout << " iterator error." << endl; for (ITER it=begin;it!=end;++it) { if ((*it)==i) { ref=it; } } return ref; } int main() { int ia[]={0,1,2,3,4,5}; vector<int> ivec(ia,ia+6); // bool find=false; ITER ref=ivec.end(); ITER findit=find_int(ivec.begin(),ivec.end(),3,ref); if(findit!=ivec.end()) { cout<<"we got 3 in ia[]."<<endl; } else cout<< "there is no 3 in ia[]."<<endl; }
#include <iostream> #include <vector> #include <string> using namespace std; int main() { cout << "\tInput some strings ( ctrl+z to end ):" << endl; vector<string> strVec; string str; while ( cin >> str ) { strVec.push_back( str ); } cout << " All the member of the vector<string> strVec are:\n"; for ( vector<string>::iterator it = strVec.begin(); it != strVec.end(); ++it ) { cout << *it << endl; } return 0; }
#include <iostream> #include <list> #include <deque> #include <string> using namespace std; int main() { cout<<"input some int numbers:"<<endl; list<int> ilist; int iVal; while(cin>>iVal) { ilist.push_back(iVal); } deque<int> iOddDeque,iEvenDeque; for(list<int>::iterator it=ilist.begin();it!=ilist.end();++it) { if(*it%2==0) { iEvenDeque.push_back(*it); } else if(*it%2==1) { iOddDeque.push_back(*it); } } cout<<"All numbers inputed,the odd numbers are:"<<endl; for(deque<int>::iterator it=iOddDeque.begin();it!=iOddDeque.end();++it) { cout<<*it<<" "; } cout<<"\nAll the number inputed,the even numbers are:"<<endl; for(deque<int>::iterator it=iEvenDeque.begin();it!=iEvenDeque.end();++it) { cout<<*it<<" "; } return 0; }
vector<int>::iterator mid = iv.begin() + iv.size()/2; while (vector<int>::iterator iter != mid) if (iter == some_val) iv.insert(iter, 2 * some_val);
(1)當執行it.insert操做以後,迭代器 mid 就失效了,是由於 iv.end() 失效了。
(2)迭代器iter沒有初始化;
(3)if語句中錯誤,由於if ( *iter == some_val )
可改成:
vector<int>::iterator iter = iv.begin(); while ( iter != iv.begin() + iv.end() / 2 ) { if ( *iter == some_val ) { it.insert ( iter, 2 * some_val ); iter += 2; // important } else ++iter; }
假設有以下 ia 的定義,將 ia 複製到一個 vector 容器和一個 list 容器中。
使用單個迭代器參數版本的 erase 函數將 list 容器中的奇數值元素刪除掉,而後將 vector 容器中的偶數值元素刪除掉。int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89 };
#include <iostream> #include <list> #include <vector> #include <string> using namespace std; int main() { int ia[]={0,1,1,2,2,3,5,8,8,13,21,55,89}; vector<int> ivec(ia,ia+13); list<int> ilist(ia,ia+13); cout<<"before erase,the elements of ivec are:"<<endl; for(vector<int>::iterator it=ivec.begin();it!=ivec.end();++it) { cout<<*it<<" "; } cout<<"\nbefore erase,the elements of ilist are:"<<endl; for(list<int>::iterator it=ilist.begin();it!=ilist.end();++it) { cout<<*it<<" "; } for(vector<int>::iterator iter=ivec.begin();iter!=ivec.end();) { cout<<"\nbefore erase *it:"<<*iter<<endl; if((*iter)%2==0) { iter=ivec.erase(iter);//erase擦除iter迭代器後iter爲野指針,要把下一個迭代器值付給它 } else { iter++;//不刪除就向後搜索 } cout<<"after erase *it:"<<*iter<<endl; } for(list<int>::iterator iter=ilist.begin();iter!=ilist.end();++iter) { cout<<"\n2:before erase *it:"<<*iter<<endl; if((*iter)%2==1) { iter=ilist.erase(iter);//第二種寫法,擦除以後將指針往前進一個 --iter; } cout<<"2:after erase *it:"<<*iter<<endl; } cout << "\n After erase, the elements of ivec are:" << endl; for ( vector<int>::iterator it = ivec.begin(); it != ivec.end(); ++it ) { cout << *it << " "; } cout << "\n After erase, the elements of list are:" << endl; for ( list<int>::iterator it = ilist.begin(); it != ilist.end(); ++it ) { cout << *it << " "; } return 0; }
#include <iostream> #include <list> #include <vector> #include <string> #include <algorithm> using namespace std; int main() { char *c_arr[] = { "one", "two", "three" }; list<char*> pLst; pLst.assign( &c_arr[0], &c_arr[0]+3 ); cout << "\tAll the members in the list<char*> pLst are:\n"; for ( list<char*>::iterator it = pLst.begin(); it != pLst.end(); ++it ) { cout << *it << " "; } vector<string> strVec; strVec.assign( pLst.begin(), pLst.end() ); cout << "\n\tAfter assignment from list, the vector<string> strVec are:\n"; for ( vector<string>::iterator it = strVec.begin(); it != strVec.end(); ++it ) { cout << *it << " "; } cout << endl; return 0; }
"ab2c3d7R4E6"
, 編寫程序尋找該字符串中全部的數字字符,而後再尋找全部的字母字符。以兩種版本編寫該程序:第一個版本使用 find_first_of 函數,而第二個版本則使用 find_first_not_of 函數。#include <iostream> #include <list> #include <vector> #include <string> #include <algorithm> using namespace std; int main() { string s1("ab2c3d7r4e6"); vector <string::size_type> index; string s2("0123456789"); string::size_type ix=0; while((ix=s1.find_first_not_of(s2,ix))!=string::npos) { //int id=static_cast<int> (ix); index.push_back(ix); ++ix; } for(vector <string::size_type> ::iterator it=index.begin();it!=index.end();++it) { cout<<s1[*it]<<endl; } return 0; }
已知有以下 string 對象:
string line1 = "We were her pride of 10 she named us:"; string line2 = "Benjamin, Phoenix, the Prodigal" string line3 = "and perspicacious pacific Suzanne"; string sentence = line1 + ' ' + line2 + ' ' + line3;
編寫程序計算 sentence 中有多少個單詞,並指出其中最長和最短的單詞。若是有多個最長或最短的單詞,則將它們所有輸出。
#include <iostream> #include <list> #include <vector> #include <string> #include <algorithm> using namespace std; int main() { string line1 = "We were her pride of 10 she named us:"; string line2 = "Benjamin, Phoenix, the Prodigal"; string line3 = "and perspicacious pacific Suzanne"; string sentence = line1 + ' ' + line2 + ' ' + line3; string separators(" :\t,\v\r\n\f");//分隔字符 for(size_t ix=0;ix<separators.size();++ix) { cout<<" "<<separators[ix]<<" "; } cout<<endl; string word; string::size_type maxlen,minlen,wordlen; vector<string> longestword,shortestword; string::size_type startpos ,endpos=0; size_t cnt=0; cout << "\n The sentence is :\n" << sentence << endl; while((startpos=sentence.find_first_not_of(separators,endpos))!=string::npos) { ++cnt; endpos=sentence.find_first_of(separators,startpos); if(endpos==string::npos)//若是到達句子的末尾,則認爲這個句子只有一個單詞 { wordlen=sentence.size()-startpos; } else //不然的話該單詞長度爲末尾點減初始點阿 wordlen=endpos-startpos; word.assign(sentence.begin()+startpos,sentence.begin()+startpos+wordlen); if(cnt==1) { maxlen=minlen=wordlen; longestword.push_back(word); shortestword.push_back(word); } else //處理最長字符和最短字符 { if(wordlen>maxlen) { maxlen=wordlen; longestword.clear(); longestword.push_back(word); } else if(wordlen==maxlen) { longestword.push_back(word); } if(wordlen<minlen) { minlen=wordlen; shortestword.clear(); shortestword.push_back(word); } else if(wordlen==minlen) { shortestword.push_back(word); } } } cout << "\n There are " << cnt << " words in the sentence." << endl; vector<string>::iterator iter; // out the longest word cout << "\n longest word :" << endl; iter = longestword.begin(); while ( iter != longestword.end() ) { cout << *iter++ << endl; } // out the shortest word cout << "\n shortest word :" << endl; iter = shortestword.begin(); while ( iter != shortestword.end() ) { cout << *iter++ << endl; } return 0; }
#include <iostream> #include <string> #include <stack> #include <deque> using namespace std; int main( ) { stack<char> sExp; string strExp; cout << " Input a expression: "; cin >> strExp; // deal the sExp string::iterator it = strExp.begin(); while ( it != strExp.end() ) { if ( *it != ')' ) sExp.push( *it );//若是不是)則將字符push進來,一直push到(爲止 else { while ( ( sExp.top() != '(' ) && !sExp.empty() )//檢測到),如今pop頂元素,一直到(爲止 { sExp.pop(); } // sExp.pop(); if ( sExp.empty() )//若是檢測不到(則沒有匹配到( cout << " It's not matched. " << endl; else { sExp.pop(); sExp.push('@'); } } ++it; } // show out the elements of the stack cout << "\nThe elements of the stack are:" << endl; while ( ! sExp.empty() ) { cout << sExp.top() << endl; sExp.pop(); } return 0; }
#include <iostream> #include <utility> #include <string> #include <vector> using namespace std; int main() { // typedef pair <string,string> Author; // pair <string,string> author("James","Smith"); // Author proud("Marvell","Joy"); // cout<<author.first<<"\t"<<author.second<<endl; // cout<<proud.first<<"\t"<<proud.second<<endl; //pair<string,string> next_auth; //string first,last; //while (cin>>first>>last) //{ // next_auth=make_pair(first,last); // cout<<next_auth.first<<"\t"<<next_auth.second; //} string str; int ival; vector< pair<string,int> > pairVec; while(cin>>str>>ival) { pairVec.push_back(make_pair(str,ival)); } cout<<"\nThe content of pairVec is : \n"; for(vector< pair<string,int> >::iterator it=pairVec.begin();it!=pairVec.end();++it) { cout<<it->first<<"\t"<<it->second<<endl; } return 1; }
支持第一種,不支持list
Exercise 10.14:
map 容器的 count 和 find 運算有何區別?
Exercise 10.15:
你認爲 count 適合用於解決哪一類問題?而 find 呢?
Exercise 10.16:
定義並初始化一個變量,用來存儲調用鍵爲 string、值爲 vector
count 返回被尋找元素的次數,結果爲0或者1.find函數返回被尋找元素的迭代器。
count用來查找元素是否存在,find用來查找該鍵值對應的元素
#include <iostream> #include <utility> #include <string> #include <vector> #include <map> #include <fstream> #include <sstream> using namespace std; int main() { // typedef pair <string,string> Author; // pair <string,string> author("James","Smith"); // Author proud("Marvell","Joy"); // cout<<author.first<<"\t"<<author.second<<endl; // cout<<proud.first<<"\t"<<proud.second<<endl; // pair<string,string> next_auth; // string first,last; // while (cin>>first>>last) // { // next_auth=make_pair(first,last); // cout<<next_auth.first<<"\t"<<next_auth.second; // } // string str; // int ival; // vector< pair<string,int> > pairVec; // while(cin>>str>>ival) // { // pairVec.push_back(make_pair(str,ival)); // } // cout<<"\nThe content of pairVec is £º \n"; // for(vector< pair<string,int> >::iterator it=pairVec.begin(); it!=pairVec.end(); ++it) // { // cout<<it->first<<"\t"<<it->second<<endl; // } // map<string,int> WordCount; // string word; // while(cin>>word) // { // // ++WordCount[word]; // // cout<<"The word "<<word<<" appears for "<<WordCount[word]<<" times "<<endl; // //WordCount.insert(make_pair(word,1)); // pair<map<string,int>::iterator,bool> ret=WordCount.insert(make_pair(word,1)); // if(!ret.second) // ++ret.first->second; // // } // map<string,int>::iterator map_it=WordCount.begin(); // // while(map_it!=WordCount.end()) // { // //// cout<<map_it->first<<" "<<map_it->second<<endl; //// ++map_it; // int occurs = 0; // if (WordCount.count("foobar")&&WordCount.find("foobar")!=WordCount.end()) // { // occurs = WordCount["foobar"]; // cout<<"foobar occurs"<<occurs<<" times "; // } map<string,string> trans_map; string key,value; ifstream map_file("C://Users//allen//Desktop//mapfile.txt"); ifstream input("C://Users//allen//Desktop//input.txt"); if(map_file.is_open()&&input.is_open()) { while(map_file>>key>>value) trans_map.insert(make_pair(key,value)); string line; while(getline(input,line)) { istringstream stream(line); string word; bool firstword=true; while(stream>>word) { map<string,string>::const_iterator map_it=trans_map.find(word); if(map_it!=trans_map.end()) { word=map_it->second; } if(firstword) firstword=false; else cout<<" "; cout<<word; } cout<<endl; } } else { // throw runtime_error("no transformation file"); cout<<"No file information"<<endl; } return 1; }
#include <iostream> #include <utility> #include <string> #include <vector> #include <map> #include <fstream> #include <sstream> #include <set> using namespace std; void restricted_wc(vector<string> strVec,map<string,int>&wordCount) { set<string> excluded; for ( vector<string>::iterator it = strVec.begin(); it != strVec.end(); ++it ) { excluded.insert( *it ); } string word; cout << " Input some words to count the words in wordCount(map) ( ctrl + z to end): " << endl; cin.clear(); while ( cin >> word ) { if ( !excluded.count( word ) ) ++wordCount[ word ]; } } int main() { cout << " Input some words to vector<string> excluded ( ctrl + z to end): " << endl; vector<string> excludedVec; string excludedWord; while ( cin >> excludedWord ) excludedVec.push_back( excludedWord ); map<string, int > wordCount; restricted_wc( excludedVec, wordCount ); cout << "\n\tShow out the map:wordCount: " << endl; for ( map< string, int >::iterator it = wordCount.begin(); it != wordCount.end(); ++it ) { cout << " The word '" << (*it).first << "' appears for " << (*it).second << " times. " << endl; } return 1; }
#include <iostream> #include <map> #include <utility> #include <string> using namespace std; int main() { // cout << "Hello world!" << endl; multimap<string,string> mmapAuthor; string author,book; cout<<"input Author and his books:\n"; while(cin>>author>>book) { mmapAuthor.insert(make_pair(author,book)); } string searchitem; cout<<"which author you wanna search: "; cin.clear(); cin>>searchitem; multimap<string,string>::iterator iter=mmapAuthor.find(searchitem); typedef multimap<string,string>::size_type sz_type; sz_type amount=mmapAuthor.count(searchitem);//count返回查找元素的數量,find返回第一個指針 for(sz_type cnt=0; cnt!=amount; ++cnt,++iter) { cout<<"\n we got the author: "<<iter->first<<endl<<"\t==>>his book:\t"<<iter->second<<endl; } amount=mmapAuthor.erase(searchitem); if(amount) { cout<<"\n we have erase"<<amount<<"books of the author"<<endl; } cout<<endl; return 0; }
multimap< string, string > mmapAuthor; string author, book; cin.clear(); cout << " \t=>> Input Author and his Book( ctrl + z to end ):\n"; while ( cin >> author >> book ) { mmapAuthor.insert( make_pair( author, book ) ); } typedef multimap<string, string >::iterator author_it; author_it iter = mmapAuthor.begin(); if ( iter == mmapAuthor.end() ) { cout << "\n\t Empty multimap! " << endl; return 0; } string currAuthor, preAuthor; do { currAuthor = iter->first; if ( preAuthor.empty() || currAuthor[0] != preAuthor[0] ) { cout << "Author Names Beginning with ' " << iter->first[0] << " ' : " << endl; } cout << currAuthor; pair< author_it, author_it > pos = mmapAuthor.equal_range( iter->first ); while ( pos.first != pos.second ) { cout << ", " << pos.first->second; ++pos.first; } cout << endl; iter = pos.second; preAuthor = currAuthor; } while ( iter != mmapAuthor.end() );
#include <iostream> #include <utility> #include <string> #include <vector> #include <map> #include <fstream> #include <sstream> #include <set> using namespace std; class TextQuery { public: typedef vector<string>::size_type line_no; void read_file(ifstream &is){store_file(is);build_map();} set<line_no> run_query(const string&) const; string text_line(line_no) const; private: void store_file(ifstream&); void build_map(); vector<string> lines_of_text; map< string,set<line_no> > word_map; }; void TextQuery::store_file(ifstream& is) { string line; while(getline(is,line)) { lines_of_text.push_back(line); } } void TextQuery::build_map() { for (line_no line_num=0;line_num!=lines_of_text.size();++line_num) { istringstream line(lines_of_text[line_num]); string word; while(line>>word) { word_map[word].insert(line_num);//word_map[word]==set } } } set<TextQuery::line_no> TextQuery::run_query(const string&query_word) const { map< string,set<line_no> >::const_iterator loc=word_map.find(query_word); if(loc==word_map.end()) return set<line_no>(); else return loc->second; } string TextQuery::text_line(line_no line) const { if(line<lines_of_text.size()) return lines_of_text[line]; // throw std::out_of_range("line number out of range"); } void print_results(const set<TextQuery::line_no>& locs,const string& sought,const TextQuery &file) { typedef set<TextQuery::line_no> line_nums; line_nums::size_type size1 =locs.size(); cout<<"\n"<<sought<<" occurs "<<size1<<" "<<" times "<<endl; line_nums::const_iterator it=locs.begin(); for(;it!=locs.end();++it) { cout<<"\t(line "<<(*it)+1<<")"<<file.text_line(*it)<<endl; } } int main() { ifstream infile("C://Users//allen//Desktop//input.txt"); TextQuery tq; tq.read_file(infile); while(true) { cout<<"Enter a word to look for, or q to quit it: "; string s; cin>>s; if(!cin||s=="q") break; set<TextQuery::line_no> locs=tq.run_query(s); print_results(locs,s,tq); } return 1; }
#include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> using namespace std; int main() { // istream_iterator <int> cin_it(cin); // istream_iterator <int> eof; // vector<int> vec(cin_it,eof); // sort(vec.begin(),vec.end()); // ostream_iterator <int> output(cout," "); // unique_copy(vec.begin(),vec.end(),output); ifstream ifile("C://Users//melo//Desktop//1.txt"); string istr; vector <string> inputfile; ostream_iterator <string> output(cout," "); while(ifile.is_open()&&ifile>>istr) { inputfile.push_back(istr); } copy(inputfile.begin(),inputfile.end(),output); return 0; } #include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> using namespace std; int main() { ifstream ifile("C://Users//melo//Desktop//1.txt"); istream_iterator <string> cin_it(ifile); istream_iterator <string> eof; ostream_iterator <string> output(cout," "); vector<string> inputfile(cin_it,eof); copy(inputfile.begin(),inputfile.end(),output); //sort(inputfile.begin) return 0; }
#include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> using namespace std; bool IsOdd (int i) { return ((i%2)==1); } int main() { istream_iterator <int> cin_it(cin); istream_iterator <int> eof; ofstream outputfile1("C://Users//melo//Desktop//1.txt"); ofstream outputfile2("C://Users//melo//Desktop//2.txt"); if ( !outputfile1 || !outputfile2 ) { cerr << " File can't be open. " << endl; return -1; } ostream_iterator <int> output1(outputfile1," "); ostream_iterator <int> output2(outputfile2,"\n"); while(cin_it!=eof) { if((*cin_it)%2==0) { *output2++=*cin_it++; } else { *output1++=*cin_it++; } //cin_it++; } outputfile1.close(); outputfile2.close(); return 0; }
#include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> #include <list> using namespace std; int main() { int ia[]={1,2,3,4,0,6}; list <int> iList(ia,ia+6); list <int> :: reverse_iterator last_0_it=find(iList.rbegin(),iList.rend(),0); if(last_0_it!=iList.rend()) cout<<"get the last 0,it's value is:"<<*last_0_it<<endl; else cout<<endl; return 0; }
myScreen.move(4,0).set('#').display(cout);
#include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> #include <list> using namespace std; class Screen { public: typedef std::string::size_type index; Screen():cursor(0),height(0),width(0),contents("") {}; Screen(index hei,index wid,const string&content=""):cursor(0),height(hei),width(wid),contents(content) {}; Screen& move(index r,index c) { index row=r*width; cursor=row+c; return *this; } Screen& set(char c) { contents[cursor]=c; return *this; } Screen& display(ostream& os) { do_display(os); return *this; } const Screen& display(ostream &os) const { do_display(os); return *this; } private: string contents; index cursor; index height,width; void do_display(ostream&os)const { os<<contents; } }; int main() { Screen myscreen(5,5,"bbbbbgggggfffffiiiiimmmmm"); myscreen.move(4,0).set('$').display(cout); return 0; }
理解複製控制成員和構造函數的一個良好方式是定義一個簡單類,該類具備這些成員,每一個成員打印本身的名字:
struct Exmpl { Exmpl() { std::cout << "Exmpl()" << std::endl; } Exmpl(const Exmpl&) { std::cout << "Exmpl(const Exmpl&)" << std::endl; } // ... };
編寫一個像 Exmpl 這樣的類,給出複製控制成員和其餘構造函數。而後寫一個程序,用不一樣方式使用 Exmpl 類型的對象:做爲非引用形參和引用形參傳遞,動態分配,放在容器中,等等。研究什麼時候執行哪一個構造函數和複製構造函數,能夠幫助你融會貫通地理解這些概念。
#include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> #include <list> using namespace std; class exmpl { public: exmpl() { cout<<"Using Constructor exmpl"<<endl; } exmpl(const exmpl& ex1) { cout<<"Using Copy Constructor exmpl(const exmpl&)"<<endl; } exmpl& operator=(const exmpl& ex1) { cout<<"Using operator="<<endl; } ~exmpl() { cout<<"Using deconstructor"<<endl; } }; void func1(exmpl obj) { } void func2(exmpl& obj) { } exmpl func3() { exmpl obj; return obj; } int main() { exmpl ex1; exmpl ex2(ex1); exmpl ex3=ex1; ex2=ex3; func1(ex1); func2(ex1); ex1=func3(); exmpl *p=new exmpl; delete p; vector<exmpl> iVec(3); return 0; }
A Message-Handling Example:有些類爲了作一些工做須要對複製進行控制。爲了給出這樣的例子,咱們將概略定義兩個類,
這兩個類可用於郵件處理應用程序。Message 類和 Folder 類分別表示電子郵件(或其餘)消息和消息所出現的目錄,
一個給定消息能夠出如今多個目錄中。Message 上有 save 和 remove 操做,用於在指定 Folder 中保存或刪除該消息。
#include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> #include <list> using namespace std; class Message { public: Message(const string& str=""):contents(str) {} Message(const Message&); Message& operator=(const Message&); ~Message() { remove_Msg_from_Folders(); } void save(Folder&); void remove(Folder&); void addFldr(Folder*); void remFldr(Folder*); private: string contents; set<Folder*> folders; void put_Msg_in_Folders(const set<Folder*> &); void remove_Msg_from_Folders(); }; class Folder { public: Folder() {} Folder(const Folder&); Folder& operator=(const Folder&); ~Folder(); void save(Message&); void remove(Message&); void addMsg(Message&); void remMsg(Message&); private: set<Message*> messages; void put_Fldr_In_Messages(const set<Message*>&); void remove_Fldr_Messages(); }; /*******************Folder 類 的定義************************/ Folder::Folder(const Folder&f):messages(f.messages) { put_Fldr_In_Messages(messages); } void Folder::put_Fldr_In_Messages(const set<Message*>&rhs) { for(set<Message*>::const_iterator beg=rhs.begin();beg!=rhs.end();++beg) (*beg)->addFldr(this); } Folder& Folder::operator=(const Folder& rhs) { if(&rhs!=this) { remove_Fldr_Messages(); messages=rhs.messages; put_Fldr_In_Messages(rhs.messages); } return *this; } void Folder::remove_Fldr_Messages() { for(set<Message*>::const_iterator beg=messages.begin();beg!=messages.end();++beg) (*beg)->remFldr(this); } Folder::~Folder() { remove_Fldr_Messages(); } void Folder::save(Message &msg) { addMsg(&msg); msg.addFldr(this); } void Folder::remove(Message& msg) { remMsg(&msg); msg.remFldr(this); } void Folder::addMsg(Message & msg) { messages.insert(mag); } void Folder::remMsg(Message & msg) { messages.erase(msg); } /*******************Message類 的定義************************/ Message::Message(const Message& m):contents(m.contents),folders(m.folders) { put_Msg_in_Folders(); } Message& Message::operator=(const Message&rhs) { if(&rhs!=this) { remove_Msg_from_Folders(); contents=rhs.contents; folders=rhs.folders; put_Msg_in_Folders(rhs.folders); } return *this; } void Message::put_Msg_in_Folders(const set<Folder*> &rhs) { for(set<Folder*>::const_iterator beg=rhs.begin(); beg!=rhs.end(); ++beg) (*beg)->addMsg(this); } void Message::remove_Msg_from_Folders() { for(set<Folder*>::const_iterator beg=folders.begin(); beg!=folders.end(); ++beg) (*beg)->remMsg(this); } void Message::save(Folder &fldr) { addFldr(&fldr); fldr.remMsg(this); } void Message::remove(Folder & fldr) { remFldr(&fldr); fldr.remMsg(this); } void Message::addFldr(Folder* fldr) { folders.insert(fldr); } void Message::remFldr(Folder* fldr) { folders.erase(fldr); } int main() { return 0; }
#include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> #include <list> using namespace std; class HasPtr { public: HasPtr(int *p,int i):ptr(new U_Ptr(p)),val(i){} HasPtr(const HasPtr&orig):ptr(orig.ptr),val(orig.val){++ptr->use;} HsaPtr& operator=(const HasPtr& rhs) { ++rhs.ptr->use; if(--ptr->use==0) delete ptr; ptr=rhs.ptr; val=rhs.val; return *this; } ~HasPtr() { if(--ptr->use==0) delete ptr; } int *get_ptr() const {return ptr->ip;} int get_int() const {return val;} void set_ptr(int *p){ptr->ip=p;} void set_int(int i){val=i;} int get_ptr_val() const {return *(ptr->ip);} void set_ptr_val(int val) {*(ptr->ip=i);} private: U_ptr* ptr; int val; }; class U_ptr { friend class HasPtr; int *ip; size_t use; U_Ptr(int* p) :ip(p),use(1){} ~U_Ptr() {delete p;} }; int main() { return 0; }
The valuelike HasPtr class defines each of the copy-control members. Describe what would happen if the class defined
值型 HasPtr 類定義了全部複製控制成員。描述將會發生什麼,若是該類:
(a)此種狀況下,使用編譯器合成的賦值操做符。所以若將一個HasPtr對象賦值給另外一個HasPtr對象,則兩個對象的ptr成員值相同,
即兩者指向同一基礎int對象,當其中一個對象被撤銷後,該基礎int對象也被撤銷,使得另外一個對象中的ptr成員指向一個失效的基礎int對象。
並且當另外一個對象被撤銷時,會由於析構函數對同一指針進行重複刪除而出現內存訪問非法的錯誤。此外,被賦值的HasPtr對象
的ptr成員原來所指向的基礎int對象不能再被訪問,但也沒有被撤銷。'
(b) 此時使用編譯器合成的析構函數,當一個對象被撤銷後,其成員所指向的基礎int對象不會被撤銷,會一直存在,從而致使內存泄露。
(c) 此時,使用編譯器合成的複製構造函數和賦值操做符。當將一個對象賦值給另外一個HasPtr對象時或複製構造另外一個HasPtr對象時,
則兩個HasPtr對象的ptr成員值相同,其餘出現的問題與(a)的狀況相同。
爲下面的 CheckoutRecord 類定義一個輸出操做符:
class CheckoutRecord { public: // ... private: double book_id; string title; Date date_borrowed; Date date_due; pair<string,string> borrower; vector< pair<string,string>* > wait_list; };
(a) Book (b) Date (c) Employee (d) Vehicle (e) Object (f) Tree
c++ #include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> #include <list> using namespace std; class Date { public: Date(){} Date(int y,int m,int d):year(y),month(m),day(d){} friend ostream& operator<<(ostream&,const Date&); private: int year,month,day; }; ostream& operator<<(ostream& out,const Date&d) { out<<"year:"<<d.year<<"\t"<<"month:"<<d.month<<"\t"<<"day:"<<d.day<<endl; } int main() { Date d(1988,12,1); cout<<d<<endl; return 0; }
c++
Sales_item Sales_item::operator+( const Sales_item& rhs ) { units_sold += rhs.units_sold; revenue += rhs.revenue; return *this; } //將下面定義的非成員+=操做符聲明爲類Sales_item的友元: Sales_item operator+=( Sales_item& lhs, const Sales_item& rhs ) { lhs = lhs + rhs; return lhs; }
這個方法缺點:在+=操做中須要建立和撤銷一個臨時Sales_item對象,來保存+操做的結果,沒有本節中的方法簡單有效。
#include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> #include <list> using namespace std; class Date { public: Date(){}//默認構造函數 Date(int y,int m,int d):year(y),month(m),day(d){}//構造函數 Date(Date& d):year(d.year),month(d.month),day(d.day){}//複製構造函數 friend ostream& operator<<(ostream&,const Date&);//輸出操做符重載函數 int year,month,day; }; ostream& operator<<(ostream& out,const Date& d) { out<<"year:"<<d.year<<"\t"<<"month:"<<d.month<<"\t"<<"day:"<<d.day<<endl; } class CheckoutRecord { public: CheckoutRecord(){} friend istream& operator>>(istream& ,CheckoutRecord&); friend ostream& operator<<(ostream& ,CheckoutRecord&); CheckoutRecord& operator=(const CheckoutRecord&); private: double book_id; string title; Date date_borrowed; Date date_due; pair<string,string> borrower; vector<pair<string,string>*> wait_list; }; CheckoutRecord& CheckoutRecord::operator=(const CheckoutRecord& cr) { book_id=cr.book_id; title=cr.title; date_borrowed=cr.date_borrowed; date_due=cr.date_borrowed; borrower.first=cr.borrower.first; borrower.second=cr.borrower.second; wait_list.clear(); for(vector <pair<string,string>*>::const_iterator it=cr.wait_list.begin();it!=wait_list.end();++it) { pair<string,string> *ppr=new pair<string,string>; ppr->first=(*it)->first; ppr->second=(*it)->second; wait_list.push_back(ppr); } return *this; } istream& operator>>(istream& in, CheckoutRecord& c) { cout << " Input book_id(double) and title(string) :\n"; in >> c.book_id >> c.title; cout << " Input data_borrowed (3 ints: year, month , day) :\n"; in >> c.date_borrowed.year >>c.date_borrowed.month >>c.date_borrowed.day; cout << " Input data_due (3 ints: year, month , day) :\n"; in >> c.date_due.year >> c.date_due.month >> c.date_due.day; cout << " Input the pair<string,string> borrower (string) :\n"; in >> c.borrower.first >> c.borrower.second; if ( !in )//檢查輸入是否錯誤 { c = CheckoutRecord(); return in; } cout << " Input the wait_list (string) :\n"; c.wait_list.clear(); while(in) { pair<string,string>* p_pstr=new pair<string,string>; in>>p_pstr->first>>p_pstr->second; if(!in)//檢查輸入是否錯誤 { delete p_pstr; return in; } else { c.wait_list.push_back(p_pstr); } } return in; } ostream& operator<<(ostream& out,CheckoutRecord& s) { out << s.book_id << "\t" << s.title<< "\t" << s.date_borrowed<< "\t" << s.date_due<< "\t" ; out<< " borrower:" <<s.borrower.first << "," << s.borrower.second << endl; out << " wait_list: " << endl; for ( vector< pair<string,string>* >::const_iterator it = s.wait_list.begin();it!= s.wait_list.end(); ++it ) { out << "\t" << (*it)->first << "," << (*it)->second << endl; } return out; } int main() { CheckoutRecord c1; CheckoutRecord c2; cin>>c1; c2=c1; cout<<c2<<endl; return 0; }
有問題:vector<pair<string,string>*>保存的是指針,對象的地址。
#include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> #include <list> using namespace std; class Screen { public: /*****構造函數以及類型聲明*****/ typedef string::size_type index; Screen():cursor(0),height(0),width(0),contents("") {}; Screen(index he,index wd,string content=""):contents(content),height(he),width(wd),cursor(0) {} /*****操做函數*****/ Screen& move(index r,index c); Screen& set(char c); Screen& display(ostream& os); char get_char() const; const Screen& display(ostream &os) const; const char get_char(index r, index c) const; const index get_cursor() const; /*****操做符重載函數*****/ Screen& operator=(Screen& s); private: string contents; string::size_type cursor; string::size_type height,width; void do_display(ostream&os)const { os<<contents<<endl; } }; Screen& Screen::move(index r,index c) { index row=r*width; cursor=row+c; return *this; } Screen& Screen::set(char c) { contents[cursor]=c; return *this; } Screen& Screen::display(ostream& os) { do_display(os); return *this; } char Screen::get_char() const { return contents[cursor]; } Screen& Screen::operator=(Screen& s) { contents=s.contents; height=s.height; width=s.width; cursor=s.cursor; } const Screen& Screen::display(ostream &os) const { do_display(os); return *this; } const char Screen::get_char(index r, index c) const { index row = r * width; // compute the row location return contents[row + c]; // offset by c to fetch specified character } const Screen::index Screen::get_cursor() const { return cursor; } /*****ScrPtr類*****/ class ScrPtr { friend class ScreenPtr; Screen *sp; size_t use; ScrPtr (Screen *p):sp(p),use(1) {} ~ScrPtr() { delete sp; } }; /*****ScreenPtr類*****/ class ScreenPtr { public: ScreenPtr(Screen *p):ptr(new ScrPtr(p)) { cout<<"after call the constructor ,use :"<<ptr->use<<endl; } ScreenPtr(const ScreenPtr &orig):ptr(orig.ptr) { ++ptr->use; cout<<"after call the copy constructor ,use :"<<ptr->use<<endl; } ScreenPtr& operator=(const ScreenPtr& sp) { ++sp.ptr->use; if ( --ptr->use == 0 ) delete ptr; ptr = sp.ptr; return *this; } Screen& operator*() { return *ptr->sp; } Screen* operator->() { return ptr->sp; } const Screen& operator*( ) const { return *ptr->sp; } const Screen* operator->( ) const { return ptr->sp; } ~ScreenPtr() { if(--ptr->use==0) delete ptr; cout<<"after call the deconstructor ,use :"<<ptr->use<<endl; } private: ScrPtr *ptr; }; int main() { ScreenPtr s1=new Screen(5,5,"bbbbbgggggfffffiiiiimmmmm"); ScreenPtr s2=s1; //s1->move() s1->move(4,0).set('$').display(cout); (*s2).move(4,0).set('$').display(cout); return 0; }
CheckedPtr 類 表示指向數組的指針:
#include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> #include <list> #include <stdexcept> using namespace std; class CheckedPtr { public: CheckedPtr(int*b,int*e):beg(b),end(e),curr(b) {} CheckedPtr& operator++(); CheckedPtr& operator--(); CheckedPtr operator++(int); CheckedPtr operator--(int); int& operator* (); int& operator[](const size_t index); const int& operator*() const; const int& operator[](const size_t index)const; friend bool operator==(const CheckedPtr& lhs,const CheckedPtr& rhs); friend bool operator!=(const CheckedPtr& lhs,const CheckedPtr& rhs); friend bool operator>(const CheckedPtr& lhs,const CheckedPtr& rhs); friend bool operator<(const CheckedPtr& lhs,const CheckedPtr& rhs); friend bool operator>=(const CheckedPtr& lhs,const CheckedPtr& rhs); friend bool operator<=(const CheckedPtr& lhs,const CheckedPtr& rhs); private: int* beg; int* end; int* curr; }; CheckedPtr& CheckedPtr::operator++() { if(curr==end) throw out_of_range ("increment past the end of CheckedPtr"); ++curr; return *this; } CheckedPtr& CheckedPtr::operator--() { if(curr==beg) throw out_of_range ("decrement past the begining of the CheckedPtr"); --curr; return *this; } CheckedPtr CheckedPtr::operator++(int) { CheckedPtr ret(*this); ++(*this); return ret; } CheckedPtr CheckedPtr::operator--(int) { CheckedPtr ret(*this); --(*this); return ret; } int& CheckedPtr::operator*() { if(curr==end) throw out_of_range("invalid ptr"); return *curr; } const int& CheckedPtr::operator*() const { if(curr==end) throw out_of_range("invalid ptr"); return *curr; } int& CheckedPtr::operator[](const size_t index) { if(beg+index>=end||beg+index<beg) throw out_of_range("invalid index"); return *(beg+index); } const int& CheckedPtr::operator[](const size_t index) const { if(beg+index>=end||beg+index<beg) throw out_of_range("invalid index"); return *(beg+index); } bool operator==(const CheckedPtr& lhs,const CheckedPtr& rhs) { return lhs.beg == rhs.beg && lhs.end == rhs.end && lhs.curr == rhs.curr; } bool operator!=(const CheckedPtr& lhs,const CheckedPtr& rhs) { return !( lhs == rhs ); } bool operator>(const CheckedPtr& lhs,const CheckedPtr& rhs) { return lhs.beg == rhs.beg && lhs.end == rhs.end && lhs.curr > rhs.curr; } bool operator<(const CheckedPtr& lhs,const CheckedPtr& rhs) { return lhs.beg == rhs.beg && lhs.end == rhs.end && lhs.curr < rhs.curr; } bool operator>=(const CheckedPtr& lhs,const CheckedPtr& rhs) { return !( lhs.curr < rhs.curr ); } bool operator<=(const CheckedPtr& lhs,const CheckedPtr& rhs) { return !( lhs.curr > rhs.curr ); } int main() { int ia[]={1,2,3,4,5,6}; CheckedPtr c1(ia,ia+6); cout<<&(*c1)<<endl;//1的地址 cout<<&(*(++c1))<<endl;//2的地址 cout<<&(*(++c1))<<endl;//3的地址 cout<<&(*(++c1))<<endl;//4的地址 //cout<<&(*(c1++))<<endl;//是個臨時變量 cout<<*c1++<<endl; return 0; }
#include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> #include <list> #include <stdexcept> using namespace std; class GT_cls { public: GT_cls(const string a=""):str(a){} bool operator()(const string &s) { return (s>str); } private: string str; }; int main() { std::cout << " Input some words( ctrl + z to end ):" << std::endl; vector<string> text; string word; while ( std::cin >> word ) { text.push_back( word ); } // end of input the text std::cin.clear(); std::cout << " Then , input one given word:\t"; string givenWord; std::cin >> givenWord; vector<string>::iterator it = find_if( text.begin(), text.end(), GT_cls( givenWord )); if ( it != text.end() ) std::cout << "\n Then the first word in the text you input," << std::endl << " \twhich is bigger than the given word is:" << std::endl << "\t" << *it << std::endl; return 0; }
#include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> #include <list> #include <stdexcept> using namespace std; class Item_base { public: Item_base(const string &book="", double sales_price=0.0):isbn(book),price(sales_price){} string book() const{return isbn;} virtual double net_price(size_t n)const{return n*price;} virtual void print(ostream &os){os <<price;} virtual ~Item_base(){} private: string isbn; protected: double price; }; class Bulk_item:public Item_base { public: double net_price(size_t cnt)const { if(cnt>min_qty) return cnt*(1-discount)*price; else return cnt*price; } void print(ostream &os) { Item_base::print(ostream &os); os << " " << discount; } private: size_t min_qty; double discount; }; class Ltd_item:public Item_base { public: Led_item(const string& book="",double sales_price,size_t qty=0,double disc_rate=0):item_base(book,sales_price),max_qty(qty),discount(disc_rate){} double net_price(size_t cnt) const { if(cnt<max_qty) return cnt*(1-discount)*price; else return cnt*price-max_qty*discount*price; } private: size_t max_qty; double discount; }; int main() { return 0; }
派生類的構造函數與複製控制
#include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> #include <list> #include <stdexcept> using namespace std; //基類定義:Item_base class Item_base { public: Item_base(const string& book="",double sales_price=0):isbn(book),price(sales_price) { cout<<"Using Item_base's constructor"<<endl; } Item_base(const Item_base& bi) { isbn=bi.isbn; price=bi.price; cout<<"Using Item_base's copy constructor"<<endl; } string book() const { return isbn; } virtual double net_price(size_t n) const { cout<<"Using Item_base's net_price"<<endl; return price*n; } // friend ostream& operator<<(ostream&,const Item_base&); virtual ~Item_base() { cout<<"Using Item_base's destructor"<<endl; } private: string isbn; protected: double price; }; ostream& operator<<(ostream& os,const Item_base &ib) { os<<"Using operator<< (ostream&,Item_base&)"<<endl <<"Item_base's book():"<<ib.book()<<endl <<"Item_base's net_price():"<<ib.net_price(3)<<endl; return os; } //派生類定義:Bulk_item class Bulk_item:public Item_base { public: Bulk_item(const string& book,double sales_price,size_t qty=0,double disc=0): Item_base(book,sales_price),min_qty(qty),discount(disc) { cout<<"Using Bulk_item's constructor "<<endl; } Bulk_item(const Bulk_item& bi):Item_base(bi) { min_qty=bi.min_qty; discount=bi.discount; cout<<"Using Bulk_item's copy constructor"<<endl; } virtual double net_price(size_t cnt) const { cout<<"Using Bulk_item's net_price"<<endl; if(cnt>min_qty) return cnt*(1-discount)*price; else return cnt*price; } ~Bulk_item() { cout<<"Using Bulk_item's destructor "<<endl; } private: size_t min_qty; double discount; }; ostream& operator<<(ostream& os,const Bulk_item& bi) { os<<"Using operator<< (ostream&, Bulk_item&)"<<endl <<"Bulk_item's book():"<<bi.book()<<endl <<"Bulk_item's net_price():"<<bi.net_price(3)<<endl; return os; } int main() { Item_base* p=new Item_base("C++ Primer",42.00); Bulk_item* p222=new Bulk_item("How to program",42,1,0.2); cout<<*p<<endl; cout<<*p222<<endl; delete p; delete p222;//析構函數先刪除派生類的成員後刪除基礎類的成員 Item_base p11("C++ Primer",42.00); Bulk_item p22("How to program",42,1,0.2); cout<<p11<<endl; cout<<p22<<endl; Item_base base0("C++ Primer_0",50); Bulk_item bulk0("How to program_0",50,1,0.2); vector<Item_base> basket; basket.push_back(base0);//此處調用Item_base的複製構造函數 basket.push_back(bulk0);//此處調用Item_base的複製構造函數 生成一箇中間變量 傳遞給basket中元素 再刪除這個中間變量 double SumPrice=0; for (vector<Item_base>::iterator it=basket.begin();it!=basket.end();++it) { SumPrice+=(*it).net_price(3); } cout<<"\n\tthe sum price of the basket is :\t"<<SumPrice<<endl; vector<Item_base*> basket2; Item_base *p1=&base0; Item_base *p2=&bulk0; basket2.push_back(p1); basket2.push_back(p2); SumPrice = 0.0; for ( vector<Item_base*>::iterator it = basket2.begin(); it != basket2.end(); ++it ) { SumPrice += (*it)->net_price(3); } cout << "\n\tthe sum price of the basket is :\t" << SumPrice << endl; return 0; }
句柄類與繼承:item_base(基類)->Bulk_item(派生類)->sales_item(句柄類)->Basket(容器)
item_base(基類)&Bulk_item(派生類)
//item.h #ifndef ITEM_H #define ITEM_H #include <iostream> #include <string> using namespace std; //基類 class Item_base { public:句柄類與繼承 Item_base(const string& book="",double sales_price=0):isbn(book),price(sales_price) { cout<<"Using Item_base's constructor"<<endl; } Item_base(const Item_base& bi) { isbn=bi.isbn; price=bi.price; cout<<"Using Item_base's copy constructor"<<endl; } string book() const { return isbn; } virtual double net_price(size_t n) const { cout<<"Using Item_base's net_price"<<endl; return price*n; } virtual Item_base* clone() const { return new Item_base(*this); } // friend ostream& operator<<(ostream&,const Item_base&); virtual ~Item_base() { cout<<"Using Item_base's destructor"<<endl; } private: string isbn; protected: double price; }; ostream& operator<<(ostream& os,const Item_base &ib) { os<<"Using operator<< (ostream&,Item_base&)"<<endl <<"Item_base's book():"<<ib.book()<<endl <<"Item_base's net_price():"<<ib.net_price(3)<<endl; return os; } //打折的派生類 class Bulk_item:public Item_base { public: Bulk_item(const string& book,double sales_price,size_t qty=0,double disc=0):Item_base(book,sales_price),min_qty(qty),discount(disc) { cout<<"Using Bulk_item's constructor "<<endl; } Bulk_item(const Bulk_item& bi):Item_base(bi) { min_qty=bi.min_qty; discount=bi.discount; cout<<"Using Bulk_item's copy constructor"<<endl; } virtual double net_price(size_t cnt) const { cout<<"Using Bulk_item's net_price"<<endl; if(cnt>min_qty) return cnt*(1-discount)*price; else return cnt*price; } virtual Bulk_item* clone() const { return new Bulk_item(*this); } ~Bulk_item() { cout<<"Using Bulk_item's destructor "<<endl; } private: size_t min_qty; double discount; }; ostream& operator<<(ostream& os,const Bulk_item& bi) { os<<"Using operator<< (ostream&, Bulk_item&)"<<endl <<"Bulk_item's book():"<<bi.book()<<endl <<"Bulk_item's net_price():"<<bi.net_price(3)<<endl; return os; } #endif
sales_item(句柄類)
//sales_item #ifndef SALES_ITEM_H #define SALES_ITEM_H #include "item.h" class Sales_item { public: Sales_item():p(0),use(new size_t(1)){}//空的構造函數 Sales_item(const Item_base& item):p(item.clone()),use(new size_t(1)){}//用Item_base類的賦值構造函數 Sales_item(const Sales_item& i):p(i.p),use(i.use){++*use;}//複製構造函數 ~Sales_item(){decr_use();} Sales_item& operator=(const Sales_item&);//複製函數 const Item_base* operator->() const{if(p) return p;else throw logic_error("Unbound Sales_item");} const Item_base& operator*() const {if(p) return *p;else throw logic_error("Unbound Sales_item");} private: Item_base *p; size_t *use; void decr_use() { if(--*use==0) { delete p; delete use; } } }; Sales_item& Sales_item::operator=(const Sales_item &rhs) { ++*rhs.use; decr_use(); p=rhs.p; use=rhs.use; return *this; } #endif // SALES_ITEM_H
Basket(容器)
//basket.h #ifndef __BASKET_H_ #define __BASKET_H_ #include "sales_item.h" #include <set> inline bool compare(const Sales_item &lhs,const Sales_item& rhs) { return lhs->book()<rhs->book(); } class Basket { typedef bool (*Comp)(const Sales_item&, const Sales_item&); public: typedef multiset<Sales_item,Comp> set_type; typedef set_type::size_type size_type; typedef set_type::const_iterator const_iter; Basket():items(compare){} void add_item(const Sales_item& item){items.insert(item);} size_type size(const Sales_item& i) const {return items.count(i);} double total() const; private: multiset<Sales_item,Comp> items; }; double Basket::total() const { double sum=0; for(const_iter it=items.begin();it!=items.end();it=items.upper_bound(*it)) { size_t i=items.count(*it); cout<<i<<endl; sum+=(*it)->net_price(i); } return sum; } #endif
main.cpp
#include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <fstream> #include <list> #include <stdexcept> #include "basket.h" #include "sales_item.h" int main() { Basket basket; Sales_item item1 ( Bulk_item( "0-0001-0001-1", 99, 5, 0.5 )); //Sales_item item2 ( Bulk_item( "0-0001-0001-2", 50 )); //Sales_item item3 ( Bulk_item( "0-0001-0001-3", 59, 200, 0.3 )); //Sales_item item4 ( Bulk_item( "0-0001-0001-1", 99, 20, 0.2 )); basket.add_item(item1); //basket.add_item(item2); //basket.add_item(item3); //basket.add_item(item4); cout << basket.total() << endl; return 0; }
TextQuery.h
#pragma once #include <iostream> #include <string> #include <vector> #include <map> #include <fstream> #include <set> using namespace std; class TextQuery { public: typedef vector<string>::size_type line_no; void read_file(ifstream &is) { store_file(is);build_map(); } set<line_no> run_query(const string&) const; string text_line(line_no) const; line_no size() const { return lines_of_text.size(); } private: void store_file(ifstream&); void build_map(); vector<string> lines_of_text; map< string,set<line_no> > word_map; };
TextQuery.cpp
#include "TextQuery.h" #include <fstream> #include <sstream> using namespace std; void TextQuery::store_file(ifstream& is) { string line; while(getline(is,line)) { lines_of_text.push_back(line); } } void TextQuery::build_map() { for (line_no line_num=0;line_num!=lines_of_text.size();++line_num) { istringstream line(lines_of_text[line_num]); string word; while(line>>word) { word_map[word].insert(line_num);//word_map[word]==set } } } set<TextQuery::line_no> TextQuery::run_query(const string&query_word) const { map< string,set<line_no> >::const_iterator loc=word_map.find(query_word); if(loc==word_map.end()) return set<line_no>(); else return loc->second; } string TextQuery::text_line(line_no line) const { if(line<lines_of_text.size()) return lines_of_text[line]; }
Query.h
#include "TextQuery.h" #include <string> #include <set> #include <iostream> #include <fstream> using namespace std; /********************************class Query_Base***************************/ //private, abstract class acts as a base for concrete query types class Query_base { public: friend class Query; protected: typedef TextQuery::line_no line_no; virtual ~Query_base(){} private: virtual set<line_no> eval(const TextQuery&) const=0; virtual ostream& display(ostream& =cout) const=0; }; /********************************class Query***************************/ class Query { //typedef TextQuery::line_no line_no; public: Query(const string&); /****複製控制*****/ Query(const Query& c):q(c.q),use(c.use){++*use;} ~Query(){decr_use();} Query& operator=(const Query&); set<TextQuery::line_no> eval(const TextQuery& t) const { return q->eval(t); } ostream& display(ostream& os) const { return q->display(os); } friend Query operator~(const Query&); friend Query operator|(const Query&,const Query&); friend Query operator&(const Query&,const Query&); private: Query(Query_base *query):q(query),use(new size_t(1)){} Query_base* q; size_t* use; void decr_use() { if(--*use==0) { delete q; delete use; } } }; inline ostream& operator<<(ostream& os,const Query &q) { return q.display(os); } inline Query& Query::operator=(const Query& rhs) { ++*rhs.use; decr_use(); q=rhs.q; use=rhs.use; return *this; } /********************************class WordQuery***************************/ class WordQuery:public Query_base { public: friend class Query; private: WordQuery(const string& s):query_word(s){} set<line_no> eval(const TextQuery& t)const { return t.run_query(query_word); } ostream& display (ostream& os) const { return os<<query_word; } string query_word; }; inline Query::Query(const string& word): q(new WordQuery(word)), use(new std::size_t(1)) {} /********************************class NotQuery***************************/ class NotQuery:public Query_base { friend Query operator~(const Query&); private: NotQuery(Query q):query(q){} set<line_no> eval(const TextQuery&) const; ostream& display(ostream& os) const { return os<<"~("<<query<<")"; } const Query query; }; /********************************class BinaryQuery***************************/ class BinaryQuery:public Query_base { protected: BinaryQuery(Query left,Query right,string op):lhs(left),rhs(right),oper(op){} ostream& display(ostream &os) const { return os<<"("<<lhs<<" "<<oper<<" "<<rhs<<")"; } const Query lhs,rhs; const string oper; }; /********************************class AndQuery***************************/ class AndQuery:public BinaryQuery { friend Query operator&(const Query&,const Query&); AndQuery(Query left,Query right):BinaryQuery(left,right,"&"){} set<line_no> eval(const TextQuery&) const; }; /********************************class OrQuery***************************/ class OrQuery:public BinaryQuery { friend Query operator|(const Query&,const Query&); OrQuery(Query left,Query right):BinaryQuery(left,right,"|"){} set<line_no> eval(const TextQuery&) const; }; inline Query operator&(const Query &lhs,const Query &rhs) { return new AndQuery(lhs,rhs); } inline Query operator|(const Query &lhs,const Query &rhs) { return new OrQuery(lhs,rhs); } inline Query operator~(const Query &oper) { return new NotQuery(oper); }
Query.cpp
#include "Query.h" #include "TextQuery.h" #include <map> #include <algorithm> set<TextQuery::line_no> OrQuery::eval(const TextQuery& file) const { set<line_no> right=rhs.eval(file); set<line_no> ret_lines=lhs.eval(file); ret_lines.insert(right.begin(),right.end()); return ret_lines; } set<TextQuery::line_no> AndQuery::eval(const TextQuery& file) const { set<line_no> left=lhs.eval(file); set<line_no> right=rhs.eval(file); set<line_no> ret_lines; set_intersection(left.begin(),left.end(),right.begin(),right.end(),inserter(ret_lines,ret_lines.begin())); return ret_lines; } set<TextQuery::line_no> NotQuery::eval(const TextQuery& file) const { set<line_no> has_val=query.eval(file); set<line_no> ret_lines; for(TextQuery::line_no n=0;n!=file.size();++n) { if(has_val.find(n)==has_val.end()) ret_lines.insert(n); } return ret_lines; }
main.cpp
#include <iostream> #include "TextQuery.h" #include "Query.h" using namespace std; void print_result(const set<TextQuery::line_no>& locs, const string& sought, const TextQuery& file) { typedef set<TextQuery::line_no> line_nums; line_nums::size_type size = locs.size(); cout<<"\n"<<sought<<" occurs "<<size<<(size>1?" times ":"Time")<<endl; line_nums::const_iterator it = locs.begin(); for(; it!=locs.end(); ++it) cout<<(*it)+1<<"\t"<<file.text_line(*it)<<endl; } int main() { ifstream is("1.txt"); TextQuery tq; tq.read_file(is); Query q=Query("fiery")&Query("bird")|Query("wind"); set<TextQuery::line_no> locs=q.eval(tq); string s("((fiery & bird) | wind)"); print_result(locs,s,tq); // cout << "Hello world!" << endl; return 0; }
#include <iostream> #include <utility> #include <string> #include <vector> #include <map> #include <fstream> #include <sstream> #include <set> #include <algorithm> using namespace std; template <typename T> typename T::value_type frq(T first,T last) { size_t amount=0; T start=first; while(start!= last) { amount++; start++; } typedef vector <typename T::value_type> VecType; VecType vec(amount); typename VecType::iterator newFirst=vec.begin(); typename VecType::iterator newLast=vec.end(); uninitialized_copy( first, last, newFirst ); sort ( newFirst, newLast ); size_t maxOccu = 0, occu = 0; typename VecType::iterator preIter = newFirst; typename VecType::iterator maxOccuElement = newFirst; while( newFirst != newLast ) { if ( *newFirst != *preIter ) // 當前值與前一值不一樣 { if ( occu > maxOccu ) { maxOccu = occu; // 修改最大次數 maxOccuElement = preIter; // 修改指向當前出現最頻繁的值的迭代器 } occu = 0; } ++occu; preIter = newFirst; ++newFirst; } if ( occu > maxOccu ) { maxOccu = occu; maxOccuElement = preIter; } return *maxOccuElement; } template<typename T> int compare(const T&v1,const T& v2) { if(v1<v2) return -1; if(v1>v2) return 1; if(v1==v2) return 0; } template<typename T> inline T abs(const T& v1) { return v1>0?v1:-(v1); } template<typename T> inline testOstream(ostream& os,T v1) { os<<v1; } template <class Type> class Queue { public: Queue(); Type& front(); const Type& front() const; void push(const Type&); void pop(); bool empty() const; private: }; int main() { // cout << compare(1, 0) << endl; // string s1="hi",s2="world"; // cout<<compare(s1,s2)<<endl; // std::cout << "abs( s1) is:" << abs(false) << std::endl // << "abs( -3 ) is:" << abs( -3 ) << std::endl // << "abs( -8.6 ) is:" << abs( -8.6 ) << std::endl; // cout << " Test of testOstream( cout, 6 ):"; // testOstream( cout, 6 ); // cout << "\n Test of testOstream( cout, true ):\t"; // testOstream( cout, true ); // cout << "\n Test of testOstream( cout, 8.6 ):\t"; // testOstream( cout, 8.6 ); // cout << "\n Test of testOstream( cout, \"Good!\" ):\t";i.begin() // testOstream( cout, "Good!" ); // // ofstream outfile; // outfile.open("out.txt"); //// assert( outfile ); // cout << "\nTest of ofstream, Please check the file just create.\n"; // if ( !outfile ) // { // return NULL; // } // testOstream(outfile, "\n Test of testOstream( outfile, 6 ):"); // testOstream( outfile, 6 ); // testOstream(outfile, "\n Test of testOstream( outfile, true ):"); // testOstream( outfile, true ); // testOstream(outfile, "\n Test of testOstream( outfile, 8.6 ):"); // testOstream( outfile, 8.6 ); // testOstream(outfile, "\n Test of testOstream( outfile, \"Good!\" ):"); // testOstream( outfile, "Good!" ); // outfile.close(); // cout << endl; // // // stringstream oss; // cout << "\n Test of testOstream( oss, 6 )/( oss, true )/( oss, 8.6 )/( oss, \"Good!\"):" << endl; // testOstream( oss, 6 ); // testOstream( oss, "\n" ); // testOstream( oss, true ); // testOstream( oss, "\n" ); // testOstream( oss, 8.6 ); // testOstream( oss, "\n" ); // testOstream( oss, "Good!"); // testOstream( oss, "\n" ); // cout << oss.str() << endl; int ia[]={1,2,3,4,2,3,2,2,4,5,6,7,8}; vector<int> i(13); copy(ia,ia+13,i.begin()); cout<<frq(i.begin(),i.end()); return 1; }
#include <iostream> #include <utility> #include <string> #include <vector> #include <map> #include <fstream> #include <sstream> #include <set> #include <algorithm> #include <stdexcept> using namespace std; /***************************************************/ // template<class Iterator> // struct iterator_traits { // typedef typename Iterator::iterator_category iterator_category; // typedef typename Iterator::value_type value_type; // typedef typename Iterator::difference_type difference_type; // typedef typename Iterator::pointer pointer; // typedef typename Iterator::reference reference; // }; // template<class Type> // struct iterator_traits<Type*> { // typedef random_access_iterator_tag iterator_category; // typedef Type value_type; // typedef ptrdiff_t difference_type; // typedef Type *pointer; // typedef Type& reference; // }; // template<class Type> // struct iterator_traits<const Type*> { // typedef random_access_iterator_tag iterator_category; // typedef Type value_type; // typedef ptrdiff_t difference_type; // typedef const Type *pointer; // typedef const Type& reference; // }; //iterator_traits是一個類模板 它接受一個指針類型或者一個iterator類型, //這個traits(顯著的特色)保存了迭代器的類型以及其指針和地址 /***************************************************/ template<typename Iterator,typename Object> Iterator Find(Iterator v1,Iterator v2,const Object& s) { for(Iterator it=v1;it!=v2;++it) { if(*it==s) return it; } return v2; } template<typename T> T Find2(T v1,T v2,typename iterator_traits<T>::value_type s) { for(T it=v1;it!=v2;++it) { if(*it==s) return it; } return v2; } int main() { int ia[]={1,2,3,4,5,6,7}; vector<int> ip(ia,ia+6); cout<<*(Find2(ip.begin(),ip.end(),5))<<endl; cout<<*(Find2(ia,ia+6,5)); return 1; }
#include <iostream> #include <utility> #include <string> #include <vector> #include <map> #include <fstream> #include <sstream> #include <set> #include <algorithm> #include <stdexcept> using namespace std; template <typename T> void PrintValue(const vector<T>& v1) { typedef typename vector<T>::size_type sizet; for(sizet i=0;i!=v1.size();++i) { cout<<v1[i]<<" "; } } template <typename T> void PrintValue2(const vector<T>& v1) { typedef typename vector<T>::const_iterator iter; for(iter i=v1.begin();i!=v1.end();++i) { cout<<*i<<" "; } } int main() { int ia[]={1,2,3,4,5,6,7}; vector<int> ip(ia,ia+7); PrintValue2(ip); return 1; }
Exercise 16.16:
#include <iostream> #include <utility> #include <string> #include <vector> #include <map> #include <fstream> #include <sstream> #include <set> #include <algorithm> #include <stdexcept> using namespace std; template<typename T,size_t N> void print_array(T (&parm)[N]) { for (size_t i = 0; i != N; ++i) { cout<<parm[i]<<" "; } cout<<endl; } int main() { int ia[7]={1,2,3,4,5,6,7}; vector<int> ip(ia,ia+7); print_array(ia); return 1; }
#include <iostream> #include <utility> #include <string> #include <vector> #include <map> #include <fstream> #include <sstream> #include <set> #include <algorithm> using namespace std; template <class Type> class Queue;//Queue類聲明 /********************operator<<函數聲明********************/ template <class T> ostream& operator<<(ostream &os, const Queue<T> &q); /********************QueueItem類定義********************/ template <class Type> class QueueItem { friend class Queue<Type>; friend ostream& operator<< <Type> (ostream &, const Queue<Type> &); QueueItem (const Type&t):item(t),next(0) {} Type item; QueueItem* next; }; /********************Queue類定義********************/ template <class Type> class Queue { public: friend ostream& operator<< <Type>(ostream &, const Queue<Type> &); Queue():head(0),tail(0) {} Queue(const Queue& Q):head(0),tail(0) { copy_elems(Q); //複製構造 } Queue& operator=(const Queue&);//賦值構造 ~Queue() { destory(); //析構函數 } template<class It> Queue(It beg,It end):head(0),tail(0){copy_elems(beg,end);} template<class Iter> void assign(Iter,Iter); Type& front() { return head->item; } const Type& front() const { return head->item; } void push(const Type&);// void pop();// bool empty() const { return head==0; } private: QueueItem<Type> *head; QueueItem<Type> *tail; void destory();// void copy_elems(const Queue&);// template <class Iter> void copy_elems(Iter,Iter); }; /********************Queue類函數destory定義********************/ template <class Type> void Queue<Type>::destory() { while(!empty()) pop(); } /********************Queue類函數pop定義********************/ template <class Type> void Queue<Type>::pop() { QueueItem<Type>* p=head; head=head->next; delete p; } /********************Queue類函數push定義********************/ template <class Type> void Queue<Type>::push(const Type&val) { QueueItem<Type> *pt=new QueueItem<Type> (val); if(empty()) head=tail=pt; else { tail->next=pt; tail=pt; } } /********************Queue類函數copy_elems定義********************/ template<class Type> void Queue<Type>::copy_elems(const Queue& orig) { for(QueueItem<Type>* pt=orig.head; pt; pt=pt->next) { push(pt->item); } } /********************Queue類函數assign定義********************/ template<class T> template<class Iter> void Queue<T>::assign(Iter beg,Iter end) { destory(); copy_elems(beg,end); } /********************Queue類函數copy_elems定義********************/ template <class Type> template <class It> void Queue<Type>::copy_elems(It beg,It end) { while(beg!=end) { push(*beg); ++beg; } } /********************Queue類輸出函數opeator<<定義********************/ template <class Type> ostream& operator<<(ostream &os, const Queue<Type> &q) { os << "< "; QueueItem<Type> *p; for (p = q.head; p; p = p->next) os << p->item << " "; os <<">"; return os; } template<typename T> int compare(const T&v1,const T& v2) { if(v1<v2) return -1; if(v1>v2) return 1; if(v1==v2) return 0; } int main() { short a[4]={0,3,6,9}; Queue<int> qi(a,a+4); vector<int> vi(a,a+4); qi.assign(vi.begin(),vi.end()); Queue<int> xi(vi.begin(),vi.end());//xi被實例化 cout<<qi<<endl; cout<<xi<<endl; xi.pop(); cout<<xi<<endl; xi.push(3.1);//發生類型轉換 double 3.1->int 3 cout<<xi<<endl; cout<<compare<string>("Hi","World"); return 1; }
泛型句柄類: Handle 類行爲相似於指針:複製 Handle 對象將不會複製基礎對象,複製以後,兩個 Handle 對象將引用同一基礎對象。要建立 Handle 對象,用戶須要傳遞屬於由 Handle 管理的類型(或從該類型派生的類型)的動態分配對象的地址,今後刻起,Handle 將「擁有」這個對象。並且,一旦再也不有任意 Handle 對象與該對象關聯,Handle 類將負責刪除該對象。
#include <iostream> #include <utility> #include <string> #include <vector> #include <map> #include <fstream> #include <sstream> #include <set> #include <algorithm> #include <stdexcept> using namespace std; /**********************泛式句柄Handle類*************************/ template <class T> class Handle { public: Handle (T* p=0):ptr(p),use(new size_t(1)) {cout<<"Using Handle's Constructor;"<<endl;cout<<"The use is: "<<*use<<endl;} T& operator*();// T* operator->();// const T& operator*() const;// const T* operator->() const;// Handle (const Handle& h):ptr(h.ptr),use(h.use) { ++*use; //複製構造函數 cout<<"Using Handle's Copy Constructor;"<<endl; cout<<"The use is: "<<*use<<endl; } Handle& operator=(const Handle&);// ~Handle() { cout<<"Using Handle's Deconstructor;"<<endl; // cout<<"The use is: "<<*use<<endl; rem_ref(); } private: T* ptr; size_t* use; void rem_ref() { if(--*use==0) { cout<<"The use is: 0"<<endl; delete ptr; delete use; } } }; /**********************賦值操做符operator=*************************/ template<class T> inline Handle<T>& Handle<T>::operator=(const Handle& rhs) { ++*rhs.use; rem_ref(); ptr=rhs.ptr; use=rhs.use; cout<<"Using Handle's operator=;"<<endl; cout<<"The use is: "<<*use<<endl; return *this; } /**********************解引用操做符operator**************************/ template<class T> inline T& Handle<T>::operator*() { if(ptr) { return *ptr; } else throw runtime_error("dereference of unbound handle"); } /**********************取地址操做符operator->**************************/ template<class T> inline const T* Handle<T>::operator->() const { if(ptr) { return ptr; } else throw runtime_error("access through unbound handle"); } template<class T> inline const T& Handle<T>::operator*() const { if(ptr) { return *ptr; } else throw runtime_error("dereference of unbound handle"); } int main() { Handle<int> hp(new int(42)); { Handle<int> hp2=hp; cout<<*hp<<" "<<*hp2<<endl; *hp2=10; } cout<<*hp<<endl; return 1; }
#include <iostream> #include <utility> #include <string> #include <vector> #include <map> #include <fstream> #include <sstream> #include <set> #include <algorithm> #include <stdexcept> using namespace std; /**********************基類Item_base類*************************/ class Item_base { public://句柄類與繼承 Item_base(const string& book="",double sales_price=0):isbn(book),price(sales_price) { cout<<"Using Item_base's constructor"<<endl; } Item_base(const Item_base& bi) { isbn=bi.isbn; price=bi.price; cout<<"Using Item_base's copy constructor"<<endl; } string book() const { return isbn; } virtual double net_price(size_t n) const { cout<<"Using Item_base's net_price"<<endl; return price*n; } virtual Item_base* clone() const { return new Item_base(*this); } // friend ostream& operator<<(ostream&,const Item_base&); virtual ~Item_base() { cout<<"Using Item_base's destructor"<<endl; } private: string isbn; protected: double price; }; /**********************基類Item_base類輸出函數*************************/ ostream& operator<<(ostream& os,const Item_base &ib) { os<<"Using operator<< (ostream&,Item_base&)"<<endl <<"Item_base's book():"<<ib.book()<<endl <<"Item_base's net_price():"<<ib.net_price(3)<<endl; return os; } /**********************派生類Bulk_item類*************************/ class Bulk_item:public Item_base { public: Bulk_item(const string& book,double sales_price,size_t qty=0,double disc=0):Item_base(book,sales_price),min_qty(qty),discount(disc) { cout<<"Using Bulk_item's constructor "<<endl; } Bulk_item(const Bulk_item& bi):Item_base(bi) { min_qty=bi.min_qty; discount=bi.discount; cout<<"Using Bulk_item's copy constructor"<<endl; } virtual double net_price(size_t cnt) const { cout<<"Using Bulk_item's net_price"<<endl; if(cnt>min_qty) return cnt*(1-discount)*price; else return cnt*price; } virtual Bulk_item* clone() const { return new Bulk_item(*this); } ~Bulk_item() { cout<<"Using Bulk_item's destructor "<<endl; } private: size_t min_qty; double discount; }; /**********************派生類Bulk_item類的輸出函數*************************/ ostream& operator<<(ostream& os,const Bulk_item& bi) { os<<"Using operator<< (ostream&, Bulk_item&)"<<endl <<"Bulk_item's book():"<<bi.book()<<endl <<"Bulk_item's net_price():"<<bi.net_price(3)<<endl; return os; } /****************************************************************/ /**********************泛式句柄Handle類*************************/ template <class T> class Handle { public: Handle (T* p=0):ptr(p),use(new size_t(1)) { cout<<"Using Handle's Constructor;"<<endl; cout<<"The use is: "<<*use<<endl; } T& operator*();// T* operator->();// const T& operator*() const;// const T* operator->() const;// Handle (const Handle& h):ptr(h.ptr),use(h.use) { ++*use; //複製構造函數 cout<<"Using Handle's Copy Constructor;"<<endl; cout<<"The use is: "<<*use<<endl; } Handle& operator=(const Handle&);// ~Handle() { cout<<"Using Handle's Deconstructor;"<<endl; // cout<<"The use is: "<<*use<<endl; rem_ref(); } private: T* ptr; size_t* use; void rem_ref() { if(--*use==0) { cout<<"The use is: 0"<<endl; delete ptr; delete use; } } }; /**********************賦值操做符operator=*************************/ template<class T> inline Handle<T>& Handle<T>::operator=(const Handle& rhs) { ++*rhs.use; rem_ref(); ptr=rhs.ptr; use=rhs.use; cout<<"Using Handle's operator=;"<<endl; cout<<"The use is: "<<*use<<endl; return *this; } /**********************解引用操做符operator**************************/ template<class T> inline T& Handle<T>::operator*() { if(ptr) { return *ptr; } else throw runtime_error("dereference of unbound handle"); } /**********************取地址操做符operator->**************************/ template<class T> inline const T* Handle<T>::operator->() const { if(ptr) { return ptr; } else throw runtime_error("access through unbound handle"); } template<class T> inline const T& Handle<T>::operator*() const { if(ptr) { return *ptr; } else throw runtime_error("dereference of unbound handle"); } /**********************採用泛式句柄的Sales_item類*************************/ class Sales_item { public: Sales_item():h(){} Sales_item(const Item_base &item):h(item.clone()){} const Item_base& operator*()const {return *h;} const Item_base* operator->() const {return h.operator->();} private: Handle <Item_base> h; }; /**********************採用泛式句柄的Basket類*************************/ inline bool compare(const Sales_item &lhs,const Sales_item& rhs) { return lhs->book()<rhs->book(); } class Basket { typedef bool (*Comp)(const Sales_item&, const Sales_item&); public: typedef multiset<Sales_item,Comp> set_type; typedef set_type::size_type size_type; typedef set_type::const_iterator const_iter; Basket():items(compare){} void add_item(const Sales_item& item){items.insert(item);} size_type size(const Sales_item& i) const {return items.count(i);} double total() const; private: multiset<Sales_item,Comp> items; }; double Basket::total() const { double sum=0; for(const_iter it=items.begin();it!=items.end();it=items.upper_bound(*it)) { size_t i=items.count(*it); cout<<i<<endl; sum+=(*it)->net_price(i); } return sum; } int main() { Basket basket; Sales_item item1 ( Bulk_item( "0-0001-0001-1", 99, 5, 0.5 )); //Sales_item item2 ( Bulk_item( "0-0001-0001-2", 50 )); //Sales_item item3 ( Bulk_item( "0-0001-0001-3", 59, 200, 0.3 )); //Sales_item item4 ( Bulk_item( "0-0001-0001-1", 99, 20, 0.2 )); basket.add_item(item1); //basket.add_item(item2); //basket.add_item(item3); //basket.add_item(item4); cout <<"The total is: "<<basket.total() << endl; return 1; }
#include <iostream> #include <utility> #include <string> #include <cstring> #include <vector> #include <map> #include <fstream> #include <sstream> #include <set> #include <algorithm> #include <stdexcept> using namespace std; /*****************************函數模板Count****************************/ template<typename Type> int Count(vector<Type> const &v1,Type const &v2) { cout<<"Calling Count's general version:"<<endl; int sum=0; for(size_t i=0; i!=v1.size(); ++i) { if(v1[i]==v2) ++sum; } return sum; } /**********************函數模板Count的string特化*************************/ template<> int Count( vector<string> const& v1,string const& v2) { cout<<"Calling Count's string version:"<<endl; int sum=0; for(size_t i=0; i!=v1.size(); ++i) { if(v1[i]==v2) ++sum; } return sum; } /**************************函數模板Compare******************************/ template<typename T> int compare(const T &v1, const T &v2) { cout<<"Calling Compare's general version:"<<endl; if (v1 < v2) return -1; if (v2 < v1) return 1; return 0; } /*******************函數模板Compare的const char*特化**********************/ template <> int compare<const char*>(const char* const &v1, const char* const &v2) { cout<<"Calling Compare's const char* version:"<<endl; return strcmp(v1, v2); } int main() { int ia[]= {1,2,3,5,5,3,4,5,6,7}; double ib[]= {23.6,23.4,52.2}; string ic[]= {"ibg","wings","EG"}; vector<int> ip(ia,ia+10); vector<double> ig(ib,ib+3); vector<string> istr(ic,ic+3); cout<<Count(ip,5)<<endl; cout<<Count(ig,23.6)<<endl; cout<<Count(istr,string("EG"))<<endl; /*zhihu*/ const char *cp1 = "world", *cp2 = "hi"; char * const cp3 = "world", *cp4 = "hi"; int i2, i1; compare(i1, i2); compare(cp1, cp2); // 這個地方匹配成了通用模板很讓我費解 compare(cp3, cp4); return 1; }
優化內存分配:
#include <iostream> #include <utility> #include <string> #include <cstring> #include <vector> #include <map> #include <fstream> #include <sstream> #include <set> #include <algorithm> #include <stdexcept> #include <memory> using namespace std; template<class T> class Vector { public: Vector():first_free(0),end(0),element(0){} void push_back(T t) { if(first_free==end) { reallocate(); } alloc.construct(first_free,t); //new (first_free)T (t); first_free++; } T& operator[](size_t s) { if(s>first_free-element) { throw out_of_range("下標越界!"); } else { return element[s]; } } const T& operator[](size_t s)const { if(s>first_free-element) { throw out_of_range("下標越界!"); } else { return element[s]; } } size_t size() { return first_free-element; } size_t capacity() { return end-element; } void reserve(size_t n) { size_t Capacity=capacity(); if(n>0) { if(Capacity<n) { T* newelement=alloc.allocate(n);//在堆上開闢空間 uninitialized_copy(element,first_free,newelement); for (T *p = first_free; p != element; /* empty */ )//調用T的析構函數,將原有空間的元素撤銷 { alloc.destroy(--p); //p->~T();//顯式調用析構函數。 } if(element) { alloc.deallocate(element,end-element);//將原有空間歸還給系統 //operator delete (element);//使用operator delete釋放空間。 } element=newelement; first_free=element+size(); end=element+n; } } else { throw runtime_error("n<0!"); } } // void resize(size_t n) // { // size_t Size=size(); // size_t Capacity=capacity(); // if(n<Size) // { // for (T *p = first_free;p!=element+n; /* empty */ )//調用T的析構函數,將原有空間的元素撤銷 // { // alloc.destroy(--p); // //p->~T();//顯式調用析構函數。 // } // first_free=element+n+1; // } // else // { // if(n>Capacity) // { // std::ptrdiff_t num=first_free-element;//原有vector的size // std::ptrdiff_t newcapacity = 2 * max(n, 1);//capacity增長成2*size // T* newelement=alloc.allocate(newcapacity);//在堆上開闢空間 // //newelement=static_cast<T*>(operator new(2*num*sizeof(T)));//調用operator new申請空間。 // for() // uninitialized_copy(element,first_free,newelement);//將原有的元素複製到現有空間上 // for (T *p = first_free; p != element; /* empty */ )//調用T的析構函數,將原有空間的元素撤銷 // { // alloc.destroy(--p); // //p->~T();//顯式調用析構函數。 // } // if(element) // { // alloc.deallocate(element,end-element);//將原有空間歸還給系統 // //operator delete (element);//使用operator delete釋放空間。 // } // // element=newelement; // first_free=element+num; // end=element+newcapacity; // } // else // { // // } // } // } private: void reallocate() { std::ptrdiff_t num=first_free-element;//原有vector的size std::ptrdiff_t newcapacity = 2 * max(num, 1);//capacity增長成2*size T* newelement=alloc.allocate(newcapacity);//在堆上開闢空間 //newelement=static_cast<T*>(operator new(2*num*sizeof(T)));//調用operator new申請空間。 uninitialized_copy(element,first_free,newelement);//將原有的元素複製到現有空間上 for (T *p = first_free; p != element; /* empty */ )//調用T的析構函數,將原有空間的元素撤銷 { alloc.destroy(--p); //p->~T();//顯式調用析構函數。 } if(element) { alloc.deallocate(element,end-element);//將原有空間歸還給系統 //operator delete (element);//使用operator delete釋放空間。 } element=newelement; first_free=element+num; end=element+newcapacity; } private: allocator<T> alloc; // T* newelement; T* first_free; T* end; T* element; }; int main() { Vector<int> vi; try { for(int i=0; i<20; i++) { vi.push_back(i+5); } for(int i=0; i<20; i++) { cout<<i+1<<": "<<vi[i]<<endl; } cout<<vi[28]<<endl; } catch (exception &e) { cout<<e.what()<<endl; } vi.reserve(20); cout<<vi.capacity()<<endl; vector<int> pi(20); pi.push_back(2); cout<<pi.capacity()<<endl; return 1; }
Example:
#include<iostream> #include<stdexcept> using namespace std; template<typename T> class MemoryAllocate { public: MemoryAllocate() { } void *operator new(size_t s) { if(s!=sizeof(T)) throw runtime_error("傳入的類型大小不符!"); if(!freeList) { T*array=alloc.allocate(num); for(size_t i=0;i<num;i++) { addToFreeList(array+i); } } T*p=freeList; freeList=freeList->next; return p; } void operator delete(void*s) { T*p=static_cast<T*>(s); addToFreeList(p); cout<<"DELETE函數被調用 "<<endl;//這句話被輸出了,說明此函數被調用了。可是爲什麼沒法跟進呢???20120530 21:22 } virtual ~MemoryAllocate() { } private: static void addToFreeList(T*t) { t->next=freeList; freeList=t; } private: static T*freeList; static T*next; static allocator<T> alloc; static size_t num; }; template<typename T> T*MemoryAllocate<T>::freeList=NULL; template<typename T> size_t MemoryAllocate<T>::num=10; template<typename T> T*MemoryAllocate<T>::next=NULL; template<typename T> allocator<T> MemoryAllocate<T>::alloc; class Derived:public MemoryAllocate<Derived> { public: Derived() { i=0; } int i; }; int main(int argc,char**argv) { try { Derived *mai=new Derived; Derived *p=new Derived; delete mai; delete p; } catch (exception& e) { cout<<e.what()<<endl; } return 0; }
Associativity and Operator | Function | Use | See Page | |
L | :: | global scope(全局做用域) | :: name | p. 450 |
L | :: | class scope(類做用域) | class :: name | p. 85 |
L | :: | namespace scope(名字空間做用域) | namespace :: name | p. 78 |
L | . | member selectors(成員選擇) | object . member | p. 25 |
L | -> | member selectors(成員選擇) | pointer -> member | p. 164 |
L | [] | subscript(下標) | variable [ expr ] | p. 113 |
L | () | function call(函數調用) | name (expr_list) | p. 25 |
L | () | type construction(類型構造) | type (expr_list) | p. 460 |
R | ++ | postfix increment(後自增操做) | lvalue++ | p. 162 |
R | -- | postfix decrement(後自減操做) | lvalue-- | p. 162 |
R | typeid | type ID(類型 ID) | typeid (type) | p. 775 |
R | typeid | run-time type ID(運行時類型 ID) | typeid (expr) | p. 775 |
R | explicit cast(顯式強制類型轉換) | type conversion(類型轉換) | cast_name
|
p. 183 |
R | sizeof | size of object(對象的大小) | sizeof expr | p. 167 |
R | sizeof | size of type(類型的大小) | sizeof(type) | p. 167 |
R | ++ | prefix increment(前自增操做) | ++ lvalue | p. 162 |
R | -- | prefix decrement(前自減操做) | -- lvalue | p. 162 |
R | ~ | bitwise NOT(位求反) | ~expr | p. 154 |
R | ! | logical NOT(邏輯非) | !expr | p. 152 |
R | - | unary minus(一元負號) | -expr | p. 150 |
R | + | unary plus(一元正號) | +expr | p. 150 |
R | * | dereference(解引用) | *expr | p. 119 |
R | & | address-of(取地址) | &expr | p. 115 |
R | () | type conversion(類型轉換) | (type) expr | p. 186 |
R | new | allocate object(建立對象) | new type | p. 174 |
R | delete | deallocate object(釋放對象) | delete expr | p. 176 |
R | delete[] | deallocate array(釋放數組) | delete[] expr | p. 137 |
L | ->* | ptr to member select(指向成員操做的指針) | ptr ->* ptr_to_member | p. 783 |
L | .* | ptr to member select(指向成員操做的指針) | obj .*ptr_to_member | p. 783 |
L | * | multiply(乘法) | expr * expr | p. 149 |
L | / | divide(除法) | expr / expr | p. 149 |
L | % | modulo (remainder)(求模(求餘)) | expr % expr | p. 149 |
L | + | add(加法) | expr + expr | p. 149 |
L | - | subtract(減法) | expr - expr | p. 149 |
L | << | bitwise shift left(位左移) | expr << expr | p. 154 |
L | >> | bitwise shift right(位右移) | expr >> expr | p. 154 |
L | < | less than(小於) | expr < expr | p. 152 |
L | <= | less than or equal(小於或等於) | expr <= expr | p. 152 |
L | > | greater than(大於) | expr > expr | p. 152 |
L | >= | greater than or equal(大於或等於) | expr >= expr | p. 152 |
L | == | equality(相等) | expr == expr | p. 152 |
L | != | inequality(不等) | expr != expr | p. 152 |
L | & | bitwise AND(位與) | expr & expr | p. 154 |
L | ^ | bitwise XOR() | expr ^ expr | p. 154 |
L | | | bitwise OR(位異或) | expr | expr | p. 154 |
L | && | logical AND(邏輯與) | expr && expr | p. 152 |
L | || | logical OR(邏輯或) | expr || expr | p. 152 |
R | ?: | conditional(條件操做) | expr ? expr : expr | p. 165 |
R | = | assignment(賦值操做) | lvalue = expr | p. 159 |
R | *=, /=, %=, | compound assign(複合賦值操做) | lvalue += expr, etc. | p. 159 |
R | +=, -=, | p. 159 | ||
R | <<=, >>=, | p. 159 | ||
R | &=,|=, ^= | p. 159 | ||
R | throw | throw exception(拋出異常) | throw expr | p. 216 |
L | , | comma(逗號) | expr , expr | p. 168 |