久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

读书笔记之:C++ Primer (第4版)及习题(ch12-ch18) [++++]

發布時間:2025/5/22 c/c++ 150 豆豆
生活随笔 收集整理的這篇文章主要介紹了 读书笔记之:C++ Primer (第4版)及习题(ch12-ch18) [++++] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第12章 類

1. 類的聲明與定義:前向聲明,不完全類型

2. 從const函數返回*this

3. 可變數據成員mutable

4. 用于const對象的構造函數:構造函數不能聲明為const

5. 構造函數初始化式

構造函數的執行分為兩個階段:初始化階段和普通的計算階段

6. 構造函數初始化列表

7. 默認實參與構造函數

8. 類通常定義一個默認構造函數,不然的話使用起來會很麻煩。

9. 使用默認構造函數

10. 隱式類類型轉換:使用explicit來杜絕隱式類類型的轉換

11. 類成員的顯式初始化,這種顯式初始化的方式是從C繼承來的

12. static類成員

13. static成員函數

14. static成員變量

?

第13章 復制控制

1.C++中的復制控制

2. 復制構造函數

3. 合成復制構造函數

?

4. 禁止復制

?

5. 智能指針,引用計數

智能指針的實現:

View Code #include?<iostream>
#include?<string>
#include?<cstddef>
using?namespace?std;

class?U_Ptr?{
????friend?class?HasPtr;
????int?*ip;
????size_t?use;
????U_Ptr(int?*p):?ip(p),?use(1)?{?}
????~U_Ptr()?{?delete?ip;?}
};

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;?}
????HasPtr&?operator=(const?HasPtr&);

????~HasPtr()?{?if?(--ptr->use?==?0)?delete?ptr;?}?

????friend?ostream&?operator<<(ostream&,?const?HasPtr&);

????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?i)?{?*ptr->ip?=?i;?}
private:
????U_Ptr?*ptr;????????
????int?val;
};

HasPtr&?HasPtr::operator=(const?HasPtr?&rhs)
{
????++rhs.ptr->use;?????
????if?(--ptr->use?==?0)
?????????delete?ptr;????
????ptr?=?rhs.ptr;??????
????val?=?rhs.val;??????
????return?*this;
}

ostream&?operator<<(ostream?&os,?const?HasPtr?&hp)
{
????os?<<?"*ptr:?"?<<?hp.get_ptr_val()?<<?"\tval:?"?<<?hp.get_int()?<<?endl;
????return?os;
}

int?main()
{
????int?obj?=?0;

????HasPtr?ptr1(&obj,?42);
????HasPtr?ptr2(ptr1);
????cout?<<?"(1)?ptr1:?"?<<?ptr1?<<?endl?<<?"ptr2:?"?<<?ptr2?<<?endl;

????ptr1.set_ptr_val(42);?
????ptr2.get_ptr_val();???

????cout?<<?"(2)?ptr1:?"?<<?ptr1?<<?endl?<<?"ptr2:?"?<<?ptr2?<<?endl;

????ptr1.set_int(0);???
????ptr2.get_int();????
????ptr1.get_int();????

????cout?<<?"(3)?ptr1:?"?<<?ptr1?<<?endl?<<?"ptr2:?"?<<?ptr2?<<?endl;
}

?

第14章 重載操作符與轉換

1.可重載的操作符與不可重載的操作符

不要重載具有內置含義的操作符

定義為成員函數或非成員函數

2. 輸出操作符重載

3. 函數對象的函數適配器:綁定器與求反器

?

4. 轉換操作符重載

?

5. 習題

?

第15章 面向對象編程

1. 動態綁定virtual,從派生類到基類的轉換

2. C++中的多態性

3. 虛函數與默認實參

4. 轉換與繼承

5. 派生類到基類的轉換

5.1 引用轉換不同于對象轉換

5.2 派生類對象對基類對象的初始化或賦值:切割

6. 從基類到派生類的轉換


7. 復制控制和繼承

8. 虛析構函數

9. 構造函數和賦值操作符不是虛函數:構造函數不能定義為虛函數,而賦值操作符定義為虛函數的話會令人混淆。

10. 構造函數和析構函數中的虛函數

11. 名字查找與繼承

12. 容器與繼承

容器中如果定義保存基類,那么派生類對象會被切割,如果定義為保持派生類,那么會產生很大問題。

13. 句柄類與繼承

指針型句柄

一個例子如下:

View Code #include?<iostream>
#include?<iostream>
#include?<string>
#include?<set>
#include?<map>
#include?<utility>
#include?<cstddef>
#include?<stdexcept>
#include?<algorithm>
using?namespace?std;

class?Item_base?{
friend?std::istream&?operator>>(std::istream&,?Item_base&);
friend?std::ostream&?operator<<(std::ostream&,?const?Item_base&);
public:
????virtual?Item_base*?clone()?const?{?return?new?Item_base(*this);?}
public:
????Item_base(const?std::string?&book?=?"",?double?sales_price?=?0.0):
?????????????????????isbn(book),?price(sales_price)?{?}

????std::string?book()?const?{?return?isbn;?}

????virtual?double?net_price(std::size_t?n)?const?{?return?n?*?price;?}

????virtual?~Item_base()?{?}?
private:
????std::string?isbn;???
protected:
????double?price;???????

};

class?Bulk_item?:?public?Item_base?{
public:
????std::pair<size_t,?double>?discount_policy()?const
????????{?return?std::make_pair(min_qty,?discount);?}
????Bulk_item*?clone()?const?
????????{?return?new?Bulk_item(*this);?}
????Bulk_item():?min_qty(0),?discount(0.0)?{?}
????Bulk_item(const?std::string&?book,?double?sales_price,?
??????????????std::size_t?qty?=?0,?double?disc_rate?=?0.0):
?????????????????Item_base(book,?sales_price),?
?????????????????min_qty(qty),?discount(disc_rate)?{?}

????double?net_price(std::size_t?cnt)?const
????{
????????if?(cnt?>=?min_qty)
????????????return?cnt?*?(1?-?discount)?*?price;
????????else
????????????return?cnt?*?price;
????}
private:
????std::size_t?min_qty;???
????double?discount;??????
};

class?Lim_item?:?public?Item_base?{
public:
????Lim_item(const?std::string&?book?=?"",?double?sales_price?=?0.0,
?????????????std::size_t?qty?=?0,?double?disc_rate?=?0.0):
?????????????????Item_base(book,?sales_price),?
?????????????????max_qty(qty),?discount(disc_rate)?{?}

????double?net_price(std::size_t?cnt)?const
????{
????????size_t?discounted?=?min(cnt,?max_qty);
????????size_t?undiscounted?=?cnt?-?discounted;
????????return?discounted?*?(1?-?discount)?*?price?
????????????+?undiscounted?*?price;
????}
private:
????std::size_t?max_qty;???
????double?discount;???????
public:
????Lim_item*?clone()?const?{?return?new?Lim_item(*this);?}
????std::pair<size_t,?double>?discount_policy()?const
????????{?return?std::make_pair(max_qty,?discount);?}
};

class?Sales_item?{
friend?class?Basket;
friend?bool?compare(const?Sales_item&?lhs,const?Sales_item&?rhs);
public:
????Sales_item():?p(0),?use(new?std::size_t(1))?{?}

????Sales_item(const?Item_base&?item):p(item.clone()),?use(new?std::size_t(1))?{?}?

????Sales_item(const?Sales_item?&i):?
??????????????????????p(i.p),?use(i.use)?{?++*use;?}
????~Sales_item()?{?decr_use();?}
????Sales_item&?operator=(const?Sales_item&?rhs)?{
????????++*rhs.use;
????????decr_use();
????????p?=?rhs.p;
????????use?=?rhs.use;
????????return?*this;
????}

????const?Item_base?*operator->()?const?{?if?(p)?return?p;?
????????else?throw?std::logic_error("unbound?Sales_item");?}
????const?Item_base?&operator*()?const?{?if?(p)?return?*p;?
????????else?throw?std::logic_error("unbound?Sales_item");?}
private:
????Item_base?*p;?????????
????std::size_t?*use;?????

????void?decr_use()?
?????????{?if?(--*use?==?0)?{?delete?p;?delete?use;?}?}
};

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?std::multiset<Sales_item,?Comp>?set_type;

????typedef?set_type::size_type?size_type;
????typedef?set_type::const_iterator?const_iter;

????void?display(std::ostream&)?const;

????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:
????std::multiset<Sales_item,?Comp>?items;
};

void?Basket::display(ostream?&os)?const
{
????os?<<?"Basket?size:?"?<<?items.size()?<<?endl;

????for?(const_iter?next_item?=?items.begin();?next_item?!=?items.end();
??????????????????next_item?=?items.upper_bound(*next_item))?{
????????os?<<?(*next_item)->book()?<<?"?occurs?"?
???????????<<?items.count(*next_item)?<<?"?times"?
???????????<<?"?for?a?price?of?"?
???????????<<?(*next_item)->net_price(items.count(*next_item))?
???????????<<?endl;
????}
}
void?print_total(ostream?&os,?const?Item_base?&item,?size_t?n)?{
????os?<<?"ISBN:?"?<<?item.book()?//?calls?Item_base::book
???????<<?"\tnumber?sold:?"?<<?n?<<?"\ttotal?price:?"
???????<<?item.net_price(n)?<<?endl;
}
double?Basket::total()?const
{
????double?sum?=?0.0;????//?holds?the?running?total?
????for?(const_iter?iter?=?items.begin();?iter?!=?items.end();
????????????????????iter?=?items.upper_bound(*iter))?{
????????print_total(cout,?*(iter->p),?items.count(*iter));
????????sum?+=?(*iter)->net_price(items.count(*iter));
????}
????return?sum;
}

int?main()
{
????Sales_item?item1(Item_base("123",?45));
????Sales_item?item2(Bulk_item("345",?45,?3,?.15));
????Sales_item?item3(Bulk_item("678",?55,?5,?.25));
????Sales_item?item4(Lim_item("abc",?35,?2,?.10));
????Sales_item?item5(Item_base("def",?35));

????Basket?sale;
????sale.add_item(item1);
cout?<<?"added?first?item"?<<?endl;
????sale.add_item(item1);
????sale.add_item(item1);
????sale.add_item(item1);
????sale.add_item(item2);
????sale.add_item(item2);
????sale.add_item(item2);
????sale.add_item(item2);
????sale.add_item(item2);
????sale.add_item(item2);
????sale.add_item(item2);
????sale.add_item(item2);
????sale.add_item(item3);
????sale.add_item(item3);
????sale.add_item(item3);
????sale.add_item(item3);
????sale.add_item(item3);
????sale.add_item(item3);
????sale.add_item(item3);
????sale.add_item(item3);
????sale.add_item(item4);
????sale.add_item(item4);
????sale.add_item(item4);
????sale.add_item(item4);
????sale.add_item(item4);
????sale.add_item(item4);
????sale.add_item(item5);
????sale.add_item(item5);
cout?<<?"added?last?item"?<<?endl;

????sale.display(cout);
????cout?<<?sale.total()?<<?endl;
{
????//?arguments?are?the?isbn,?price,?minimum?quantity,?and?discount
????Bulk_item?bulk("0-201-82470-1",?50,?5,?.19);
????Basket?sale;
????sale.add_item(Bulk_item("0-201-82470-1",?50,?5,?.19));
????sale.add_item(Bulk_item("0-201-82470-1",?50,?5,?.19));
????sale.add_item(Bulk_item("0-201-82470-1",?50,?5,?.19));
????sale.add_item(Bulk_item("0-201-82470-1",?50,?5,?.19));
????sale.add_item(Bulk_item("0-201-82470-1",?50,?5,?.19));
????sale.add_item(Lim_item("0-201-54848-8",?35,?2,?.10));
????sale.add_item(Lim_item("0-201-54848-8",?35,?2,?.10));
????sale.add_item(Lim_item("0-201-54848-8",?35,?2,?.10));
????double?total?=?sale.total();
????cout?<<?"Total?Sale:?"?<<?total?<<?endl;
}
}

?

?

輸出如下:

?

14. 文本查詢

在原來的基礎上添加了~,& 和| 來進行組合查詢。

代碼如下:

View Code #include?<iostream>
#include?<set>
#include?<map>
#include?<vector>
#include?<string>
#include?<algorithm>
#include?<fstream>
using?namespace?std;

class?TextQuery
{
public:
????typedef?string::size_type?str_size;
????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;
????void?display_map();
????str_size?size()const?{
????????return?lines_of_text.size();
????}
private:
????void?store_file(ifstream&);
????void?build_map();
private:
????vector<string>?lines_of_text;
????map<string,set<line_no>?>?word_map;
????static?string?sep;
????static?string?cleanup_str(const?string&);
};

string?TextQuery::sep("?\t\n\v\r\f,.`~!@#$%^&*-+=()[]{}<>;:\\/?\'\"|");
void?TextQuery::store_file(ifstream&?is)
{
????string?textline;
????while(getline(is,textline))
????????????lines_of_text.push_back(textline);

}
void?TextQuery::build_map()
{
????string?line;
????string?word;
????for(line_no?num=0;num!=lines_of_text.size();++num)
????{
????????line=lines_of_text[num];
????????string::size_type?pos=0,pos2=0;
????????while((pos2=line.find_first_not_of(sep,pos))
????????????????!=string::npos){
????????????pos=line.find_first_of(sep,pos2);
????????????if(pos!=string::npos){
????????????????word=line.substr(pos2,pos-pos2);
????????????}
????????????else{
????????????????word=line.substr(pos2);
????????????}
????????????word_map[word].insert(num);
????????}
????}
}
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?"line_number?out?of?range";
}
void?TextQuery::display_map()
{
????map<string,set<line_no>?>::iterator?iter=word_map.begin(),
????????iter_end=word_map.end();
????for(;iter!=iter_end;++iter)
????{
????????cout<<"word:?"<<iter->first<<"?{";
????????const?set<line_no>&text_locs=iter->second;
????????set<line_no>::const_iterator?loc_iter=text_locs.begin(),
????????????loc_iter_end=text_locs.end();
????????while(loc_iter!=loc_iter_end)
????????{
????????????cout<<*loc_iter;
????????????if(++loc_iter!=loc_iter_end)
????????????????cout<<",?";
????????}
????????cout<<"}\n";
????}
????cout<<endl;
}
string?TextQuery::cleanup_str(const?string?&word)
{
????string?ret;
????for(string::const_iterator?it=word.begin();it!=word.end();++it)
????{
????????if(!ispunct(*it))
????????????ret+=tolower(*it);
????}
????return?ret;
}
string?make_plural(size_t?ctr,?const?string?&word,const?string?&ending)
{
????return?(ctr?==?1)???word?:?word?+?ending;
}
class?Query_base?{
????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?{
????friend?Query?operator~(const?Query?&);
????friend?Query?operator|(const?Query&,?const?Query&);
????friend?Query?operator&(const?Query&,?const?Query&);
public:
????Query(const?string&);??
????Query(const?Query?&c):?q(c.q),?use(c.use)?{?++*use;?}
????~Query()?{?decr_use();?}
????Query&?operator=(const?Query&rhs)?{
????????++*rhs.use;?
????????decr_use();?
????????q?=?rhs.q;?
????????use?=?rhs.use;?
????????return?*this;?
????}

????set<TextQuery::line_no>?eval(const?TextQuery?&t)?const?{?return?q->eval(t);?}
????ostream?&display(ostream?&os)?const?{?return?q->display(os);?}
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;?}?}
};

ostream&?operator<<(ostream?&os,?const?Query?&q)?{
????return?q.display(os);
}

class?WordQuery:?public?Query_base?{
????friend?class?Query;?
????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?&s):?q(new?WordQuery(s)),?use(new?size_t(1))?{?}

class?NotQuery:?public?Query_base?{
????friend?Query?operator~(const?Query?&);
????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:?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:?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:?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);
}

set<TextQuery::line_no>
NotQuery::eval(const?TextQuery&?file)?const
{
????set<TextQuery::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;
}

set<TextQuery::line_no>
AndQuery::eval(const?TextQuery&?file)?const
{
????set<line_no>?left?=?lhs.eval(file),?
?????????????????right?=?rhs.eval(file);

????set<line_no>?ret_lines;??//?destination?to?hold?results?

????set_intersection(left.begin(),?left.end(),?
??????????????????right.begin(),?right.end(),
??????????????????inserter(ret_lines,?ret_lines.begin()));
????return?ret_lines;
}

set<TextQuery::line_no>
OrQuery::eval(const?TextQuery&?file)?const
{
????set<line_no>?right?=?rhs.eval(file),
?????????????ret_lines?=?lhs.eval(file);??//?destination?to?hold?results

????ret_lines.insert(right.begin(),?right.end());

????return?ret_lines;
}

TextQuery?build_textfile(const?char*?filename)
{
????//?get?a?file?to?read?from?which?user?will?query?words
????ifstream?infile;
????infile.open(filename);
????if?(!infile)?{
????????cerr?<<?"No?input?file!"?<<?endl;
????????return?TextQuery();
????}

????TextQuery?ret;
????ret.read_file(infile);??//?builds?query?map
????return?ret;??//?builds?query?map
}

void?print_results(const?set<TextQuery::line_no>&?locs,?const?TextQuery?&file)
{
????//?report?no?matches
????if?(locs.empty())?{
????????cout?<<?"\nSorry.?There?are?no?entries?for?your?query."?
?????????????<<?"\nTry?again."?<<?endl;
????????return;
????}

????//?if?the?word?was?found,?then?print?count?and?all?occurrences
????set<TextQuery::line_no>::size_type?size?=?locs.size();
????cout?<<?"match?occurs?"?
?????????<<?size?<<?(size?==?1???"?time:"?:?"?times:")?<<?endl;

????//?print?each?line?in?which?the?word?appeared
????set<TextQuery::line_no>::const_iterator?it?=?locs.begin();
????for?(?;?it?!=?locs.end();?++it)?{
????????cout?<<?"\t(line?"
?????????????//?don't?confound?user?with?text?lines?starting?at?0
?????????????<<?(*it)?+?1?<<?")?"
?????????????<<?file.text_line(*it)?<<?endl;
????}
}
string&?trim(string&?s){
????if(s.empty())
????????return?s;
????s.erase(0,s.find_first_not_of('?'));
????s.erase(s.find_last_not_of('?')+1);
????return?s;
}

int?main(int?argc,char**argv){
????TextQuery?file?=?build_textfile(argv[1]);

????string?sought;
????while(true){
????cout?<<?"enter?a?word(s)?to?search?for,?or?q?to?quit:?";
????getline(cin,sought);
????if(!cin||sought=="q")
????????break;
????string::size_type?pos;
????if((pos=sought.find('~'))!=string::npos){

????????sought=sought.substr(pos+1);
????????trim(sought);
????????Query?name(sought);
????????Query?notq?=?~name;
????????const?set<TextQuery::line_no>?locs?=?notq.eval(file);
????????cout?<<?"\nExecuted?Query?for:?"?<<?notq?<<?endl;

????????print_results(locs,?file);
????}
????else?if((pos=sought.find('&'))!=string::npos){
????????string?sought1,?sought2;
????????sought1=sought.substr(0,pos);
????????trim(sought1);
????????sought2=sought.substr(pos+1);
????????trim(sought2);
????????cout<<"sought1="<<sought1<<"?sought2="<<sought2<<endl;
????
????????Query?andq?=?Query(sought1)?&?Query(sought2);
????????set<TextQuery::line_no>?locs?=?andq.eval(file);
????????cout?<<?"\nExecuted?query:?"?<<?andq?<<?endl;
????????print_results(locs,?file);
????
????????locs?=?Query(sought1).eval(file);
????????cout?<<?"\nExecuted?query:?"?<<?Query(sought1)?<<?endl;
????????print_results(locs,?file);
????
????????locs?=?Query(sought2).eval(file);
????????cout?<<?"\nExecuted?query:?"?<<?Query(sought2)?<<?endl;
????????print_results(locs,?file);
????}
????else?if((pos=sought.find('|'))!=string::npos){
????????string?sought1,?sought2;
????????sought1=sought.substr(0,pos);
????????trim(sought1);
????????sought2=sought.substr(pos+1);
????????trim(sought2);
????????cout<<"sought1="<<sought1<<"?sought2="<<sought2<<endl;
????????Query?orq?=?Query(sought1)?|?Query(sought2);
????????cout?<<?"\nExecuting?Query?for:?"?<<?orq?<<?endl;
????????const?set<TextQuery::line_no>?locs?=?orq.eval(file);

????????print_results(locs,?file);

????}
????else{
????????trim(sought);
????????Query?name(sought);
????????const?set<TextQuery::line_no>?locs?=?name.eval(file);
????????cout?<<?"\nExecuted?Query?for:?"?<<?name?<<?endl;

????????print_results(locs,?file);
????}

????}
????return?0;
}

?

簡單的運行結果如下:

第16章 模板與泛型編程

1. typename與class

只能使用typename來聲明在類內部定義的類型成員。

2. 非類型模板參數

模板形參不一定都是類型。

template?<class?T,size_t?N>
void?array_init(T?(&parm)[N]){
for(size_t?i=0;i!=N;++i)
parm[i]=0;
}

int?main(){
int?x[42];
double?y[10];
array_init(x);
array_init(y);
}

可以使用非類型模板來確定數組的長度。

template?<class?T,size_t?N>
size_t?size(T?(&parm)[N]){?????
????return?N;
}

?

3. 模板實例化

在模板實參推斷期間確定模板實參的類型和值。

?

4. 模板推斷過程中涉及的函數實參允許的類型轉換

?

5.應用于非模板形參的常規轉換

6. 模板實參推斷與函數指針

可以使用函數模板對函數指針進行初始化或賦值,這樣做的時候,編譯器使用指針的類型實例化具有適當模板實參的模板版本。

例如,假定有一個函數指針指向返回 int 值的函數,該函數接受兩個形參,都是 const int 引用,可以用該指針指向 compare 的實例化

template?<typename?T>?int?compare(const?T&,?const?T&);
?????//?pf1?points?to?the?instantiation?int?compare?(const?int&,?const?int&)
?????int?(*pf1)?(const?int&,?const?int&)?=?compare;

?

pf1 的類型是一個指針,指向"接受兩個 const int& 類型形參并返回 int 值的函數",形參的類型決定了 T 的模板實參的類型,T 的模板實參為 int 型,指針 pf1 引用的是將 T 綁定到 int 的實例化。

????獲取函數模板實例化的地址的時候,上下文必須是這樣的:它允許為每個模板形參確定唯一的類型或值。

如果不能從函數指針類型確定模板實參,就會出錯。例如,假定有兩個名為 func 的函數,每個函數接受一個指向函數實參的指針。func 的第一個版本接受有兩個 const string 引用形參并返回 string 對象的函數的指針,func 的第二個版本接受帶兩個 const int 引用形參并返回 int 值的函數的指針,不能使用 compare 作為傳給 func 的實參:

//?overloaded?versions?of?func;?each?take?a?different?function?pointer?type
?????void?func(int(*)?(const?string&,?const?string&));
?????void?func(int(*)?(const?int&,?const?int&));
?????func(compare);?//?error:?which?instantiation?of?compare?

?

?

問題在于,通過查看 func 的形參類型不可能確定模板實參的唯一類型,對 func 的調用可以實例化下列函數中的任意一個:

compare(const?string&,?const?string&)
?????compare(const?int&,?const?int&)

?

?

因為不能為傳給 func 的實參確定唯一的實例化,該調用會產生一個編譯時(或鏈接時)錯誤。

7. 函數模板的顯式實參

(1) 指定顯式模板實參

(2)在返回類型中使用類型形參

(3)顯式實參與函數模板的指針

?

8. 非類型形參的模板實參

9. 類模板中的友元聲明
在類模板中可以出現三種友元聲明,每一種都聲明了與一個或多個實體友元關系:

(1) 普通非模板類或函數的友元聲明,將友元關系授予明確指定的類或函數。

(2) 類模板或函數模板的友元聲明,授予對友元所有實例的訪問權。

(3) 類模板或函數模板的特定實例的訪問權的友元聲明。

10. 成員模板

任意類(模板或非模板)可以擁有本身為類模板或函數模板的成員,這種成員稱為成員模板,成員模板不能為虛。

11. 類模板的static成員

?

12. 模板特化

函數模板特化

?

13. 類模板特化

類模板的部分特化

如果類模板有一個以上的模板形參,我們也許想要特化某些模板形參而非全部。使用類模板的部分特化可以做到這一點:

template?<class?T1,?class?T2>
?????class?some_template?{
?????????//?...
?????};
?????//?partial?specialization:?fixes?T2?as?int?and?allows?T1?to?vary
?????template?<class?T1>
?????class?some_template<T1,?int>?{
?????????//?...
?????};

?

類模板的部分特化本身也是模板。部分特化的定義看來像模板定義,這種定義以關鍵字 template 開頭,接著是由尖括號(<>)括住的模板形參表。部分特化的模板形參表是對應的類模板定義形參表的子集。some_template 的部分特化只有一個名為 T1 的模板類型形參,第二個模板形參 T2 的實參已知為 int。部分特化的模板形參表只列出未知模板實參的那些形參。

部分特化的定義與通用模板的定義完全不會沖突。部分特化可以具有與通用類模板完全不同的成員集合。類模板成員的通用定義永遠不會用來實例化類模板部分特化的成員。

?

14. 重載與函數模板

確定重載函數模板的調用

可以在不同類型上調用這些函數:

//?calls?compare(const?T&,?const?T&)?with?T?bound?to?int
?????compare(1,?0);
?????//?calls?compare(U,?U,?V),?with?U?and?V?bound?to?vector<int>::iterator
?????vector<int>?ivec1(10),?ivec2(20);
?????compare(ivec1.begin(),?ivec1.end(),?ivec2.begin());
?????int?ia1[]?=?{0,1,2,3,4,5,6,7,8,9};
?????//?calls?compare(U,?U,?V)?with?U?bound?to?int*
?????
//?and?V?bound?to?vector<int>::iterator
?????compare(ia1,?ia1?+?10,?ivec1.begin());
?????//?calls?the?ordinary?function?taking?const?char*?parameters
?????const?char?const_arr1[]?=?"world",?const_arr2[]?=?"hi";
?????compare(const_arr1,?const_arr2);
?????//?calls?the?ordinary?function?taking?const?char*?parameters
?????char?ch_arr1[]?=?"world",?ch_arr2[]?=?"hi";
?????compare(ch_arr1,?ch_arr2);

?

下面依次介紹每個調用。

compare(1, 0):兩個形參都是 int 類型。候選函數是第一個模板將 T 綁定到 int 的實例化,以及名為 compare 的普通函數。但該普通函數不可行——不能將 int 對象傳給期待 char* 對象的形參。用 int 實例化的函數與該調用完全匹配,所以選擇它。

compare(ivec1.begin(), ivec1.end(), ivec2.begin())

compare(ia1, ia1 + 10, ivec1.begin()):

這兩個調用中,唯一可行的函數是有三個形參的模板的實例化。帶兩個參數的模板和普通非模板函數都不能匹配這兩個調用。

compare(const_arr1, const_arr2): 這個調用正如我們所期待的,調用普通函數。該函數和將 T 綁定到 const char* 的第一個模板都是可行的,也都完全匹配。根據規則 3b,會選擇普通函數。從候選集合中去掉模板實例,只剩下普通函數可行。

compare(ch_arr1, ch_arr2):這個調用也綁定到普通函數。候選者是將 T 綁定到 char* 的函數模板的版本,以及接受 const char* 實參的普通函數,兩個函數都需要稍加轉換將數組 ch_arr1 和 ch_arr2 轉換為指針。因為兩個函數一樣匹配,所以普通函數優先于模板版本。

?

第17章 用于大型程序的工具

1. 拋出類類型的異常

異常是通過拋出對象而引發的。該對象的類型決定應該激活哪個處理代碼。被選中的處理代碼是調用鏈中與該對象類型匹配且離拋出異常位置最近的那個。

異常以類似于將實參傳遞給函數的方式拋出和捕獲。異常可以是可傳給非引用形參的任意類型的對象,這意味著必須能夠復制該類型的對象。

回憶一下,傳遞數組或函數類型實參的時候,該實參自動轉換為一個指針。被拋出的對象將發生同樣的自動轉換,因此,不存在數組或函數類型的異常。相反。相反,如果拋出一個數組,被拋出的對象轉換為指向數組首元素的指針,類似地,如果拋出一個函數,函數被轉換為指向該函數的指針第 7.9 節。

執行 throw 的時候,不會執行跟在 throw 后面的語句,而是將控制從 throw 轉移到匹配的 catch,該 catch 可以是同一函數中局部的 catch,也可以在直接或間接調用發生異常的函數的另一個函數中。控制從一個地方傳到另一地方,這有兩個重要含義:

1. 沿著調用鏈的函數提早退出。第 17.1.2 節將討論函數因異常而退出時會發生什么。

2. 一般而言,在處理異常的時候,拋出異常的塊中的局部存儲不存在了。

因為在處理異常的時候會釋放局部存儲,所以被拋出的對象就不能再局部存儲,而是用 throw 表達式初始化一個稱為異常對象的特殊對象。異常對象由編譯器管理,而且保證駐留在可能被激活的任意 catch 都可以訪問的空間。這個對象由 throw 創建,并被初始化為被拋出的表達式的副本。異常對象將傳給對應的 catch,并且在完全處理了異常之后撤銷。

異常對象通過復制被拋出表達式的結果創建,該結果必須是可以復制的類型

?

2. 異常對象與繼承

當拋出一個表達式的時候,被拋出對象的靜態編譯時類型將決定異常對象的類型。

通常,使用靜態類型拋出對象不成問題。當拋出一個異常的時候,通常在拋出點構造將拋出的對象,該對象表示出了什么問題,所以我們知道確切的異常類型。

3. 異常與指針

用拋出表達式拋出靜態類型時,比較麻煩的一種情況是,在拋出中對指針解引用。對指針解引用的結果是一個對象,其類型與指針的類型匹配。如果指針指向繼承層次中的一種類型,指針所指對象的類型就有可能與指針的類型不同。無論對象的實際類型是什么,異常對象的類型都與指針的靜態類型相匹配。如果該指針是一個指向派生類對象的基類類型指針,則那個對象將被分割,只拋出基類部分。

?

如果拋出指針本身,可能會引發比分割對象更嚴重的問題。具體而言,拋出指向局部對象的指針總是錯誤的,其理由與從函數返回指向局部對象的指針是錯誤的一樣。拋出指針的時候,必須確定進入處理代碼時指針所指向的對象存在。

?

如果拋出指向局部對象的指針,而且處理代碼在另一函數中,則執行處理代碼時指針所指向的對象將不再存在。即使處理代碼在同一函數中,也必須確信指針所指向的對象在 catch 處存在。如果指針指向某個在 catch 之前退出的塊中的對象,那么,將在 catch 之前撤銷該局部對象。

?

4. 棧展開Stack Unwinding

拋出異常的時候,將暫停當前函數的執行,開始查找匹配的 catch 子句。首先檢查 throw 本身是否在 try 塊內部,如果是,檢查與該 catch 相關的 catch 子句,看是否其中之一與拋出對象相匹配。如果找到匹配的 catch,就處理異常;如果找不到,就退出當前函數(釋放當前函數的內在并撤銷局部對象),并且繼續在調用函數中查找。

如果對拋出異常的函數的調用是在 try 塊中,則檢查與該 try 相關的 catch 子句。如果找到匹配的 catch,就處理異常;如果找不到匹配的 catch,調用函數也退出,并且繼續在調用這個函數的函數中查找。

這個過程,稱之為棧展開(stack unwinding),沿嵌套函數調用鏈繼續向上,直到為異常找到一個 catch 子句。只要找到能夠處理異常的 catch 子句,就進入該 catch 子句,并在該處理代碼中繼續執行。當 catch 結束的時候,在緊接在與該 try 塊相關的最后一個 catch 子句之后的點繼續執行。

(1)為局部對象調用析構函數

棧展開期間,提早退出包含 throw 的函數和調用鏈中可能的其他函數。一般而言,這些函數已經創建了可以在退出函數時撤銷的局部對象。因異常而退出函數時,編譯器保證適當地撤銷局部對象。每個函數退出的時候,它的局部存儲都被釋放,在釋放內存之前,撤銷在異常發生之前創建的所有對象。如果局部對象是類類型的,就自動調用該對象的析構函數。通常,編譯器不撤銷內置類型的對象。

棧展開期間,釋放局部對象所用的內存并運行類類型局部對象的析構函數。

如果一個塊直接分配資源,而且在釋放資源之前發生異常,在棧展開期間將不會釋放該資源。例如,一個塊可以通過調用 new 動態分配內存,如果該塊因異常而退出,編譯器不會刪除該指針,已分配的內在將不會釋放。

由類類型對象分配的資源一般會被適當地釋放。運行局部對象的析構函數,由類類型對象分配的資源通常由它們的析構函數釋放。第 17.1.8 節說明面對異常使用類管理資源分配的編程技術

(2)析構函數應該從不拋出異常

棧展開期間會經常執行析構函數。在執行析構函數的時候,已經引發了異常但還沒有處理它。如果在這個過程中析構函數本身拋出新的異常,又會發生什么呢?新的異常應該取代仍未處理的早先的異常嗎?應該忽略析構函數中的異常嗎?

答案是:在為某個異常進行棧展開的時候,析構函數如果又拋出自己的未經處理的另一個異常,將會導致調用標準庫 terminate 函數。一般而言,terminate 函數將調用 abort 函數,強制從整個程序非正常退出。

因為 terminate 函數結束程序,所以析構函數做任何可能導致異常的事情通常都是非常糟糕的主意。在實踐中,因為析構函數釋放資源,所以它不太可能拋出異常。標準庫類型都保證它們的析構函數不會引發異常。

(3)異常與構造函數

與析構函數不同,構造函數內部所做的事情經常會拋出異常。如果在構造函數對象的時候發生異常,則該對象可能只是部分被構造,它的一些成員可能已經初始化,而另一些成員在異常發生之前還沒有初始化。即使對象只是部分被構造了,也要保證將會適當地撤銷已構造的成員。

類似地,在初始化數組或其他容器類型的元素的時候,也可能發生異常,同樣,也要保證將會適當地撤銷已構造的元素。

(4)未捕獲的異常終止程序

不能不處理異常。異常是足夠重要的、使程序不能繼續正常執行的事件。如果找不到匹配的 catch,程序就調用庫函數 terminate。

?

5. 捕獲異常

catch 子句中的異常說明符看起來像只包含一個形參的形參表,異常說明符是在其后跟一個(可選)形參名的類型名。

說明符的類型決定了處理代碼能夠捕獲的異常種類。類型必須是完全類型,即必須是內置類型或者是已經定義的程序員自定義類型。類型的前向聲明不行。

?

當 catch 為了處理異常只需要了解異常的類型的時候,異常說明符可以省略形參名;如果處理代碼需要已發生異常的類型之外的信息,則異常說明符就包含形參名,catch 使用這個名字訪問異常對象。

(1)查找匹配的處理代碼

在查找匹配的 catch 期間,找到的 catch 不必是與異常最匹配的那個 catch,相反,將選中第一個找到的可以處理該異常的 catch。因此,在 catch 子句列表中,最特殊的 catch 必須最先出現。

異常與 catch 異常說明符匹配的規則比匹配實參和形參類型的規則更嚴格,大多數轉換都不允許——除下面幾種可能的區別之外,異常的類型與 catch 說明符的類型必須完全匹配:

*允許從非 const 到 const 的轉換。也就是說,非 const 對象的 throw 可以與指定接受 const 引用的 catch 匹配。

*允許從派生類型型到基類類型的轉換。

*將數組轉換為指向數組類型的指針,將函數轉換為指向函數類型的適當指針。

在查找匹配 catch 的時候,不允許其他轉換。具體而言,既不允許標準算術轉換,也不允許為類類型定義的轉換。

(2)異常說明符

進入 catch 的時候,用異常對象初始化 catch 的形參。像函數形參一樣,異常說明符類型可以是引用。異常對象本身是被拋出對象的副本。是否再次將異常對象復制到 catch 位置取決于異常說明符類型。

如果說明符不是引用,就將異常對象復制到 catch 形參中,catch 操作異常對象的副本,對形參所做的任何改變都只作用于副本,不會作用于異常對象本身。如果說明符是引用,則像引用形參一樣,不存在單獨的 catch 對象,catch 形參只是異常對象的另一名字。對 catch 形參所做的改變作用于異常對象。

(3)異常說明符與繼承

像形參聲明一樣,基類的異常說明符可以用于捕獲派生類型的異常對象,而且,異常說明符的靜態類型決定 catch 子句可以執行的動作。如果被拋出的異常對象是派生類類型的,但由接受基類類型的 catch 處理,那么,catch 不能使用派生類特有的任何成員。

通常,如果 catch 子句處理因繼承而相關的類型的異常,它就應該將自己的形參定義為引用。

如果 catch 形參是引用類型,catch 對象就直接訪問異常對象,catch 對象的靜態類型可以與 catch 對象所引用的異常對象的動態類型不同。如果異常說明符不是引用,則 catch 對象是異常對象的副本,如果 catch 對象是基類類型對象而異常對象是派生類型的,就將異常對象分割(第 15.3.1 節)為它的基類子對象。

而且,正如第 15.2.4 節所介紹的,對象(相對于引用)不是多態的。當通過對象而不是引用使用虛函數的時候,對象的靜態類型和動態類型相同,函數是虛函數也一樣。只有通過引用或指針調用時才發生動態綁定,通過對象調用不進行動態綁定。

(4)catch子句的次序必須反映類型層次

將異常類型組織成類層次的時候,用戶可以選擇應用程序處理異常的粒度級別。例如,只希望清除并退出的應用程序可以定義一個 try 塊,該 try 塊包圍 main 函數中帶有如下 catch 代碼:

catch(exception?&e)?{
????????//?do?cleanup
????????
//?print?a?message
????????cerr?<<?"Exiting:?"?<<?e.what()?<<?endl;
????????size_t?status_indicator?=?42;??//?set?and?return?an
????????return(status_indicator);??????//?error?indicator
????}

有更嚴格實時需求的程序可能需要更好的異常控制,這樣的應用程序將清除導致異常的一切并繼續執行。

因為 catch 子句按出現次序匹配,所以使用來自繼承層次的異常的程序必須將它們的 catch 子句排序,以便派生類型的處理代碼出現在其基類類型的 catch 之前。

?

6. 重新拋出

一般而言,catch 可以改變它的形參。在改變它的形參之后,如果 catch 重新拋出異常,那么,只有當異常說明符是引用的時候,才會傳播那些改變。

catch?(my_error?&eObj)?{????????//?specifier?is?a?reference?type
????????eObj.status?=?severeErr;????//?modifies?the?exception?object
????????throw;?//?the?status?member?of?the?exception?object?is?severeErr
????}?catch?(other_error?eObj)?{????//?specifier?is?a?nonreference?type
????????eObj.status?=?badErr;???????//?modifies?local?copy?only
????????throw;?//?the?status?member?of?the?exception?rethrown?is?unchanged
????}

?

?

7. 捕獲所有異常的代碼

即使函數不能處理被拋出的異常,它也可能想要在隨拋出異常退出之前執行一些動作。除了為每個可能的異常提供特定 catch 子句之外,因為不可能知道可能被拋出的所有異常,所以可以使用捕獲所有異常 catch 子句的。捕獲所有異常的 catch 子句形式為 (...)。例如:

//?matches?any?exception?that?might?be?thrown
?????catch?(...)?{
?????????//?place?our?code?here
?????}

?

8. 標準異常類

9. 自動資源釋放

用類管理資源分配。

對析構函數的運行導致一個重要的編程技術的出現,它使程序更為異常安全的。異常安全的意味著,即使發生異常,程序也能正確操作。在這種情況下,"安全"來自于保證"如果發生異常,被分配的任何資源都適當地釋放"。

通過定義一個類來封閉資源的分配和釋放,可以保證正確釋放資源。這一技術常稱為"資源分配即初始化",簡稱 RAII。

應該設計資源管理類,以便構造函數分配資源而析構函數釋放資源。想要分配資源的時候,就定義該類類型的對象。如果不發生異常,就在獲得資源的對象超出作用域的進修釋放資源。更為重要的是,如果在創建了對象之后但在它超出作用域之前發生異常,那么,編譯器保證撤銷該對象,作為展開定義對象的作用域的一部分。

?

10. auto_ptr類

位于頭文件memory中,智能指針

auto_ptr 只能用于管理從 new 返回的一個對象,它不能管理動態分配的數組。

正如我們所見,當 auto_ptr 被復制或賦值的時候,有不尋常的行為,因此,不能將 auto_ptrs 存儲在標準庫容器類型中。

auto_ptr 對象只能保存一個指向對象的指針,并且不能用于指向動態分配的數組,使用 auto_ptr 對象指向動態分配的數組會導致未定義的運行時行為。

每個 auto_ptr 對象綁定到一個對象或者指向一個對象。當 auto_ptr 對象指向一個對象的時候,可以說它"擁有"該對象。當 auto_ptr 對象超出作用域或者另外撤銷的時候,就自動回收 auto_ptr 所指向的動態分配對象。

(1)為異常安全的內存分配使用 auto_ptr

如果通過常規指針分配內在,而且在執行 delete 之前發生異常,就不會自動釋放該內存:

void?f()
?????{
????????int?*ip?=?new?int(42);?????//?dynamically?allocate?a?new?object
????????
//?code?that?throws?an?exception?that?is?not?caught?inside?f
????????delete?ip;?????????????????//?return?the?memory?before?exiting
?????}

?

如果在 new 和 delete 之間發生異常,并且該異常不被局部捕獲,就不會執行 delete,則永不回收該內存。

如果使用一個 auto_ptr 對象來代替,將會自動釋放內存,即使提早退出這個塊也是這樣:

void?f()
?????{
????????auto_ptr<int>?ap(new?int(42));?//?allocate?a?new?object
????????
//?code?that?throws?an?exception?that?is?not?caught?inside?f
?????}?????//?auto_ptr?freed?automatically?when?function?ends

?

在這個例子中,編譯器保證在展開棧越過 f 之前運行 ap 的析構函數。

?

(2)auto_ptr 是可以保存任何類型指針的模板

auto_ptr 類是接受單個類型形參的模板,該類型指定 auto_ptr 可以綁定的對象的類型,因此,可以創建任何類型的 auto_ptrs:

auto_ptr<string>?ap1(new?string("Brontosaurus"));

?

(3)將 auto_ptr 綁定到指針

在最常見的情況下,將 auto_ptr 對象初始化為由 new 表達式返回的對象的地址:

auto_ptr<int>?pi(new?int(1024));

這個語句將 pi 初始化為由 new 表達式創建的對象的地址,這個 new 表達式將對象初始化為 1024。

接受指針的構造函數為 explicit(第 12.4.4 節)構造函數,所以必須使用初始化的直接形式來創建 auto_ptr 對象:

//?error:?constructor?that?takes?a?pointer?is?explicit?and?can't?be?used?implicitly
auto_ptr<int>?pi?=?new?int(1024);
auto_ptr<int>?pi(new?int(1024));?//?ok:?uses?direct?initialization

pi 所指的由 new 表達式創建的對象在超出作用域時自動刪除。如果 pi 是局部對象,pi 所指對象在定義 pi 的塊的末尾刪除;如果發生異常,則 pi 也超出作用域,析構函數將自動運行 pi 的析構函數作為異常處理的一部分;如果 pi 是全局對象,就在程序末尾刪除 pi 引用的對象。

(4)使用 auto_ptr 對象

auto_ptr 類定義了解引用操作符(*)和箭頭操作符(->)的重載版本(第 14.6 節),因為 auto_ptr 定義了這些操作符,所以可以用類似于使用內置指針的方式使用 auto_ptr 對象:

?

//?normal?pointer?operations?for?dereference?and?arrow
*ap1?=?"TRex";?//?assigns?a?new?value?to?the?object?to?which?ap1?points
string?s?=?*ap1;?//?initializes?s?as?a?copy?of?the?object?to?which?ap1?points
if?(ap1->empty())?//?runs?empty?on?the?string?to?which?ap1?points

auto_ptr 的主要目的,在保證自動刪除 auto_ptr 對象引用的對象的同時,支持普通指針式行為。正如我們所見,自動刪除該對象這一事實導致在怎樣復制和訪問它們的地址值方面,auto_ptrs 與普通指針明顯不同。

(5)auto_ptr 對象的復制和賦值是破壞性操作

auto_ptr 和內置指針對待復制和賦值有非常關鍵的重要區別。當復制 auto_ptr 對象或者將它的值賦給其他 auto_ptr 對象的時候,將基礎對象的所有權從原來的 auto_ptr 對象轉給副本,原來的 auto_ptr 對象重置為未綁定狀態。

?

(6)賦值刪除左操作數指向的對象

除了將所有權從右操作數轉給左操作數之外,賦值還刪除左操作數原來指向的對象——假如兩個對象不同。通常自身賦值沒有效果。

auto_ptr<string>?ap3(new?string("Pterodactyl"));
//?object?pointed?to?by?ap3?is?deleted?and?ownership?transferred?from?ap2?to?ap3;
ap3?=?ap2;?//?after?the?assignment,?ap2?is?unbound

因為復制和賦值是破壞性操作,所以auto_ptrs不能將 auto_ptr 對象存儲在標準容器中。標準庫的容器類要求在復制或賦值之后兩個對象相等,auto_ptr 不滿足這一要求,如果將 ap2 賦給 ap1,則在賦值之后 ap1 != ap2,復制也類似。

(7)auto_ptr 的默認構造函數

如果不給定初始式,auto_ptr 對象是未綁定的,它不指向對象:

auto_ptr<int>?p_auto;?//?p_autodoesn't?refer?to?any?object

?

默認情況下,auto_ptr 的內部指針值置為 0。對未綁定的 auto_ptr 對象解引用,其效果與對未綁定的指針解引用相同——程序出錯并且沒有定義會發生什么:

*p_auto?=?1024;?//?error:?dereference?auto_ptr?that?doesn't?point?to?an?object

?

(8)測試 auto_ptr 對象

auto_ptr 類型沒有定義到可用作條件的類型的轉換,相反,要測試 auto_ptr 對象,必須使用它的 get 成員,該成員返回包含在 auto_ptr 對象中的基礎指針:

//?revised?test?to?guarantee?p_auto?refers?to?an?object
if?(p_auto.get())
*p_auto?=?1024;

使用 get 成員初始化其他 auto_ptr 對象違反 auto_ptr 類設計原則:在任意時刻只有一個 auto_ptrs 對象保存給定指針,如果兩個 auto_ptrs 對象保存相同的指針,該指針就會被 delete 兩次。

(9)reset 操作

auto_ptr 對象與內置指針的另一個區別是,不能直接將一個地址(或者其他指針)賦給 auto_ptr 對象:

p_auto?=?new?int(1024);?//?error:?cannot?assign?a?pointer?to?an?auto_ptr

?

相反,必須調用 reset 函數來改變指針:

//?revised?test?to?guarantee?p_auto?refers?to?an?object
if?(p_auto.get())
*p_auto?=?1024;
else
//?reset?p_auto?to?a?new?object
p_auto.reset(new?int(1024));

要復位 auto_ptr 對象,可以將 0 傳給 reset 函數。

?

11. auto_ptr的缺陷

auto_ptr 類模板為處理動態分配的內存提供了安全性和便利性的尺度。要正確地使用 auto_ptr 類,必須堅持該類強加的下列限制:

1.不要使用 auto_ptr 對象保存指向靜態分配對象的指針,否則,當 auto_ptr 對象本身被撤銷的時候,它將試圖刪除指向非動態分配對象的指針,導致未定義的行為。

2.永遠不要使用兩個 auto_ptr 對象指向同一對象,導致這個錯誤的一種明顯方式是,使用同一指針來初始化或者 reset 兩個不同的 auto_ptr 對象。另一種導致這個錯誤的微妙方式可能是,使用一個 auto_ptr 對象的 get 函數的結果來初始化或者 reset 另一個 auto_ptr 對象。

3.不要使用 auto_ptr 對象保存指向動態分配數組的指針。當 auto_ptr 對象被刪除的時候,它只釋放一個對象——它使用普通 delete 操作符,而不用數組的 delete [] 操作符。

4.不要將 auto_ptr 對象存儲在容器中。容器要求所保存的類型定義復制和賦值操作符,使它們表現得類似于內置類型的操作符:在復制(或者賦值)之后,兩個對象必須具有相同值,auto_ptr 類不滿足這個要求。

?

12. 異常說明
異常說明跟在函數形參表之后。一個異常說明在關鍵字 throw 之后跟著一個(可能為空的)由圓括號括住的異常類型列表。

空說明列表指出函數不拋出任何異常:

void no_problem() throw();

異常說明是函數接口的一部分,函數定義以及該函數的任意聲明必須具有相同的異常說明。

如果一個函數聲明沒有指定異常說明,則該函數可以拋出任意類型的異常。

(1)違反異常說明

如果函數拋出了沒有在其異常說明中列出的異常,就調用標準庫函數 unexpected。默認情況下,unexpected 函數調用 terminate 函數,terminate 函數一般會終止程序。

(2)確定函數不拋出異常

異常說服有用的一種重要情況是,如果函數可以保證不會拋出任何異常。

確定函數將不拋出任何異常,對函數的用戶和編譯器都有所幫助:知道函數不拋出異常會簡化編寫調用該函數的異常安全的代碼的工作,我們可以知道在調用函數時不必擔心異常,而且,如果編譯器知道不會拋出異常,它就可以執行被可能拋出異常的代碼所抑制的優化。

(3)異常說明與成員函數

像非成員函數一樣,成員函數聲明的異常說明跟在函數形參表之后。例如,C++ 標準庫中的 bad_alloc 類定義為所有成員都有空異常說明,這些成員承諾不拋出異常:

//?ilustrative?definition?of?library?bad_alloc?class
?????class?bad_alloc?:?public?exception?{
?????public:
?????????bad_alloc()?throw();
?????????bad_alloc(const?bad_alloc?&)?throw();
?????????bad_alloc?&?operator=(const
?????????bad_alloc?&)?throw();
?????????virtual?~bad_alloc()?throw();
?????????virtual?const?char*?what()?const?throw();
?????};

?

注意,在 const 成員函數聲明中,異常說明跟在 const 限定符之后。

(4)異常說明與虛函數

基類中虛函數的異常說明,可以與派生類中對應虛函數的異常說明不同。但是,派生類虛函數的異常說明必須與對應基類虛函數的異常說明同樣嚴格,或者比后者更受限。

這個限制保證,當使用指向基類類型的指針調用派生類虛函數的時候,派生類的異常說明不會增加新的可拋出異常。例如:

class?Base?{
?????public:
?????????virtual?double?f1(double)?throw?();
?????????virtual?int?f2(int)?throw?(std::logic_error);
?????????virtual?std::string?f3()?throw
???????????????(std::logic_error,?std::runtime_error);
?????};
?????class?Derived?:?public?Base?{
?????public:
?????????//?error:?exception?specification?is?less?restrictive?than?Base::f1's
?????????double?f1(double)?throw?(std::underflow_error);
?????????//?ok:?same?exception?specification?as?Base::f2
?????????int?f2(int)?throw?(std::logic_error);
?????????//?ok:?Derived?f3?is?more?restrictive
?????????std::string?f3()?throw?();
?????};

?

派生類中 f1 的聲明是錯誤的,因為它的異常說明在基類 f1 版本列出的異常中增加了一個異常。派生類不能在異常說明列表中增加異常,原因在于,繼承層次的用戶應該能夠編寫依賴于該說明列表的代碼。如果通過基類指針或引用進行函數調用,那么,這些類的用戶所涉及的應該只是在基類中指定的異常。

通過派生類拋出的異常限制為由基類所列出的那些,在編寫代碼時就可以知道必須處理哪些異常。代碼可以依賴于這樣一個事實:基類中的異常列表是虛函數的派生類版本可以拋出的異常列表的超集。例如,當調用 f3 的時候,我們知道只需要處理 logic_error 或 runtime_error:

//?guarantees?not?to?throw?exceptions
?????void?compute(Base?*pb)?throw()
?????{
?????????try?{
?????????????//?may?throw?exception?of?type?std::logic_error
?????????????
//?or?std::runtime_error
?????????????pb->f3();
?????????}?catch?(const?logic_error?&le)???{?/*?...?*/?}
???????????catch?(const?runtime_error?&re)?{?/*?...?*/?}
?????}

?

(5)函數指針異常說明

異常說明是函數類型的一部分。這樣,也可以在函數指針的定義中提供異常說明:

void (*pf)(int) throw(runtime_error);

這個聲明是說,pf 指向接受 int 值的函數,該函數返回 void 對象,該函數只能拋出 runtime_error 類型的異常。如果不提供異常說明,該指針就可以指向能夠拋出任意類型異常的具有匹配類型的函數。

在用另一指針初始化帶異常說明的函數的指針,或者將后者賦值給函數地址的時候,兩個指針的異常說明不必相同,但是,源指針的異常說明必須至少與目標指針的一樣嚴格。

void?recoup(int)?throw(runtime_error);
?????//?ok:?recoup?is?as?restrictive?as?pf1
?????void?(*pf1)(int)?throw(runtime_error)?=?recoup;
?????//?ok:?recoup?is?more?restrictive?than?pf2
?????void?(*pf2)(int)?throw(runtime_error,?logic_error)?=?recoup;
?????//?error:?recoup?is?less?restrictive?than?pf3
?????void?(*pf3)(int)?throw()?=?recoup;
?????//?ok:?recoup?is?more?restrictive?than?pf4
?????void?(*pf4)(int)?=?recoup;

?

?

第三個初始化是錯誤的。指針聲明指出,pf3 指向不拋出任何異常的函數,但是,recoup 函數指出它能拋出 runtime_error 類型的異常,recoup 函數拋出的異常類型超出了 pf3 所指定的,對 pf3 而言,recoup 函數不是有效的初始化式,并且會引發一個編譯時錯誤。

?

13. 命名空間/名字空間

命名空間可以是不連續的。與其他作用域不同,命名空間可以在幾個部分中定義。命名空間由它的分離定義部分的總和構成,命名空間是累積的。一個命名空間的分離部分可以分散在多個文件中,在不同文本文件中的命名空間定義也是累積的。當然,名字只在聲明名字的文件中可見,這一常規限制繼續應用,所以,如果命名空間的一個部分需要定義在另一文件中的名字,仍然必須聲明該名字。

定義多個不相關類型的命名空間應該使用分離的文件,表示該命名空間定義的每個類型。

(1)未命名的名字空間

未命名的命名空間與其他命名空間不同,未命名的命名空間的定義局部于特定文件,從不跨越多個文本文件。

未命名的命名空間可以在給定文件中不連續,但不能跨越文件,每個文件有自己的未命名的命名空間。

未命名的命名空間中定義的名字可直接使用,畢竟,沒有命名空間名字來限定它們。不能使用作用域操作符來引用未命名的命名空間的成員。

未命名的命名空間中定義的名字只在包含該命名空間的文件中可見。如果另一文件包含一個未命名的命名空間,兩個命名空間不相關。兩個命名空間可以定義相同的名字,而這些定義將引用不同的實體。

未命名空間中定義的名字可以在定義該命名空間所在的作用域中找到。如果在文件的最外層作用域中定義未命名的命名空間,那么,未命名的空間中的名字必須與全局作用域中定義的名字不同:

int?i;???//?global?declaration?for?i
?????namespace?{
?????????int?i;
?????}
?????//?error:?ambiguous?defined?globally?and?in?an?unnested,?unnamed?namespace
?????i?=?10;

?

像任意其他命名空間一樣,未命名的命名空間也可以嵌套在另一命名空間內部。如果未命名的命名空間是嵌套的,其中的名字按常規方法使用外圍命名空間名字訪問:

namespace?local?{
????????namespace?{
????????????int?i;
????????}
?????}
????????//?ok:?i?defined?in?a?nested?unnamed?namespace?is?distinct?from?global?i
????????local::i?=?42;

?

在標準 C++ 中引入命名空間之前,程序必須將名字聲明為 static,使它們局部于一個文件。文件中靜態聲明的使用從 C 語言繼承而來,在 C 語言中,聲明為 static 的局部實體在聲明它的文件之外不可見。

????C++ 不贊成文件靜態聲明。不造成的特征是在未來版本中可能不支持的特征。應該避免文件靜態而使用未命名空間代替。

?

14. 多重繼承與虛繼承

在多重繼承下,派生類的對象包含每個基類的基類子對象。

虛繼承來解決菱形繼承中的多個基類子對象的問題。

在 C++ 中,通過使用虛繼承解決這類問題。虛繼承是一種機制,類通過虛繼承指出它希望共享其虛基類的狀態。在虛繼承下,對給定虛基類,無論該類在派生層次中作為虛基類出現多少次,只繼承一個共享的基類子對象。共享的基類子對象稱為虛基類。

虛繼承帶來了初始化順序的問題。

通常,每個類只初始化自己的直接基類。在應用于虛基類的進修,這個初始化策略會失敗。如果使用常規規則,就可能會多次初始化虛基類。類將沿著包含該虛基類的每個繼承路徑初始化。

為了解決這個重復初始化問題,從具有虛基類的類繼承的類對初始化進行特殊處理。在虛派生中,由最低層派生類的構造函數初始化虛基類。

構造函數與析構函數次序:無論虛基類出現在繼承層次中任何地方,總是在構造非虛基類之前構造虛基類。

代碼如下:

View Code #if?1
#include?<iostream>
class?Class{
????public:
????Class(){
????????std::cout<<"Constructor->Class"<<std::endl;
????}
????~Class(){
????????std::cout<<"Destructor->Class"<<std::endl;
????}

};
class?Base:?public?Class{
????public:
????????Base():name("Base"){std::cout<<"Constructor->Base"<<std::endl;}
????????Base(std::string?s):name(s){std::cout<<"Constructor->Base"<<std::endl;}
????????Base(const?Base&?b):name(b.name){std::cout<<"Constructor->Base"<<std::endl;}
????????~Base(){
????????????std::cout<<"Destructor->Base"<<std::endl;
????????}
????protected:
????????std::string?name;
};
class?Derived1:virtual?public?Base{
????public:
????????Derived1():Base("Derived1"){std::cout<<"Constructor->Derived1"<<std::endl;}
????????Derived1(std::string?s):Base(s){std::cout<<"Constructor->Derived1"<<std::endl;}
????????Derived1(const?Derived1&?d):Base(d){std::cout<<"Constructor->Derived1"<<std::endl;}
????????~Derived1(){
????????????std::cout<<"Destructor->Derived1"<<std::endl;
????????}
};
class?Derived2:virtual?public?Base{
????public:
????????Derived2():Base("Derived2"){std::cout<<"Constructor->Derived2"<<std::endl;}
????????Derived2(std::string?s):Base(s){std::cout<<"Constructor->Derived2"<<std::endl;}
????????Derived2(const?Derived2&?d):Base(d){std::cout<<"Constructor->Derived2"<<std::endl;}
????????~Derived2(){
????????????std::cout<<"Destructor->Derived2"<<std::endl;
????????}
};
class?MI:public?Derived1,public?Derived2{
????public:
????????MI():Base("MI"){}
????????MI(std::string?s):Base(s),Derived1(s),Derived2(s){std::cout<<"Constructor->MI"<<std::endl;}
????????MI(const?MI&?m):Base(m),Derived1(m),Derived2(m){std::cout<<"Constructor->MI"<<std::endl;}
????????~MI(){
????????????std::cout<<"Destructor->MI"<<std::endl;
????????}
};
class?Final:public?MI,public?Class{
????public:
????????Final():Base("Final"){std::cout<<"Constructor->Final"<<std::endl;}
????????Final(std::string?s):Base(s),MI(s){std::cout<<"Constructor->Final"<<std::endl;}
????????Final(const?Final&?f):Base(f),MI(f){std::cout<<"Constructor->Final"<<std::endl;}
????????~Final(){
????????????std::cout<<"Destructor->Final"<<std::endl;
????????}
};

int?main(){
????Final?f;
}

#endif

?

運行結果:

第18章 特殊工具和技術

1. 優化內存分配

C++ 的內存分配是一種類型化操作:new為特定類型分配內存,并在新分配的內存中構造該類型的一個對象。new 表達式自動運行合適的構造函數來初始化每個動態分配的類類型對象。

new 基于每個對象分配內存的事實可能會對某些類強加不可接受的運行時開銷,這樣的類可能需要使用用戶級的類類型對象分配能夠更快一些。這樣的類使用的通用策略是,預先分配用于創建新對象的內存,需要時在預先分配的內存中構造每個新對象。

另外一些類希望按最小尺寸為自己的數據成員分配需要的內存。例如,標準庫中的 vector 類預先分配額外內存以保存加入的附加元素,將新元素加入到這個保留容量中。將元素保持在連續內存中的時候,預先分配的元素使 vector 能夠高效地加入元素。

在每種情況下(預先分配內存以保存用戶級對象或者保存類的內部數據)都需要將內存分配與對象構造分離開。將內存分配與對象構造分離開的明顯的理由是,在預先分配的內存中構造對象很浪費,可能會創建從不使用的對象。當實際使用預先分配的對象的時候,被使用的對象必須重新賦以新值。更微妙的是,如果預先分配的內存必須被構造,某些類就不能使用它。例如,考慮 vector,它使用了預先分配策略。如果必須構造預先分配的內存中的對象,就不能有基類型為沒有默認構造函數的 vector——vector 沒有辦法知道怎樣構造這些對象。

2. C++中的內存分配

C++ 中,內存分配和對象構造緊密糾纏,就像對象和內存回收一樣。使用 new 表達式的時候,分配內存,并在該內存中構造一個對象;使用 delete 表達式的時候,調用析構函數撤銷對象,并將對象所用內存返還給系統。

接管內存分配時,必須處理這兩個任務。分配原始內存時,必須在該內存中構造對象;在釋放該內存之前,必須保證適當地撤銷這些對象。

C++ 提供下面兩種方法分配和釋放未構造的原始內存。

(1).allocator 類,它提供可感知類型的內存分配。這個類支持一個抽象接口,以分配內存并隨后使用該內存保存對象。

(2).標準庫中的 operator new 和 operator delete,它們分配和釋放需要大小的原始的、未類型化的內存。

C++ 還提供不同的方法在原始內存中構造和撤銷對象。

(1).allocator 類定義了名為 construct 和 destroy 的成員,其操作正如它們的名字所指出的那樣:construct 成員在未構造內存中初始化對象,destroy 成員在對象上運行適當的析構函數。

(2).定位 new 表達式(placement new expression)接受指向未構造內存的指針,并在該空間中初始化一個對象或一個數組。

(3).可以直接調用對象的析構函數來撤銷對象。運行析構函數并不釋放對象所在的內存。

(4).算法 uninitialized_fill 和 uninitialized_copy 像 fill 和 copy 算法一樣執行,除了它們的目的地構造對象而不是給對象賦值之外。

3. allocator類

allocator 類將內存分配和對象構造分開。當 allocator 對象分配內存的時候,它分配適當大小并排列成保存給定類型對象的空間。但是,它分配的內存是未構造的,allocator 的用戶必須分別 construct 和 destroy 放置在該內存中的對象。

回憶一下,vector 類將元素保存在連續的存儲中。為了獲得可接受的性能,vector 預先分配比所需元素更多的元素。每個將元素加到容器中的 vector 成員檢查是否有可用空間以容納另一元素。如果有,該成員在預分配內存中下一可用位置初始化一個對象;如果沒有自由元素,就重新分配 vector:vector 獲取新的空間,將現在元素復制到空間,增加新元素,并釋放舊空間。

vector 所用存儲開始是未構造內存,它還沒有保存任何對象。將元素復制或增加到這個預分配空間的時候,必須使用 allocator 類的 construct 成員構造元素。

?

為了說明這些概念,我們將實現 vector 的一小部分。將我們的類命名為 Vector,以區別于標準類 vector:

//?pseudo-implementation?of?memory?allocation?strategy?for?a?vector-like?class
?????template?<class?T>?class?Vector?{
?????public:
?????????Vector():?elements(0),?first_free(0),?end(0)?{?}
?????????void?push_back(const?T&);
??????????//?...
?????private:
?????????static?std::allocator<T>?alloc;?//?object?to?get?raw?memory
?????????void?reallocate();?//?get?more?space?and?copy?existing?elements
?????????T*?elements;???????//?pointer?to?first?element?in?the?array
?????????T*?first_free;?????//?pointer?to?first?free?element?in?the?array
?????????T*?end;????????????//?pointer?to?one?past?the?end?of?the?array
?????????
//?...
?????};

每個 Vector<T> 類型定義一個 allocator<T> 類型的 static 數據成員,以便在給定類型的 Vector 中分配和構造元素。每個 Vector 對象在指定類型的內置數組中保存其元素,并維持該數組的下列三個指針:

  • elements,指向數組的第一個元素。
  • first_free,指向最后一個實際元素之后的那個元素。
  • end,指向數組本身之后的那個元素。

可以使用這些指針來確定 Vector 的大小和容量:

  • Vector 的 size(實際使用的元素的數目)等于 first_free-elements。
  • Vector 的 capacity(在必須重新分配 Vector 之前,可以定義的元素的總數)等于end-elements。
  • 自由空間(在需要重新分配之前,可以增加的元素的數目)是 end-first_free。

    ?

push_back 成員使用這些指針將新元素加到 Vector 末尾:

template?<class?T>
?????void?Vector<T>::push_back(const?T&?t)
?????{
?????????//?are?we?out?of?space?
?????????if?(first_free?==?end)
???????????reallocate();?//?gets?more?space?and?copies?existing?elements?to?it
?????????alloc.construct(first_free,?t);
?????????++first_free;
?????}

push_back 函數首先確定是否有可用空間,如果沒有,就調用 reallocate 函數,reallocate 分配新空間并復制現存元素,將指針重置為指向新分配的空間。

一旦 push_back 函數知道還有空間容納新元素,它就請求 allocator 對象構造一個新的最后元素。construct 函數使用類型 T 的復制構造函數將 t 值復制到由 first_free 指出的元素,然后,將 first_free 加 1 以指出又有一個元素在用。

?

reallocate 函數所做的工作最多:

template?<class?T>?void?Vector<T>::reallocate()
?????{
?????????//?compute?size?of?current?array?and?allocate?space?for?twice?as?many?elements
?????????std::ptrdiff_t?size?=?first_free?-?elements;
?????????std::ptrdiff_t?newcapacity?=?2?*?max(size,?1);
?????????//?allocate?space?to?hold?newcapacity?number?of?elements?of?type?T
?????????T*?newelements?=?alloc.allocate(newcapacity);
?????????//?construct?copies?of?the?existing?elements?in?the?new?space
?????????uninitialized_copy(elements,?first_free,?newelements);
?????????//?destroy?the?old?elements?in?reverse?order
?????????for?(T?*p?=?first_free;?p?!=?elements;?/*?empty?*/?)
????????????alloc.destroy(--p);
?????????//?deallocate?cannot?be?called?on?a?0?pointer
?????????if?(elements)
?????????????//?return?the?memory?that?held?the?elements
?????????????alloc.deallocate(elements,?end?-?elements);
?????????//?make?our?data?structure?point?to?the?new?elements
?????????elements?=?newelements;
?????????first_free?=?elements?+?size;
?????????end?=?elements?+?newcapacity;
?????}

?

我們使用一個簡單但效果驚人的策略:每次重新分配時分配兩倍內存。函數首先計算當前在用的元素數目,將該數目翻倍,并請求 allocator 對象來獲得所需數量的空間。如果 Vector 為空,就分配兩個元素。

如果 Vector 保存 int 值,allocate 函數調用為 newcapacity 數目的 int 值分配空間;如果 Vector 保存 string 對象,它就為給定數目的 string 對象分配空間。

uninitialized_copy 調用使用標準 copy 算法的特殊版本。這個版本希望目的地是原始的未構造內存,它在目的地復制構造每個元素,而不是將輸入范圍的元素賦值給目的地,使用 T 的復制構造函數從輸入范圍將每個元素復制到目的地。

for 循環對舊數組中每個對象調用 allocator 的 destroy 成員它按逆序撤銷元素,從數組中最后一個元素開始,以第一個元素結束。destroy 函數運行 T 類型的析構函數來釋放舊元素所用的任何資源。

一旦復制和撤銷了元素,就釋放原來數組所用的空間。在調用 deallocate 之前,必須檢查 elements 是否實際指向一個數組。

最后,必須重置指針以指向新分配并初始化的數組。將 first_free 和 end 指針分別置為指向最后構造的元素之后的單元以及所分配空間末尾的下一單元。

?

完整的Vector的代碼如下:

View Code #include?<iostream>
#include?<memory>
using?std::cout;?using?std::endl;

template?<class?T>?class?Vector?{
public:
????Vector():?elements(0),?first_free(0),?end(0)?{?}
????void?push_back(const?T&);
????size_t?size()?const?{?return?first_free?-?elements;?}
????size_t?capacity()?const?{?return?end?-?elements;?}
????//?.?.?.
????T&?operator[](size_t?n)?{?return?elements[n];?}
????const?T&?operator[](size_t?n)?const?{?return?elements[n];?}
private:
????static?std::allocator<T>?alloc;?//?member?to?handle?allocation
????void?reallocate();?//?get?more?space?and?copy?existing?elements
????T*?elements;???????//?pointer?to?first?element?in?the?array
????T*?first_free;?????//?pointer?to?first?free?element?in?the?array
????T*?end;????????????//?pointer?to?one?past?the?end?of?the?array
????
//?.?.?.
};

#include?<algorithm>
using?std::allocator;
template?<class?T>?allocator<T>?Vector<T>::alloc;

using?std::max;
using?std::uninitialized_copy;
template?<class?T>?void?Vector<T>::reallocate()
{
????std::ptrdiff_t?size?=?first_free?-?elements;?
????std::ptrdiff_t?newcapacity?=?2?*?max(size,?1);
????T*?newelements?=?alloc.allocate(newcapacity);
?
????uninitialized_copy(elements,?first_free,?newelements);

????for?(T?*p?=?first_free;?p?!=?elements;?/*empty*/?)
????????alloc.destroy(--p);
????
????if?(elements)
????????alloc.deallocate(elements,?end?-?elements);

????elements?=?newelements;
????first_free?=?elements?+?size;
????end?=?elements?+?newcapacity;
}

template?<class?T>?void?Vector<T>::push_back(const?T&?t)
{
????if?(first_free?==?end)
??????reallocate();?//?gets?more?space?and?copies?existing?elements?to?it
????alloc.construct(first_free,?t);??
????++first_free;
}

int?main()
{
????Vector<int>?vi;

????for?(int?i?=?0;?i?!=?10;?++i)?{
??????vi.push_back(i);
??????cout?<<?vi[i]?<<?endl;
????}

????for?(int?i?=?0;?i?!=?10;?++i)
??????cout?<<?vi[i]?<<?endl;

????return?0;
}

?

4. new和delete表達式的工作原理:

當使用 new 表達式

//?new?expression
string?*?sp?=?new?string("initialized");

的時候,實際上發生三個步驟。首先,該表達式調用名為 operator new 的標準庫函數,分配足夠大的原始的未類型化的內存,以保存指定類型的一個對象;接下來,運行該類型的一個構造函數,用指定初始化式構造對象;最后,返回指向新分配并構造的對象的指針。

當使用 delete 表達式

delete?sp;

?

刪除動態分配對象的時候,發生兩個步驟。首先,對 sp 指向的對象運行適當的析構函數;然后,通過調用名為 operator delete 的標準庫函數釋放該對象所用內存。

?

5. new表達式與operator new函數

標準庫函數 operator new 和 operator delete 的命名容易讓人誤解。與其他 operator 函數(如 operator=)不同,這些函數沒有重載 new 或 delete 表達式,實際上,我們不能重定義 new 和 delete 表達式的行為。

通過調用 operator new 函數執行 new 表達式獲得內存,并接著在該內存中構造一個對象,通過撤銷一個對象執行 delete 表達式,并接著調用 operator delete 函數,以釋放該對象使用的內存。

?

6. operator new 函數和 operator delete 函數

(1) operator new 和 operator delete 接口如下:

operator new 和 operator delete 函數有兩個重載版本,每個版本支持相關的 new 表達式和 delete 表達式:

void?*operator?new(size_t);?//?allocate?an?object
void?*operator?new[](size_t);?//?allocate?an?array
void?*operator?delete(void*);?//?free?an?object
void?*operator?delete[](void*);?//?free?an?array

(2)使用分配操作符函數

雖然 operator new 和 operator delete 函數的設計意圖是供 new 表達式使用,但它們通常是標準庫中的可用函數。可以使用它們獲得未構造內存,它們有點類似 allocate 類的 allocator 和 deallocate 成員。例如,代替使用 allocator 對象,可以在 Vector 類中使用 operator new 和 operator delete 函數。在分配新空間時我們曾編寫

//?allocate?space?to?hold?newcapacity?number?of?elements?of?type?T
T*?newelements?=?alloc.allocate(newcapacity);

這可以重新編寫為

//?allocate?unconstructed?memory?to?hold?newcapacity?elements?of?type?T
T*?newelements?=?static_cast<T*>(operator?new[](newcapacity?*?sizeof(T)));

?

類似地,在重新分配由 Vector 成員 elements 指向的舊空間的時候,我們曾經編寫

//?return?the?memory?that?held?the?elements
alloc.deallocate(elements,?end?-?elements);

?

這可以重新編寫為

//?deallocate?the?memory?that?they?occupied
operator?delete[](elements);

?

這些函數的表現與 allocate 類的 allocator 和 deallocate 成員類似。但是,它們在一個重要方面有不同:它們在 void* 指針而不是類型化的指針上進行操作。

一般而言,使用 allocator 比直接使用 operator new 和 operator delete 函數更為類型安全。

allocate 成員分配類型化的內存,所以使用它的程序可以不必計算以字節為單位的所需內存量,它們也可以避免對 operator new 的返回值進行強制類型轉換。類似地,deallocate 釋放特定類型的內存,也不必轉換為 void*。

?

7. 定位new表達式

標準庫函數 operator new 和 operator delete 是 allocator 的 allocate 和 deallocate 成員的低級版本,它們都分配但不初始化內存。

allocator 的成員 construct 和 destroy 也有兩個低級選擇,這些成員在由 allocator 對象分配的空間中初始化和撤銷對象。

類似于 construct 成員,有第三種 new 表達式,稱為定位 new。定位 new 表達式在已分配的原始內存中初始化一個對象,它與 new 的其他版本的不同之處在于,它不分配內存。相反,它接受指向已分配但未構造內存的指針,并在該內存中初始化一個對象。實際上,定位 new 表達式使我們能夠在特定的、預分配的內存地址構造一個對象。

?

定位 new 表達式的形式是:

new (place_address) type

new (place_address) type (initializer-list)

其中 place_address 必須是一個指針,而 initializer-list 提供了(可能為空的)初始化列表,以便在構造新分配的對象時使用。

?

可以使用定位 new 表達式代替 Vector 實現中的 construct 調用。原來的代碼

//?construct?a?copy?t?in?the?element?to?which?first_free?points
alloc.construct?(first_free,?t);

?

可以用等價的定位 new 表達式代替

//?copy?t?into?element?addressed?by?first_free
new?(first_free)?T(t);

?

定位 new 表達式比 allocator 類的 construct 成員更靈活。定位 new 表達式初始化一個對象的時候,它可以使用任何構造函數,并直接建立對象。construct 函數總是使用復制構造函數。

例如,可以用下面兩種方式之一,從一對迭代器初始化一個已分配但未構造的 string 對象:

allocator<string>?alloc;
string?*sp?=?alloc.allocate(2);?//?allocate?space?to?hold?2?strings
//?two?ways?to?construct?a?string?from?a?pair?of?iterators
new?(sp)?string(b,?e);?//?construct?directly?in?place
alloc.construct(sp?+?1,?string(b,?e));?//?build?and?copy?a?temporary

定位 new 表達式使用了接受一對迭代器的 string 構造函數,在 sp 指向的空間直接構造 string 對象。當調用 construct 函數的時候,必須首先從迭代器構造一個 string 對象,以獲得傳遞給 construct 的 string 對象,然后,該函數使用 string 的復制構造函數,將那個未命名的臨時 string 對象復制到 sp 指向的對象中。

?

通常,這些區別是不相干的:對值型類而言,在適當的位置直接構造對象與構造臨時對象并進行復制之間沒有可觀察到的區別,而且性能差別基本沒有意義。但對某些類而言,使用復制構造函數是不可能的(因為復制構造函數是私有的),或者是應該避免的,在這種情況下,也許有必要使用定位 new 表達式。

8. 顯示析構函數的調用

正如定位 new 表達式是使用 allocate 類的 construct 成員的低級選擇,我們可以使用析構函數的顯式調用作為調用 destroy 函數的低級選擇。

在使用 allocator 對象的 Vector 版本中,通過調用 destroy 函數清除每個元素:

//?destroy?the?old?elements?in?reverse?order
for?(T?*p?=?first_free;?p?!=?elements;?/*?empty?*/?)
alloc.destroy(--p);

?

對于使用定位 new 表達式構造對象的程序,顯式調用析構函數:

for?(T?*p?=?first_free;?p?!=?elements;?/*?empty?*/?)
p->~T();?//?call?the?destructor

?

在這里直接調用析構函數。箭頭操作符對迭代器 p 解引用以獲得 p 所指的對象,然后,調用析構函數,析構函數以類名前加 ~ 來命名。

顯式調用析構函數的效果是適當地清除對象本身。但是,并沒有釋放對象所占的內存,如果需要,可以重用該內存空間。

?

9. 運行時類型識別

通過運行時類型識別(RTTI),程序能夠使用基類的指針或引用來檢索這些指針或引用所指對象的實際派生類型。

通過下面兩個操作符提供 RTTI:

(1) typeid 操作符,返回指針或引用所指對象的實際類型。

(2) dynamic_cast 操作符,將基類類型的指針或引用安全地轉換為派生類型的指針或引用。

這些操作符只為帶有一個或多個虛函數的類返回動態類型信息,對于其他類型,返回靜態(即編譯時)類型的信息。

對于帶虛函數的類,在運行時執行 RTTI 操作符,但對于其他類型,在編譯時計算 RTTI 操作符。

當具有基類的引用或指針,但需要執行不是基類組成部分的派生類操作的時候,需要動態的強制類型轉換。通常,從基類指針獲得派生類行為最好的方法是通過虛函數。當使用虛函數的時候,編譯器自動根據對象的實際類型選擇正確的函數。

但是,在某些情況下,不可能使用虛函數。在這些情況下,RTTI 提供了可選的機制。然而,這種機制比使用虛函數更容易出錯:程序員必須知道應該將對象強制轉換為哪種類型,并且必須檢查轉換是否成功執行了。

????使用動態強制類型轉換要小心。只要有可能,定義和使用虛函數比直接接管類型管理好得多。

?

10. dynamic_cast操作符

可以使用 dynamic_cast 操作符將基類類型對象的引用或指針轉換為同一繼承層次中其他類型的引用或指針。與 dynamic_cast 一起使用的指針必須是有效的——它必須為 0 或者指向一個對象。

與其他強制類型轉換不同,dynamic_cast 涉及運行時類型檢查。如果綁定到引用或指針的對象不是目標類型的對象,則 dynamic_cast 失敗。如果轉換到指針類型的 dynamic_cast 失敗,則 dynamic_cast 的結果是 0 值;如果轉換到引用類型的 dynamic_cast 失敗,則拋出一個 bad_cast 類型的異常。

因此,dynamic_cast 操作符一次執行兩個操作。它首先驗證被請求的轉換是否有效,只有轉換有效,操作符才實際進行轉換。一般而言,引用或指針所綁定的對象的類型在編譯時是未知的,基類的指針可以賦值為指向派生類對象,同樣,基類的引用也可以用派生類對象初始化,因此,dynamic_cast 操作符執行的驗證必須在運行時進行。

作為例子,假定 Base 是至少帶一個虛函數的類,并且 Derived 類派生于 Base 類。如果有一個名為 basePtr 的指向 Base 的指針,就可以像這樣在運行時將它強制轉換為指向 Derived 的指針:

if?(Derived?*derivedPtr?=?dynamic_cast<Derived*>(basePtr))
{
//?use?the?Derived?object?to?which?derivedPtr?points
}?else?{?//?BasePtr?points?at?a?Base?object
//?use?the?Base?object?to?which?basePtr?points
}

?

在前面例子中,使用了 dynamic_cast 將基類指針轉換為派生類指針,也可以使用 dynamic_cast 將基類引用轉換為派生類引用,這種 dynamic_cast 操作的形式如下:

dynamic_cast< Type& >(val)

這里,Type 是轉換的目標類型,而 val 是基類類型的對象。

只有當 val 實際引用一個 Type 類型對象,或者 val 是一個 Type 派生類型的對象的時候,dynamic_cast 操作才將操作數 val 轉換為想要的 Type& 類型。

?

因為不存在空引用,所以不可能對引用使用用于指針強制類型轉換的檢查策略,相反,當轉換失敗的時候,它拋出一個 std::bad_cast 異常,該異常在庫頭文件 typeinfo 中定義。

?

可以重寫前面的例子如下,以便使用引用:

void?f(const?Base?&b)
{
try?{
const?Derived?&d?=?dynamic_cast<const?Derived&>(b);
//?use?the?Derived?object?to?which?b?referred
}?catch?(bad_cast)?{
//?handle?the?fact?that?the?cast?failed
}
}

?

11. 使用dynamic_cast代替虛函數

12. typeid操作符

如果表達式的類型是類類型且該類包含一個或多個虛函數,則表達式的動態類型可能不同于它的靜態編譯時類型。例如,如果表達式對基類指針解引用,則該表達式的靜態編譯時類型是基類類型;但是,如果指針實際指向派生類對象,則 typeid 操作符將說表達式的類型是派生類型。

typeid 操作符可以與任何類型的表達式一起使用。內置類型的表達式以及常量都可以用作 typeid 操作符的操作數。如果操作數不是類類型或者是沒有虛函數的類,則 typeid 操作符指出操作數的靜態類型;如果操作數是定義了至少一個虛函數的類類型,則在運行時計算類型。

typeid 操作符的結果是名為 type_info 的標準庫類型的對象引用,第 18.2.4 節將更詳細地討論這個類型。要使用 type_info 類,必須包含庫頭文件 typeinfo。

typeid 最常見的用途是比較兩個表達式的類型,或者將表達式的類型與特定類型相比較:

Base?*bp;
?????Derived?*dp;
?????//?compare?type?at?run?time?of?two?objects
?????if?(typeid(*bp)?==?typeid(*dp))?{
?????????//?bp?and?dp?point?to?objects?of?the?same?type
?????}
?????//?test?whether?run?time?type?is?a?specific?type
?????if?(typeid(*bp)?==?typeid(Derived))?{
?????????//?bp?actually?points?to?a?Derived
?????}

?

13. type_info類

type_info 類隨編譯器而變。一些編譯器提供附加的成員函數,那些函數提供關于程序中所用類型的附加信息。你應該查閱編譯器的參考手冊來理解所提供的確切的 type_info 支持。

#include?<iostream>
#include?<typeinfo>
#include?<string>
using?std::string;
using?std::cout;?using?std::endl;??????????

struct?Base?{
????virtual?~Base()?{?}
};
struct?Derived?:?Base?{?};
int?main()
{
int?iobj;

cout?<<?typeid(iobj).name()?<<?endl
?????<<?typeid(8.16).name()?<<?endl
?????<<?typeid(std::string).name()?<<?endl
?????<<?typeid(Base).name()?<<?endl
?????<<?typeid(Derived).name()?<<?endl;

return?0;
}

?

14. 類成員指針

可以通過使用稱為成員指針的特殊各類的指針做到這一點。成員指針包含類的類型以及成員的類型。這一事實影響著怎樣定義成員指針,怎樣將成員指針綁定到函數或數據成員,以及怎樣使用它們。

成員指針只應用于類的非 static 成員。static 類成員不是任何對象的組成部分,所以不需要特殊語法來指向 static 成員,static 成員指針是普通指針。

成員函數的指針必須在三個方面與它所指函數的類型相匹配:

(1)函數形參的類型和數目,包括成員是否為 const。

(2)返回類型。

(3)所屬類的類型。

通過指定函數返回類型、形參表和類來定義成員函數的指針。

普通指針與成員指針

15. 類成員指針的使用

類似于成員訪問操作符 . 和 ->,.* 和 -> 是兩個新的操作符,它們使我們能夠將成員指針綁定到實際對象。這兩個操作符的左操作數必須是類類型的對象或類類型的指針,右操作數是該類型的成員指針。

(1) 成員指針解引用操作符(.*)從對象或引用獲取成員。

(2) 成員指針箭頭操作符(->*)通過對象的指針獲取成員。

?

16. 聯合Union

聯合是一種特殊的類。一個 union 對象可以有多個數據成員,但在任何時刻,只有一個成員可以有值。當將一個值賦給 union 對象的一個成員的時候,其他所有都變為未定義的。

(1)沒有靜態數據成員、引用成員或類數據成員

某些(但不是全部)類特征同樣適用于 union。例如,像任何類一樣,union 可以指定保護標記使成員成為公用的、私有的或受保護的。默認情況下,union 表現得像 struct:除非另外指定,否則 union 的成員都為 public 成員。

union 也可以定義成員函數,包括構造函數和析構函數。但是,union 不能作為基類使用,所以成員函數不能為虛數。

union 不能具有靜態數據成員或引用成員,而且,union 不能具有定義了構造函數、析構函數或賦值操作符的類類型的成員:

union?illegal_members?{
?????????Screen?s;??????//?error:?has?constructor
?????????static?int?is;?//?error:?static?member
?????????int?&rfi;??????//?error:?reference?member
?????????Screen?*ps;????//?ok:?ordinary?built-in?pointer?type
?????};

?

這個限制包括了具有帶構造函數、析構函數或賦值操作符的成員的類。

(2)嵌套聯合,匿名聯合

union 最經常用作嵌套類型,其中判別式是外圍類的一個成員:

class?Token?{
?????public:
?????????//?indicates?which?kind?of?value?is?in?val
?????????enum?TokenKind?{INT,?CHAR,?DBL};
?????????TokenKind?tok;
?????????union?{?????????????//?unnamed?union
?????????????char???cval;
?????????????int????ival;
?????????????double?dval;
?????????}?val;??????????????//?member?val?is?a?union?of?the?3?listed?types
?????};

?

這個類中,用枚舉對象 tok 指出 val 成員中存儲了哪種值,val 成員是一個(未命名的)union,它保存 char、int 或 double 值。

經常使用 switch 語句(第 6.6 節)測試判別式,然后根據 union 中當前存儲的值進行處理:

Token?token;
?????switch?(token.tok)?{
?????case?Token::INT:
?????????token.val.ival?=?42;?break;
?????case?Token::CHAR:
?????????token.val.cval?=?'a';?break;
?????case?Token::DBL:
?????????token.val.dval?=?3.14;?break;
?????}

?

不用于定義對象的未命名 union 稱為匿名聯合。匿名 union 的成員的名字出現在外圍作用域中。例如,使用匿名 union 重寫的 Token 類如下:

class?Token?{
?????public:
?????????//?indicates?which?kind?of?token?value?is?in?val
?????????enum?TokenKind?{INT,?CHAR,?DBL};
?????????TokenKind?tok;
?????????union?{?????????????????//?anonymous?union
?????????????char???cval;
?????????????int????ival;
?????????????double?dval;
?????????};
?????};

?

因為匿名 union 不提供訪問其成員的途徑,所以將成員作為定義匿名 union 的作用域的一部分直接訪問。重寫前面的 switch 以便使用類的匿名 union 版本,如下:

Token?token;
?????switch?(token.tok)?{
?????case?Token::INT:
?????????token.ival?=?42;?break;
?????case?Token::CHAR:
?????????token.cval?=?'a';?break;
?????case?Token::DBL:
?????????token.dval?=?3.14;?break;
?????}

?

17. 固有的不可移植的特征

(1)位域

可以聲明一種特殊的類數據成員,稱為位域,來保存特定的位數。當程序需要將二進制數據傳遞給另一程序或硬件設備的時候,通常使用位域。

位域必須是整型數據類型,可以是 signed 或 unsigned。通過在成員名后面接一個冒號以及指定位數的常量表達式,指出成員是一個位域:

typedef?unsigned?int?Bit;
?????class?File?{
?????????Bit?mode:?2;
?????????Bit?modified:?1;
?????????Bit?prot_owner:?3;
?????????Bit?prot_group:?3;
?????????Bit?prot_world:?3;
?????????//?...
?????};

?

(2)volatile限定符

直接處理硬件的程序常具有這樣的數據成員,它們的值由程序本身直接控制之外的過程所控制。例如,程序可以包含由系統時鐘更新的變量。當可以用編譯器的控制或檢測之外的方式改變對象值的時候,應該將對象聲明為 volatile。關鍵字 volatile 是給編譯器的指示,指出對這樣的對象不應該執行優化。

用與 const 限定符相同的方式使用 volatile 限定符。volatile 限定符是一個對類型的附加修飾符:

volatile?int?display_register;
?????volatile?Task?*curr_task;
?????volatile?int?ixa[max_size];
?????volatile?Screen?bitmap_buf;

?

?

第 4.2.5 節介紹了 const 限定符與指針的相互作用,volatile 限定符與指針之間也存在同樣的相互作用。可以聲明 volatile 指針、指向 volatile 對象的指針,以及指向 volatile 對象的 volatile 指針:

volatile?int?v;?????//?v?is?a?volatile?int
?????int?*volatile?vip;??//?vip?is?a?volatile?pointer?to?int
?????volatile?int?*ivp;??//?ivp?is?a?pointer?to?volatile?int
?????
//?vivp?is?a?volatile?pointer?to?volatile?int
?????volatile?int?*volatile?vivp;
?????int?*ip?=?&v;?//?error:?must?use?pointer?to?volatile
?????*ivp?=?&v;????//?ok:?ivp?is?pointer?to?volatile
?????vivp?=?&v;????//?ok:?vivp?is?volatile?pointer?to?volatile

?

像用 const 一樣,只能將 volatile 對象的地址賦給指向 volatile 的指針,或者將指向 volatile 類型的指針復制給指向 volatile 的指針。只有當引用為 volatile 時,我們才可以使用 volatile 對象對引用進行初始化。

?

對待 const 和 volatile 的一個重要區別是,不能使用合成的復制和賦值操作符從 volatile 對象進行初始化或賦值。合成的復制控制成員接受 const 形參,這些形參是對類類型的 const 引用,但是,不能將 volatile 對象傳遞給普通引用或 const 引用。

如果類希望允許復制 volatile 對象,或者,類希望允許從 volatile 操作數或對 volatile 操作數進行賦值,它必須定義自己的復制構造函數和/或賦值操作符版本:

class?Foo?{
?????public:
?????????Foo(const?volatile?Foo&);????//?copy?from?a?volatile?object
?????????
//?assign?from?a?volatile?object?to?a?non?volatile?objet
?????????Foo&?operator=(volatile?const?Foo&);
?????????//?assign?from?a?volatile?object?to?a?volatile?object
?????????Foo&?operator=(volatile?const?Foo&)?volatile;
?????????//?remainder?of?class?Foo
?????};

?

通過將復制控制成員的形參定義為 const volatile 引用,我們可以從任何各類的 Foo 對象進行復制或賦值:普通 Foo 對象、const Foo 對象、volatile Foo 對象或 const volatile Foo 對象。

????

雖然可以定義復制控制成員來處理 volatile 對象,但更深入的問題是復制 volatile 對象是否有意義,對該問題的回答與任意特定程序中使用 volatile 的原因密切相關。

?

(3) 鏈接指示:extern "c"

鏈接指示與函數重載之間的相互作用依賴于目標語言。如果語言支持重載函數,則為該語言實現鏈接指示的編譯器很可能也支持 C++ 的這些函數的重載。

C++ 保證支持的唯一語言是 C。C 語言不支持函數重載,所以,不應該對下面的情況感到驚訝:在一組重載函數中只能為一個 C 函數指定鏈接指示。用帶給定名字的 C 鏈接聲明多于一個函數是錯誤的:

//?error:?two?extern?"C"?functions?in?set?of?overloaded?functions
extern?"C"?void?print(const?char*);
extern?"C"?void?print(int);

在 C++ 程序中,重載 C 函數很常見,但是,重載集合中的其他函數必須都是 C++ 函數:

class?SmallInt?{?/*?...?*/?};
class?BigNum?{?/*?...?*/?};
//?the?C?function?can?be?called?from?C?and?C++?programs
//?the?C++?functions?overload?that?function?and?are?callable?from?C++
extern?"C"?double?calc(double);
extern?SmallInt?calc(const?SmallInt&);
extern?BigNum?calc(const?BigNum&);

?

可以從 C 程序和 C++ 程序調用 calc 的 C 版本。其余函數是帶類型形參的 C++ 函數,只能從 C++ 程序調用。聲明的次序不重要。

編寫函數所用的語言是函數類型的一部分。為了聲明用其他程序設計語言編寫的函數的指針,必須使用鏈接指示:

//?pf?points?to?a?C?function?returning?void?taking?an?int
extern?"C"?void?(*pf)(int);

使用 pf 調用函數的時候,假定該調用是一個 C 函數調用而編譯該函數。

????C 函數的指針與 C++ 函數的指針具有不同的類型,不能將 C 函數的指針初始化或賦值為 C++ 函數的指針(反之亦然)。

存在這種不匹配的時候,會給出編譯時錯誤:

void?(*pf1)(int);?//?points?to?a?C++?function
extern?"C"?void?(*pf2)(int);?//?points?to?a?C?function
pf1?=?pf2;?//?error:?pf1?and?pf2?have?different?types

?

一些 C++ 編譯器可以接受前面的賦值作為語言擴展,盡管嚴格說來它是非法的。

?

?

轉載于:https://www.cnblogs.com/xkfz007/archive/2012/08/15/2639509.html

總結

以上是生活随笔為你收集整理的读书笔记之:C++ Primer (第4版)及习题(ch12-ch18) [++++]的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

亚洲成色www久久网站 | 黑人巨大精品欧美一区二区 | 国产亚洲精品久久久ai换 | 中文字幕乱码人妻二区三区 | 亚洲精品国产品国语在线观看 | 丰满肥臀大屁股熟妇激情视频 | 亚洲天堂2017无码 | 5858s亚洲色大成网站www | 成人综合网亚洲伊人 | 久久综合给合久久狠狠狠97色 | 偷窥村妇洗澡毛毛多 | 亚洲国产欧美国产综合一区 | 久久国产精品二国产精品 | 日产精品99久久久久久 | 少妇无码吹潮 | 国产舌乚八伦偷品w中 | 大屁股大乳丰满人妻 | 少妇的肉体aa片免费 | 久久久久久九九精品久 | 日韩亚洲欧美精品综合 | 国产9 9在线 | 中文 | 亚洲精品午夜国产va久久成人 | 欧美日本免费一区二区三区 | 十八禁真人啪啪免费网站 | 97精品人妻一区二区三区香蕉 | 国产人妻久久精品二区三区老狼 | 爽爽影院免费观看 | 国产成人一区二区三区在线观看 | 国产内射老熟女aaaa | 福利一区二区三区视频在线观看 | 久久成人a毛片免费观看网站 | 久久综合激激的五月天 | 久久无码中文字幕免费影院蜜桃 | 国产在线一区二区三区四区五区 | 一二三四社区在线中文视频 | 无遮无挡爽爽免费视频 | 国产在线aaa片一区二区99 | 国产sm调教视频在线观看 | 日产国产精品亚洲系列 | 亚洲精品午夜国产va久久成人 | 一二三四在线观看免费视频 | 国内精品一区二区三区不卡 | 婷婷综合久久中文字幕蜜桃三电影 | 全黄性性激高免费视频 | 亚欧洲精品在线视频免费观看 | 精品人妻人人做人人爽夜夜爽 | 精品人人妻人人澡人人爽人人 | 亚洲无人区午夜福利码高清完整版 | 成熟妇人a片免费看网站 | 午夜精品久久久久久久 | 亚洲成a人片在线观看无码 | 精品无码一区二区三区爱欲 | 无码国产色欲xxxxx视频 | 2020久久超碰国产精品最新 | 亚洲日韩av一区二区三区四区 | 国产精品va在线播放 | 中文久久乱码一区二区 | 夫妻免费无码v看片 | 清纯唯美经典一区二区 | 国产va免费精品观看 | 国产精品无码永久免费888 | 377p欧洲日本亚洲大胆 | 少妇性荡欲午夜性开放视频剧场 | 亚洲中文字幕在线观看 | 国产精品久久久久久亚洲影视内衣 | 少妇激情av一区二区 | 亚洲国产一区二区三区在线观看 | 狠狠综合久久久久综合网 | 激情综合激情五月俺也去 | 精品无人国产偷自产在线 | 国内揄拍国内精品人妻 | 综合人妻久久一区二区精品 | 三上悠亚人妻中文字幕在线 | 少妇无码一区二区二三区 | 狠狠亚洲超碰狼人久久 | 国内揄拍国内精品少妇国语 | 国产成人一区二区三区在线观看 | 久久精品人妻少妇一区二区三区 | 国产美女精品一区二区三区 | 亚洲成a人片在线观看日本 | 亚洲欧美日韩成人高清在线一区 | 无套内谢的新婚少妇国语播放 | 亚洲中文字幕久久无码 | 国产精华av午夜在线观看 | 国产特级毛片aaaaaaa高清 | 国产人妻人伦精品1国产丝袜 | 色综合久久88色综合天天 | 永久免费精品精品永久-夜色 | 亚洲日韩av一区二区三区四区 | 天天综合网天天综合色 | 精品aⅴ一区二区三区 | 大地资源网第二页免费观看 | аⅴ资源天堂资源库在线 | 131美女爱做视频 | 成人欧美一区二区三区 | 丁香花在线影院观看在线播放 | 青草青草久热国产精品 | 夜夜躁日日躁狠狠久久av | 国产精品美女久久久网av | 日韩成人一区二区三区在线观看 | 国产肉丝袜在线观看 | 激情国产av做激情国产爱 | 色综合天天综合狠狠爱 | 婷婷丁香六月激情综合啪 | 少妇人妻av毛片在线看 | 少妇人妻av毛片在线看 | 麻豆成人精品国产免费 | 欧美国产日韩久久mv | 亚洲中文字幕在线无码一区二区 | 国产性生大片免费观看性 | 国产区女主播在线观看 | 国模大胆一区二区三区 | 久久亚洲中文字幕精品一区 | 无码人妻久久一区二区三区不卡 | 亚洲第一无码av无码专区 | 色偷偷人人澡人人爽人人模 | 国产尤物精品视频 | 人人妻人人澡人人爽人人精品 | 黑人巨大精品欧美黑寡妇 | 亚洲成a人一区二区三区 | 荫蒂添的好舒服视频囗交 | 成在人线av无码免观看麻豆 | 久久精品国产99精品亚洲 | 131美女爱做视频 | 国产精品第一区揄拍无码 | 久久伊人色av天堂九九小黄鸭 | 日本精品高清一区二区 | 红桃av一区二区三区在线无码av | 中文字幕色婷婷在线视频 | 成人av无码一区二区三区 | 5858s亚洲色大成网站www | 亚洲精品午夜国产va久久成人 | 国内少妇偷人精品视频免费 | 99久久无码一区人妻 | 性欧美熟妇videofreesex | 欧美freesex黑人又粗又大 | 国产精品久久久久9999小说 | 伊人久久大香线蕉av一区二区 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 亚洲国产精品无码久久久久高潮 | 欧美人与禽猛交狂配 | 欧美日韩一区二区三区自拍 | 性欧美videos高清精品 | 六月丁香婷婷色狠狠久久 | 亚洲中文字幕久久无码 | 国产精品亚洲一区二区三区喷水 | 国产成人一区二区三区别 | 老子影院午夜伦不卡 | 疯狂三人交性欧美 | 国产精品无码永久免费888 | 亚洲狠狠色丁香婷婷综合 | 夜夜影院未满十八勿进 | 小sao货水好多真紧h无码视频 | 日韩亚洲欧美中文高清在线 | 欧美第一黄网免费网站 | 欧美日韩精品 | 亚洲国产欧美国产综合一区 | 亚洲日韩中文字幕在线播放 | 国产97色在线 | 免 | 帮老师解开蕾丝奶罩吸乳网站 | 香港三级日本三级妇三级 | 粉嫩少妇内射浓精videos | 久久久婷婷五月亚洲97号色 | 国产免费久久精品国产传媒 | 亚洲精品综合五月久久小说 | 亚洲成a人片在线观看无码 | 久久久久亚洲精品中文字幕 | 亚洲国产高清在线观看视频 | 97色伦图片97综合影院 | 综合网日日天干夜夜久久 | 国产精品va在线播放 | 领导边摸边吃奶边做爽在线观看 | 亚洲国产av美女网站 | 18黄暴禁片在线观看 | 亚洲欧洲无卡二区视頻 | 男人扒开女人内裤强吻桶进去 | 午夜精品久久久内射近拍高清 | 亚洲高清偷拍一区二区三区 | 国产sm调教视频在线观看 | 亚洲熟妇色xxxxx欧美老妇y | 少妇高潮一区二区三区99 | 国产人妻精品午夜福利免费 | 欧美35页视频在线观看 | 国产午夜福利亚洲第一 | 2020久久香蕉国产线看观看 | 对白脏话肉麻粗话av | 精品一二三区久久aaa片 | 中文字幕无码热在线视频 | 日本精品人妻无码免费大全 | 人人妻人人澡人人爽欧美精品 | 亚洲精品久久久久久久久久久 | 狂野欧美性猛xxxx乱大交 | 国产 浪潮av性色四虎 | 国产精品久久久 | 国产麻豆精品精东影业av网站 | 成人性做爰aaa片免费看不忠 | 扒开双腿疯狂进出爽爽爽视频 | 国产精品无码一区二区三区不卡 | 乱人伦人妻中文字幕无码 | 国产国产精品人在线视 | 一本久久a久久精品亚洲 | 亚洲色欲色欲欲www在线 | 亚洲欧美国产精品专区久久 | 国产av无码专区亚洲a∨毛片 | 国产精品毛片一区二区 | 六十路熟妇乱子伦 | 无套内谢老熟女 | 国产激情无码一区二区app | 午夜成人1000部免费视频 | 欧洲熟妇精品视频 | 丰满少妇女裸体bbw | 久久亚洲中文字幕无码 | 亚洲日韩av一区二区三区中文 | 亚洲色大成网站www | 久久久久亚洲精品中文字幕 | 亚洲日韩一区二区 | 亚洲成a人片在线观看无码3d | 精品熟女少妇av免费观看 | 国产97在线 | 亚洲 | 国产人妻精品一区二区三区 | 2020最新国产自产精品 | 欧美大屁股xxxxhd黑色 | 成人无码精品1区2区3区免费看 | aa片在线观看视频在线播放 | 成人精品天堂一区二区三区 | 国产内射爽爽大片视频社区在线 | 小泽玛莉亚一区二区视频在线 | 国产精品无码永久免费888 | 色一情一乱一伦一区二区三欧美 | 亚洲成av人片在线观看无码不卡 | 久久综合色之久久综合 | 少妇性俱乐部纵欲狂欢电影 | 三级4级全黄60分钟 | 亚洲人成网站色7799 | 亚洲日韩精品欧美一区二区 | 丰满肥臀大屁股熟妇激情视频 | 自拍偷自拍亚洲精品被多人伦好爽 | av在线亚洲欧洲日产一区二区 | 300部国产真实乱 | 久久久国产精品无码免费专区 | 中文字幕人妻丝袜二区 | 亚洲码国产精品高潮在线 | 在线 国产 欧美 亚洲 天堂 | 久久综合久久自在自线精品自 | 亚洲の无码国产の无码步美 | 国内精品一区二区三区不卡 | 国产亚洲精品久久久ai换 | 中文字幕av伊人av无码av | 无人区乱码一区二区三区 | 日本精品人妻无码77777 天堂一区人妻无码 | 内射老妇bbwx0c0ck | 国内综合精品午夜久久资源 | 亚洲国产av精品一区二区蜜芽 | 图片区 小说区 区 亚洲五月 | 久久久久久a亚洲欧洲av冫 | 一本久久a久久精品亚洲 | 国产高潮视频在线观看 | 性欧美大战久久久久久久 | 老头边吃奶边弄进去呻吟 | 亚洲日本一区二区三区在线 | a国产一区二区免费入口 | 一本久道久久综合婷婷五月 | 亚洲乱亚洲乱妇50p | 亚洲理论电影在线观看 | 人妻少妇精品久久 | 亚洲中文字幕乱码av波多ji | 男女超爽视频免费播放 | 人人爽人人澡人人高潮 | 麻豆国产丝袜白领秘书在线观看 | 国内精品久久毛片一区二区 | 亚洲日韩中文字幕在线播放 | 国产色在线 | 国产 | 久久综合九色综合欧美狠狠 | 中文字幕中文有码在线 | 精品国产av色一区二区深夜久久 | 日韩在线不卡免费视频一区 | 亚洲 a v无 码免 费 成 人 a v | 欧美人与牲动交xxxx | 日韩欧美中文字幕在线三区 | 性欧美videos高清精品 | 高清国产亚洲精品自在久久 | 男女猛烈xx00免费视频试看 | 国产超碰人人爽人人做人人添 | 国产一精品一av一免费 | 女人被爽到呻吟gif动态图视看 | 亚洲成色在线综合网站 | 国产精品理论片在线观看 | 久久久久亚洲精品中文字幕 | 无码任你躁久久久久久久 | 狠狠色噜噜狠狠狠狠7777米奇 | 亚洲人成网站免费播放 | 亚洲人成无码网www | 图片区 小说区 区 亚洲五月 | 午夜熟女插插xx免费视频 | 中文字幕无线码免费人妻 | 成人无码精品一区二区三区 | 三上悠亚人妻中文字幕在线 | 中文字幕无线码免费人妻 | aa片在线观看视频在线播放 | 国产一区二区三区四区五区加勒比 | 亚洲va欧美va天堂v国产综合 | 日本www一道久久久免费榴莲 | 欧美老妇交乱视频在线观看 | 色一情一乱一伦一区二区三欧美 | 日韩视频 中文字幕 视频一区 | 人妻少妇精品无码专区二区 | 久久 国产 尿 小便 嘘嘘 | 色一情一乱一伦一区二区三欧美 | 人妻与老人中文字幕 | 国产成人无码av在线影院 | 色综合久久久无码中文字幕 | 久久精品女人的天堂av | 久久精品国产大片免费观看 | 国产精品无码一区二区桃花视频 | 人妻少妇精品无码专区动漫 | 亚洲精品鲁一鲁一区二区三区 | 成人aaa片一区国产精品 | 东京热一精品无码av | 国产精品久久久av久久久 | 午夜男女很黄的视频 | 又大又硬又爽免费视频 | 精品乱码久久久久久久 | 午夜无码区在线观看 | 999久久久国产精品消防器材 | 丰满少妇熟乱xxxxx视频 | 日本乱人伦片中文三区 | 久久久久99精品成人片 | 午夜免费福利小电影 | 亚洲欧美日韩成人高清在线一区 | 欧美日韩精品 | 国产成人无码av片在线观看不卡 | 亚洲无人区一区二区三区 | 亚洲男人av香蕉爽爽爽爽 | 亚洲熟女一区二区三区 | 精品亚洲韩国一区二区三区 | 一本无码人妻在中文字幕免费 | 国产成人无码a区在线观看视频app | 内射后入在线观看一区 | 国产深夜福利视频在线 | 国产精品欧美成人 | 免费无码av一区二区 | 无码国产乱人伦偷精品视频 | 高清国产亚洲精品自在久久 | 久久亚洲a片com人成 | 图片小说视频一区二区 | 男人和女人高潮免费网站 | 亚洲啪av永久无码精品放毛片 | 大屁股大乳丰满人妻 | 久久久久se色偷偷亚洲精品av | 国产精品国产三级国产专播 | 亚洲综合精品香蕉久久网 | 久久精品中文闷骚内射 | 国内精品人妻无码久久久影院蜜桃 | 天堂在线观看www | 亚洲人成网站免费播放 | 欧洲美熟女乱又伦 | 日韩成人一区二区三区在线观看 | 久久久中文久久久无码 | 国产成人综合在线女婷五月99播放 | 免费乱码人妻系列无码专区 | 亚洲欧美国产精品专区久久 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 在线观看欧美一区二区三区 | 国产精品久久久av久久久 | 亚洲区欧美区综合区自拍区 | 欧美日韩综合一区二区三区 | 国产精品99久久精品爆乳 | 无码av岛国片在线播放 | 亚洲综合色区中文字幕 | 国产亚洲精品久久久久久久久动漫 | 亚洲国产高清在线观看视频 | 嫩b人妻精品一区二区三区 | 亚洲欧美日韩成人高清在线一区 | 欧美性猛交内射兽交老熟妇 | 亚洲成av人片天堂网无码】 | 国产精品久久国产三级国 | 日本成熟视频免费视频 | 中文字幕乱码人妻无码久久 | 天天av天天av天天透 | 国产精品资源一区二区 | 色五月五月丁香亚洲综合网 | 精品水蜜桃久久久久久久 | 纯爱无遮挡h肉动漫在线播放 | 麻豆精品国产精华精华液好用吗 | 国产熟妇另类久久久久 | 免费视频欧美无人区码 | 成人毛片一区二区 | 国产女主播喷水视频在线观看 | 国产午夜福利100集发布 | 一区二区三区高清视频一 | 女人高潮内射99精品 | 97无码免费人妻超级碰碰夜夜 | 天天摸天天碰天天添 | 国产做国产爱免费视频 | 国内精品久久久久久中文字幕 | 天天综合网天天综合色 | 7777奇米四色成人眼影 | 精品欧洲av无码一区二区三区 | 国产真实乱对白精彩久久 | 亚洲欧美日韩综合久久久 | 丰满少妇人妻久久久久久 | 亚洲精品久久久久中文第一幕 | ass日本丰满熟妇pics | 久久婷婷五月综合色国产香蕉 | 亚洲综合伊人久久大杳蕉 | 亚洲熟妇色xxxxx亚洲 | 国产亲子乱弄免费视频 | 中文字幕无码av激情不卡 | 久久亚洲日韩精品一区二区三区 | 人妻少妇精品视频专区 | 久久精品国产大片免费观看 | 丰满人妻精品国产99aⅴ | 又大又紧又粉嫩18p少妇 | 巨爆乳无码视频在线观看 | 牛和人交xxxx欧美 | 国内精品一区二区三区不卡 | 亚洲人交乣女bbw | 六十路熟妇乱子伦 | 成年美女黄网站色大免费全看 | 中文字幕 人妻熟女 | 麻豆国产97在线 | 欧洲 | 久久久亚洲欧洲日产国码αv | 国内精品人妻无码久久久影院 | 国产精品美女久久久网av | 性欧美牲交在线视频 | 性欧美videos高清精品 | 亚洲午夜无码久久 | 国产成人精品久久亚洲高清不卡 | 少妇人妻大乳在线视频 | 亚洲 日韩 欧美 成人 在线观看 | 亚洲成色www久久网站 | 欧美大屁股xxxxhd黑色 | 中文字幕乱码中文乱码51精品 | 老熟女重囗味hdxx69 | 成人亚洲精品久久久久软件 | 欧美阿v高清资源不卡在线播放 | 亚洲国产欧美国产综合一区 | 亚洲国产精品毛片av不卡在线 | 天天爽夜夜爽夜夜爽 | 国产欧美亚洲精品a | 国产69精品久久久久app下载 | 日本大香伊一区二区三区 | 沈阳熟女露脸对白视频 | 精品无码国产一区二区三区av | 国内少妇偷人精品视频 | 中文字幕乱码亚洲无线三区 | 亚洲无人区午夜福利码高清完整版 | 久久久久久av无码免费看大片 | 樱花草在线社区www | 国产激情精品一区二区三区 | 中文字幕无码热在线视频 | 2020最新国产自产精品 | 久久亚洲中文字幕无码 | 色综合久久久久综合一本到桃花网 | 人妻少妇被猛烈进入中文字幕 | 水蜜桃色314在线观看 | 日产精品99久久久久久 | 免费观看激色视频网站 | 婷婷丁香六月激情综合啪 | 天天拍夜夜添久久精品大 | 欧美日韩综合一区二区三区 | 国语精品一区二区三区 | yw尤物av无码国产在线观看 | 无码人妻久久一区二区三区不卡 | 天堂久久天堂av色综合 | 久久精品中文闷骚内射 | 亚洲中文字幕无码中字 | 人人妻人人澡人人爽人人精品浪潮 | 天天躁日日躁狠狠躁免费麻豆 | 99麻豆久久久国产精品免费 | 午夜肉伦伦影院 | 欧美性猛交xxxx富婆 | 午夜福利试看120秒体验区 | 欧美成人免费全部网站 | 思思久久99热只有频精品66 | 丰满少妇高潮惨叫视频 | 少妇人妻大乳在线视频 | 99精品国产综合久久久久五月天 | 伊人久久婷婷五月综合97色 | 中文字幕色婷婷在线视频 | 亚洲 日韩 欧美 成人 在线观看 | 欧美人与善在线com | 亚洲人成网站在线播放942 | 久久99精品久久久久久 | 成人精品天堂一区二区三区 | 亚洲乱码国产乱码精品精 | 久久人人爽人人人人片 | 国产av无码专区亚洲awww | 国产精品无套呻吟在线 | 久久久久亚洲精品中文字幕 | 亚洲成在人网站无码天堂 | 精品国产一区二区三区四区 | 熟妇女人妻丰满少妇中文字幕 | 自拍偷自拍亚洲精品被多人伦好爽 | 97精品人妻一区二区三区香蕉 | 最近的中文字幕在线看视频 | 成人aaa片一区国产精品 | 粉嫩少妇内射浓精videos | 欧美日韩一区二区免费视频 | 亚洲综合色区中文字幕 | 精品一区二区三区无码免费视频 | 亚洲综合无码久久精品综合 | 熟妇人妻中文av无码 | 国产成人无码区免费内射一片色欲 | 亚洲日韩精品欧美一区二区 | 性欧美大战久久久久久久 | 国产亚洲欧美日韩亚洲中文色 | 精品国产国产综合精品 | 97久久超碰中文字幕 | 成人性做爰aaa片免费看 | 亚洲色www成人永久网址 | 午夜熟女插插xx免费视频 | 精品无码国产一区二区三区av | 久久国产精品偷任你爽任你 | 人妻熟女一区 | 欧美午夜特黄aaaaaa片 | 丝袜美腿亚洲一区二区 | 少妇愉情理伦片bd | 亚洲七七久久桃花影院 | 亚洲毛片av日韩av无码 | 久久精品人人做人人综合 | 国产精品亚洲а∨无码播放麻豆 | 欧美成人免费全部网站 | 国模大胆一区二区三区 | 曰本女人与公拘交酡免费视频 | 亚洲精品国产品国语在线观看 | 欧美 日韩 人妻 高清 中文 | 久久精品无码一区二区三区 | 欧美一区二区三区视频在线观看 | 亚洲国产精品毛片av不卡在线 | 精品国产麻豆免费人成网站 | 天堂亚洲2017在线观看 | 一二三四在线观看免费视频 | 欧美日本日韩 | 亚洲中文字幕无码中文字在线 | 在线观看国产一区二区三区 | 又大又黄又粗又爽的免费视频 | 亚洲另类伦春色综合小说 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 麻豆md0077饥渴少妇 | 最新国产麻豆aⅴ精品无码 | 国产又粗又硬又大爽黄老大爷视 | 日本又色又爽又黄的a片18禁 | 精品无码av一区二区三区 | 国产精品无码mv在线观看 | 丁香啪啪综合成人亚洲 | 熟妇人妻无乱码中文字幕 | 午夜精品一区二区三区在线观看 | 亚洲爆乳大丰满无码专区 | 奇米影视7777久久精品人人爽 | www成人国产高清内射 | 国产精品久久久久7777 | 国产亚洲美女精品久久久2020 | 99久久人妻精品免费一区 | 老熟妇仑乱视频一区二区 | 国产成人无码av一区二区 | 亚洲va欧美va天堂v国产综合 | 国产人妻精品一区二区三区 | 国产精品无码成人午夜电影 | 久久综合色之久久综合 | 亚洲区欧美区综合区自拍区 | 久在线观看福利视频 | 成人一在线视频日韩国产 | 亚洲一区二区三区含羞草 | 久久午夜无码鲁丝片午夜精品 | 亚洲小说图区综合在线 | 色综合久久中文娱乐网 | 欧美日韩在线亚洲综合国产人 | www一区二区www免费 | 成人欧美一区二区三区黑人免费 | 欧美成人高清在线播放 | 国内老熟妇对白xxxxhd | 国产av人人夜夜澡人人爽麻豆 | 成人片黄网站色大片免费观看 | 国产亚洲欧美在线专区 | 中文字幕乱码人妻无码久久 | 久久久久成人片免费观看蜜芽 | 麻豆国产97在线 | 欧洲 | 亚洲色www成人永久网址 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 亚洲 a v无 码免 费 成 人 a v | av在线亚洲欧洲日产一区二区 | 99er热精品视频 | 奇米影视7777久久精品人人爽 | 国产熟女一区二区三区四区五区 | 成人欧美一区二区三区黑人免费 | 精品无码av一区二区三区 | 欧洲精品码一区二区三区免费看 | 精品人妻人人做人人爽 | 成人无码精品1区2区3区免费看 | 中文字幕日产无线码一区 | 大色综合色综合网站 | 亚洲一区二区三区偷拍女厕 | 人人澡人人妻人人爽人人蜜桃 | 丰满肥臀大屁股熟妇激情视频 | 亚洲精品中文字幕 | 午夜免费福利小电影 | 97无码免费人妻超级碰碰夜夜 | 永久免费观看美女裸体的网站 | 女人高潮内射99精品 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 亚洲精品中文字幕乱码 | 国内少妇偷人精品视频 | 丝袜美腿亚洲一区二区 | 国内精品久久毛片一区二区 | 国产精品久久国产三级国 | 人人爽人人澡人人人妻 | 激情五月综合色婷婷一区二区 | 在教室伦流澡到高潮hnp视频 | 亚洲理论电影在线观看 | 久久久久se色偷偷亚洲精品av | 久久久久久a亚洲欧洲av冫 | 日本丰满熟妇videos | 少妇的肉体aa片免费 | 国产亚洲精品久久久ai换 | 久久国产精品二国产精品 | 国产做国产爱免费视频 | 国产成人精品必看 | 亚洲国产综合无码一区 | 亚洲一区二区三区在线观看网站 | 内射欧美老妇wbb | 国产极品美女高潮无套在线观看 | 无码av中文字幕免费放 | 狠狠噜狠狠狠狠丁香五月 | 国产亚洲欧美日韩亚洲中文色 | 亚洲爆乳精品无码一区二区三区 | 亚洲成av人影院在线观看 | 亚洲の无码国产の无码影院 | 久久久av男人的天堂 | 亚洲日韩中文字幕在线播放 | 精品国产乱码久久久久乱码 | 欧美性生交xxxxx久久久 | 国产亚洲日韩欧美另类第八页 | 又粗又大又硬又长又爽 | 内射后入在线观看一区 | 日韩av无码中文无码电影 | 亚洲一区二区三区 | 久久99精品久久久久久动态图 | 人人妻人人澡人人爽精品欧美 | 久久久国产精品无码免费专区 | 国产成人无码专区 | 欧美性生交xxxxx久久久 | 老熟妇乱子伦牲交视频 | 亚洲狠狠色丁香婷婷综合 | 鲁大师影院在线观看 | 樱花草在线播放免费中文 | 久久熟妇人妻午夜寂寞影院 | 一本大道伊人av久久综合 | 国产97色在线 | 免 | 特黄特色大片免费播放器图片 | 亚洲综合无码一区二区三区 | 色五月五月丁香亚洲综合网 | 无码人妻精品一区二区三区不卡 | 中文字幕人妻丝袜二区 | 在线a亚洲视频播放在线观看 | 最新版天堂资源中文官网 | 国产97在线 | 亚洲 | 动漫av网站免费观看 | 乱码av麻豆丝袜熟女系列 | 又粗又大又硬又长又爽 | 人人妻在人人 | 国产精品美女久久久久av爽李琼 | 蜜桃臀无码内射一区二区三区 | 欧美高清在线精品一区 | 国产激情一区二区三区 | 精品乱码久久久久久久 | 中文字幕无码乱人伦 | 亚洲娇小与黑人巨大交 | 亚洲精品一区二区三区在线观看 | aⅴ在线视频男人的天堂 | 国产亚洲精品精品国产亚洲综合 | 麻花豆传媒剧国产免费mv在线 | 精品日本一区二区三区在线观看 | 丁香花在线影院观看在线播放 | 国产精品成人av在线观看 | 国产精品无码成人午夜电影 | 久久久久亚洲精品男人的天堂 | 蜜桃视频插满18在线观看 | 少妇性l交大片欧洲热妇乱xxx | 亚洲精品一区二区三区四区五区 | 天堂а√在线地址中文在线 | 午夜精品一区二区三区的区别 | 亚洲熟妇色xxxxx欧美老妇 | 狠狠cao日日穞夜夜穞av | 亚洲理论电影在线观看 | 日韩少妇内射免费播放 | 欧美日韩一区二区综合 | 麻豆人妻少妇精品无码专区 | 无码av免费一区二区三区试看 | 精品国产青草久久久久福利 | 亚洲一区二区三区播放 | 亚洲欧美中文字幕5发布 | 一本无码人妻在中文字幕免费 | 国产乱人伦偷精品视频 | 任你躁国产自任一区二区三区 | 亚洲国精产品一二二线 | 精品无码国产一区二区三区av | 久久久久久久女国产乱让韩 | 无码一区二区三区在线 | 欧美国产日韩久久mv | 国产熟妇另类久久久久 | 精品一区二区三区无码免费视频 | 国产九九九九九九九a片 | 夜夜躁日日躁狠狠久久av | 精品人妻中文字幕有码在线 | 中文字幕无码免费久久9一区9 | 日日碰狠狠躁久久躁蜜桃 | 亚洲欧美中文字幕5发布 | 午夜丰满少妇性开放视频 | 少妇无码一区二区二三区 | 久久久精品欧美一区二区免费 | 中文字幕人妻丝袜二区 | 亚洲色大成网站www | 亚洲小说春色综合另类 | 国产成人一区二区三区在线观看 | 精品人妻人人做人人爽 | 又粗又大又硬又长又爽 | 久9re热视频这里只有精品 | 青青青爽视频在线观看 | 东京热无码av男人的天堂 | 丰满少妇熟乱xxxxx视频 | 国产亚洲日韩欧美另类第八页 | 国产精品亚洲综合色区韩国 | 67194成是人免费无码 | 成人试看120秒体验区 | 高潮毛片无遮挡高清免费视频 | 性欧美熟妇videofreesex | 荫蒂添的好舒服视频囗交 | 国产精品永久免费视频 | 国产成人午夜福利在线播放 | 国产亚洲精品久久久久久久久动漫 | 久久午夜夜伦鲁鲁片无码免费 | 国产精品国产自线拍免费软件 | 男人的天堂2018无码 | 亚洲精品午夜无码电影网 | 国产色精品久久人妻 | 亚洲精品国产第一综合99久久 | 午夜时刻免费入口 | 国产亚洲精品久久久ai换 | 2020久久香蕉国产线看观看 | 漂亮人妻洗澡被公强 日日躁 | 国产成人人人97超碰超爽8 | 欧美亚洲国产一区二区三区 | 中文字幕乱码人妻无码久久 | 国产肉丝袜在线观看 | 欧美精品一区二区精品久久 | 精品国偷自产在线视频 | 亚洲欧美国产精品久久 | 久久亚洲日韩精品一区二区三区 | 2020久久香蕉国产线看观看 | a国产一区二区免费入口 | 欧美日本日韩 | 久久精品国产日本波多野结衣 | 日本乱人伦片中文三区 | 野狼第一精品社区 | 久久久精品国产sm最大网站 | 国产又爽又黄又刺激的视频 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 亚洲一区二区三区无码久久 | 人妻少妇精品无码专区二区 | aa片在线观看视频在线播放 | 久久精品国产精品国产精品污 | 成人av无码一区二区三区 | 欧美日韩一区二区三区自拍 | 国精产品一区二区三区 | 日韩欧美群交p片內射中文 | 国产成人综合色在线观看网站 | 精品国产av色一区二区深夜久久 | 亚洲中文字幕乱码av波多ji | 久久精品视频在线看15 | 好男人社区资源 | 成人精品天堂一区二区三区 | 日本一区二区三区免费高清 | 日韩无码专区 | 亚洲中文无码av永久不收费 | 国产热a欧美热a在线视频 | 无套内射视频囯产 | 国产午夜视频在线观看 | 2020久久香蕉国产线看观看 | 欧洲熟妇精品视频 | 国产精品99久久精品爆乳 | 欧美日韩人成综合在线播放 | 中文字幕av无码一区二区三区电影 | 国产精品久久精品三级 | 国产成人亚洲综合无码 | 亚洲天堂2017无码 | av香港经典三级级 在线 | 亚洲国产欧美日韩精品一区二区三区 | 天堂一区人妻无码 | 人人妻人人澡人人爽人人精品浪潮 | 亚洲va中文字幕无码久久不卡 | 国产香蕉尹人综合在线观看 | 免费观看又污又黄的网站 | 日韩人妻少妇一区二区三区 | 久久综合九色综合97网 | 亚洲区小说区激情区图片区 | 丁香啪啪综合成人亚洲 | √8天堂资源地址中文在线 | 亚洲无人区午夜福利码高清完整版 | 99久久人妻精品免费二区 | 久久久久国色av免费观看性色 | 亚洲乱码国产乱码精品精 | 久久久久成人精品免费播放动漫 | 欧美日本精品一区二区三区 | 玩弄少妇高潮ⅹxxxyw | 亚洲人交乣女bbw | 99久久久无码国产精品免费 | av人摸人人人澡人人超碰下载 | 久久午夜无码鲁丝片午夜精品 | 色婷婷综合激情综在线播放 | 香港三级日本三级妇三级 | 免费无码午夜福利片69 | 55夜色66夜色国产精品视频 | 少妇的肉体aa片免费 | 欧美精品无码一区二区三区 | 高清不卡一区二区三区 | 亚洲七七久久桃花影院 | 国产亚洲精品久久久闺蜜 | 激情国产av做激情国产爱 | 亚洲爆乳精品无码一区二区三区 | 久久久久人妻一区精品色欧美 | 午夜福利试看120秒体验区 | 爆乳一区二区三区无码 | 欧美xxxx黑人又粗又长 | 未满成年国产在线观看 | 97无码免费人妻超级碰碰夜夜 | 装睡被陌生人摸出水好爽 | 老熟妇乱子伦牲交视频 | 亚洲精品国偷拍自产在线观看蜜桃 | 夜先锋av资源网站 | 高清国产亚洲精品自在久久 | 欧美三级不卡在线观看 | 精品无人区无码乱码毛片国产 | 一本精品99久久精品77 | 亚洲欧美国产精品专区久久 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 一本色道婷婷久久欧美 | 欧美日本精品一区二区三区 | 波多野结衣av在线观看 | 久久久中文久久久无码 | 亚洲码国产精品高潮在线 | 成人免费视频一区二区 | 久久综合给合久久狠狠狠97色 | 久久久久亚洲精品男人的天堂 | 国产黑色丝袜在线播放 | 亚洲中文字幕成人无码 | 99久久精品午夜一区二区 | 乌克兰少妇性做爰 | 国产xxx69麻豆国语对白 | 色综合天天综合狠狠爱 | 亚洲中文字幕无码中字 | 日本丰满护士爆乳xxxx | 青春草在线视频免费观看 | 美女毛片一区二区三区四区 | 97夜夜澡人人爽人人喊中国片 | 久久综合色之久久综合 | 色婷婷av一区二区三区之红樱桃 | 成人免费无码大片a毛片 | 久久人妻内射无码一区三区 | 国内精品久久久久久中文字幕 | 激情亚洲一区国产精品 | 午夜熟女插插xx免费视频 | 最新版天堂资源中文官网 | 一本色道久久综合狠狠躁 | 久久久婷婷五月亚洲97号色 | 久久久亚洲欧洲日产国码αv | 国精品人妻无码一区二区三区蜜柚 | 无码成人精品区在线观看 | 99久久亚洲精品无码毛片 | 奇米影视888欧美在线观看 | 久久99精品国产麻豆蜜芽 | 嫩b人妻精品一区二区三区 | 欧美 亚洲 国产 另类 | 亚洲а∨天堂久久精品2021 | 任你躁在线精品免费 | 无码吃奶揉捏奶头高潮视频 | 高清国产亚洲精品自在久久 | 久久99精品国产.久久久久 | 久久精品丝袜高跟鞋 | 久9re热视频这里只有精品 | 午夜精品久久久久久久久 | 亚洲va欧美va天堂v国产综合 | 帮老师解开蕾丝奶罩吸乳网站 | 无码帝国www无码专区色综合 | 少妇人妻偷人精品无码视频 | 伦伦影院午夜理论片 | 日日夜夜撸啊撸 | 亚洲人成人无码网www国产 | 国产xxx69麻豆国语对白 | 国产精品自产拍在线观看 | 国产激情综合五月久久 | 国产亚洲精品久久久久久久 | 国产免费久久久久久无码 | 男人的天堂2018无码 | 国内精品久久久久久中文字幕 | 国产av一区二区精品久久凹凸 | 少妇一晚三次一区二区三区 | 亚洲一区二区三区无码久久 | 亚洲日韩av一区二区三区四区 | 无码午夜成人1000部免费视频 | 成人免费无码大片a毛片 | 丰满人妻一区二区三区免费视频 | 99精品视频在线观看免费 | 初尝人妻少妇中文字幕 | 一本大道久久东京热无码av | av无码久久久久不卡免费网站 | 妺妺窝人体色www在线小说 | 人妻插b视频一区二区三区 | 无码帝国www无码专区色综合 | 一区二区三区高清视频一 | 国产熟妇另类久久久久 | 国产精品18久久久久久麻辣 | 成人一区二区免费视频 | 久精品国产欧美亚洲色aⅴ大片 | 国产精品第一国产精品 | 久久久成人毛片无码 | 日韩欧美群交p片內射中文 | 扒开双腿疯狂进出爽爽爽视频 | 人妻少妇被猛烈进入中文字幕 | 国产人妻精品一区二区三区 | 无码国模国产在线观看 | 国产亚洲视频中文字幕97精品 | 天天摸天天碰天天添 | 人人爽人人澡人人人妻 | 性欧美牲交在线视频 | 欧美日韩色另类综合 | 国产人妻精品午夜福利免费 | 成人av无码一区二区三区 | 美女扒开屁股让男人桶 | 无码吃奶揉捏奶头高潮视频 | 国产精品久久久久7777 | 国产熟妇高潮叫床视频播放 | 国产尤物精品视频 | 亚洲爆乳大丰满无码专区 | 女人被男人爽到呻吟的视频 | 日韩精品久久久肉伦网站 | 亚洲小说图区综合在线 | 玩弄中年熟妇正在播放 | 久久国内精品自在自线 | 好屌草这里只有精品 | 久久午夜夜伦鲁鲁片无码免费 | 欧美xxxxx精品 | 丰满少妇熟乱xxxxx视频 | 欧美老熟妇乱xxxxx | 久久久久免费看成人影片 | 中文字幕无码av波多野吉衣 | 亚洲成a人片在线观看无码3d | 澳门永久av免费网站 | 国内少妇偷人精品视频 | 欧美性生交活xxxxxdddd | 久久国产精品二国产精品 | 55夜色66夜色国产精品视频 | 欧洲vodafone精品性 | 日韩精品无码一本二本三本色 | 给我免费的视频在线观看 | 99久久久无码国产精品免费 | 青青草原综合久久大伊人精品 | 18禁止看的免费污网站 | 亚洲 a v无 码免 费 成 人 a v | 丰满少妇弄高潮了www | 亚洲国产精品久久久久久 | 我要看www免费看插插视频 | 国产成人无码av在线影院 | 18精品久久久无码午夜福利 | 4hu四虎永久在线观看 | av无码电影一区二区三区 | 精品人妻人人做人人爽 | 欧美xxxxx精品 | 亚洲欧洲中文日韩av乱码 | 精品久久久中文字幕人妻 | 亚洲中文字幕在线观看 | 少妇激情av一区二区 | 欧美日韩精品 | 亚洲国产精品一区二区第一页 | 国产精品内射视频免费 | 精品成人av一区二区三区 | 高清不卡一区二区三区 | 久久亚洲国产成人精品性色 | 国产乱子伦视频在线播放 | 国产精品久久福利网站 | 76少妇精品导航 | 中文字幕人妻丝袜二区 | 亚洲阿v天堂在线 | 国产激情综合五月久久 | 国产精品久久久久久久9999 | 97色伦图片97综合影院 | 国产区女主播在线观看 | 国产口爆吞精在线视频 | 亚洲精品中文字幕久久久久 | 免费无码午夜福利片69 | a片免费视频在线观看 | 日本大乳高潮视频在线观看 | 成人亚洲精品久久久久 | 精品人妻中文字幕有码在线 | 曰本女人与公拘交酡免费视频 | 无码人妻出轨黑人中文字幕 | 成人av无码一区二区三区 | 蜜臀aⅴ国产精品久久久国产老师 | 九月婷婷人人澡人人添人人爽 | 精品乱码久久久久久久 | 亚洲精品国产a久久久久久 | 亚洲综合久久一区二区 | 国产亲子乱弄免费视频 | 5858s亚洲色大成网站www | 国产亚洲精品久久久久久 | 色一情一乱一伦一区二区三欧美 | 色综合久久久无码中文字幕 | 美女黄网站人色视频免费国产 | 55夜色66夜色国产精品视频 | 成人无码精品1区2区3区免费看 | 色欲综合久久中文字幕网 | 日韩精品乱码av一区二区 | 久久精品国产一区二区三区 | 熟女少妇在线视频播放 | 日日摸日日碰夜夜爽av | 午夜免费福利小电影 | 成 人 网 站国产免费观看 | 亚洲国产欧美国产综合一区 | 国产农村妇女高潮大叫 | 精品亚洲韩国一区二区三区 | 亚洲成av人影院在线观看 | 伊人久久婷婷五月综合97色 | 高清无码午夜福利视频 | 久久久精品456亚洲影院 | 成人免费视频视频在线观看 免费 | 久青草影院在线观看国产 | 亚洲色偷偷男人的天堂 | 任你躁国产自任一区二区三区 | 性色欲网站人妻丰满中文久久不卡 | 亚洲精品一区二区三区在线观看 | 日韩人妻无码中文字幕视频 | 日韩av无码一区二区三区不卡 | 又粗又大又硬又长又爽 | 国产免费久久久久久无码 | 精品夜夜澡人妻无码av蜜桃 | 欧美丰满少妇xxxx性 | 亚洲熟妇色xxxxx欧美老妇y | 国产欧美精品一区二区三区 | 97无码免费人妻超级碰碰夜夜 | 国产精品久久精品三级 | 性色欲情网站iwww九文堂 | 最近的中文字幕在线看视频 | 国产国语老龄妇女a片 | av无码不卡在线观看免费 | 精品一区二区不卡无码av | 国产手机在线αⅴ片无码观看 | 亚洲乱码日产精品bd | 亚洲国产精品美女久久久久 | 老熟女重囗味hdxx69 | 无码播放一区二区三区 | 国产猛烈高潮尖叫视频免费 | 伊人久久婷婷五月综合97色 | 国产精品99久久精品爆乳 | 97资源共享在线视频 | 最新版天堂资源中文官网 | 亚洲午夜福利在线观看 | 成人免费视频视频在线观看 免费 | 国内精品人妻无码久久久影院 | 内射后入在线观看一区 | 欧美人与牲动交xxxx | 久久人人爽人人爽人人片av高清 | 国精品人妻无码一区二区三区蜜柚 | 亚洲国产精品久久久天堂 | 欧美 日韩 人妻 高清 中文 | 日日天日日夜日日摸 | 久久久久人妻一区精品色欧美 | 一区二区三区高清视频一 | 久久亚洲中文字幕精品一区 | 国产精品人妻一区二区三区四 | 久久久国产精品无码免费专区 | 亚洲七七久久桃花影院 | 久久综合给合久久狠狠狠97色 | 色欲久久久天天天综合网精品 | 大屁股大乳丰满人妻 | 欧美国产日韩久久mv | 人人爽人人澡人人人妻 | 97精品国产97久久久久久免费 | 精品欧洲av无码一区二区三区 | 亚洲国产精品无码久久久久高潮 | 亚洲无人区午夜福利码高清完整版 | 国产三级精品三级男人的天堂 | 日韩精品久久久肉伦网站 | 亚洲另类伦春色综合小说 | 亚洲国精产品一二二线 | 婷婷六月久久综合丁香 | 久久久久se色偷偷亚洲精品av | 俄罗斯老熟妇色xxxx | 精品无码一区二区三区爱欲 | 爽爽影院免费观看 | 97久久超碰中文字幕 | 精品久久久久久人妻无码中文字幕 | 国产免费无码一区二区视频 | 久久人人爽人人爽人人片ⅴ | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 又紧又大又爽精品一区二区 | 成人欧美一区二区三区黑人 | 日本爽爽爽爽爽爽在线观看免 | 中国女人内谢69xxxxxa片 | 窝窝午夜理论片影院 | 中文字幕人妻丝袜二区 | 亚洲综合伊人久久大杳蕉 | 老司机亚洲精品影院 | 国内精品人妻无码久久久影院 | 娇妻被黑人粗大高潮白浆 | 国产精品美女久久久网av | 波多野结衣乳巨码无在线观看 | 扒开双腿疯狂进出爽爽爽视频 | 强奷人妻日本中文字幕 | 久久无码人妻影院 | а√天堂www在线天堂小说 | 亚洲另类伦春色综合小说 | 理论片87福利理论电影 | 亚洲精品综合一区二区三区在线 | 欧美日韩色另类综合 | 99精品无人区乱码1区2区3区 | 日韩人妻无码一区二区三区久久99 | 国产九九九九九九九a片 | 亚拍精品一区二区三区探花 | 婷婷六月久久综合丁香 | av在线亚洲欧洲日产一区二区 | 欧洲极品少妇 | 国产真实伦对白全集 | 亚洲熟妇色xxxxx欧美老妇 | 亚洲精品一区三区三区在线观看 | 国产高清不卡无码视频 | 成人无码视频免费播放 | 欧美国产日韩久久mv | 真人与拘做受免费视频 | 啦啦啦www在线观看免费视频 | 国产人成高清在线视频99最全资源 | 精品熟女少妇av免费观看 | 漂亮人妻洗澡被公强 日日躁 | 青青草原综合久久大伊人精品 | 人妻插b视频一区二区三区 | 国产黄在线观看免费观看不卡 | 在线成人www免费观看视频 | 亚洲码国产精品高潮在线 | 久久精品一区二区三区四区 | 99精品国产综合久久久久五月天 | 日本精品少妇一区二区三区 | 国精产品一区二区三区 | 日韩av激情在线观看 | 捆绑白丝粉色jk震动捧喷白浆 | 色婷婷久久一区二区三区麻豆 | 一个人免费观看的www视频 | 婷婷色婷婷开心五月四房播播 | 亚洲精品一区二区三区在线 | 波多野结衣一区二区三区av免费 | 激情内射日本一区二区三区 | 亚洲中文字幕无码一久久区 | 亚洲精品国偷拍自产在线观看蜜桃 | www国产亚洲精品久久网站 | 熟女少妇在线视频播放 | 人妻少妇精品视频专区 | a国产一区二区免费入口 | 国产综合在线观看 | 色欲av亚洲一区无码少妇 | 特大黑人娇小亚洲女 | 久久精品丝袜高跟鞋 | 中文字幕无码人妻少妇免费 | 未满成年国产在线观看 | 亚洲欧美中文字幕5发布 | 日日碰狠狠躁久久躁蜜桃 | 国产97人人超碰caoprom | 精品国产av色一区二区深夜久久 | 东京热男人av天堂 | 高中生自慰www网站 | 无码人妻出轨黑人中文字幕 | 无码国模国产在线观看 | 蜜桃臀无码内射一区二区三区 | 性欧美大战久久久久久久 | 扒开双腿吃奶呻吟做受视频 | 少妇人妻av毛片在线看 | 永久免费精品精品永久-夜色 | 国产口爆吞精在线视频 | 无码精品人妻一区二区三区av | 久久精品人妻少妇一区二区三区 | 欧美日韩一区二区三区自拍 | 欧美性生交活xxxxxdddd | 香蕉久久久久久av成人 | 亚洲毛片av日韩av无码 | 在线亚洲高清揄拍自拍一品区 | 久久人人97超碰a片精品 | 国产精品办公室沙发 | 欧美日韩人成综合在线播放 | 久久无码专区国产精品s | 人人妻人人澡人人爽欧美一区九九 | 久久无码人妻影院 | 日韩 欧美 动漫 国产 制服 | 男女下面进入的视频免费午夜 | 国产午夜无码精品免费看 | 日日噜噜噜噜夜夜爽亚洲精品 | 国产色精品久久人妻 | 国产亚洲欧美日韩亚洲中文色 | 扒开双腿疯狂进出爽爽爽视频 | 久久亚洲a片com人成 | 激情国产av做激情国产爱 | 日韩精品无码一区二区中文字幕 | 人人妻人人澡人人爽欧美精品 | 人妻互换免费中文字幕 | 国产成人综合美国十次 | 亚洲天堂2017无码中文 | 男女爱爱好爽视频免费看 | 亚洲一区二区三区香蕉 | 日韩欧美群交p片內射中文 | 亚洲国产欧美在线成人 | 国产综合久久久久鬼色 | 日本熟妇人妻xxxxx人hd | 国产在线精品一区二区三区直播 | 色综合久久88色综合天天 | 无码毛片视频一区二区本码 | 丰满人妻被黑人猛烈进入 | 任你躁国产自任一区二区三区 | 双乳奶水饱满少妇呻吟 | 国内精品久久毛片一区二区 | 国产真实夫妇视频 | 免费国产黄网站在线观看 | 亚洲爆乳大丰满无码专区 | 日韩精品无码免费一区二区三区 | 成熟女人特级毛片www免费 | 又紧又大又爽精品一区二区 | 日韩亚洲欧美中文高清在线 | 人妻插b视频一区二区三区 | 99国产精品白浆在线观看免费 | 激情内射亚州一区二区三区爱妻 | 欧美激情综合亚洲一二区 | 国产成人精品优优av | 亚洲一区二区三区含羞草 | 男女爱爱好爽视频免费看 | 欧美精品无码一区二区三区 | 少妇性l交大片 | 中文字幕色婷婷在线视频 | 精品国产成人一区二区三区 | 六十路熟妇乱子伦 | 成年美女黄网站色大免费视频 | 中文毛片无遮挡高清免费 | 亚洲无人区一区二区三区 | 一区二区传媒有限公司 | 国产午夜无码精品免费看 | 国产极品美女高潮无套在线观看 | 熟女少妇人妻中文字幕 | 欧美人妻一区二区三区 | 亚洲国产精品毛片av不卡在线 | 在线播放免费人成毛片乱码 | 国产亚洲精品久久久ai换 | 丰满人妻一区二区三区免费视频 | 中文字幕乱码人妻二区三区 | 久久久精品国产sm最大网站 | 亚洲欧洲日本综合aⅴ在线 | 特黄特色大片免费播放器图片 | 欧美 丝袜 自拍 制服 另类 | 夜精品a片一区二区三区无码白浆 | 午夜嘿嘿嘿影院 | 无码一区二区三区在线观看 | 国产农村乱对白刺激视频 | 中文无码伦av中文字幕 | 国产精品久久久久影院嫩草 | 双乳奶水饱满少妇呻吟 | 免费看男女做好爽好硬视频 | 精品国产福利一区二区 | 国产精品美女久久久 | 久久精品国产亚洲精品 | 少妇性l交大片 | 久久国产精品萌白酱免费 | 少妇高潮一区二区三区99 | 国产午夜福利亚洲第一 | 中文字幕乱码中文乱码51精品 | 国产成人精品久久亚洲高清不卡 | 成人免费视频一区二区 | 亚洲精品久久久久久一区二区 | 精品国产精品久久一区免费式 | 成人无码精品1区2区3区免费看 | 国产麻豆精品一区二区三区v视界 | 大地资源网第二页免费观看 | 性欧美videos高清精品 | 乌克兰少妇性做爰 | 大胆欧美熟妇xx | 国产激情一区二区三区 | 国产精品二区一区二区aⅴ污介绍 | 国产成人无码一二三区视频 | 97资源共享在线视频 | 蜜桃视频韩日免费播放 | 无码人妻精品一区二区三区不卡 | 精品久久久无码人妻字幂 | 国产黄在线观看免费观看不卡 | 久久精品人人做人人综合试看 | 久久99国产综合精品 | 无码人妻精品一区二区三区下载 | 国产精品福利视频导航 | 久久aⅴ免费观看 | 真人与拘做受免费视频一 | 色噜噜亚洲男人的天堂 | 亚洲精品美女久久久久久久 | 色综合久久88色综合天天 | 国产亚洲人成在线播放 | 综合网日日天干夜夜久久 | 亚洲精品欧美二区三区中文字幕 | 领导边摸边吃奶边做爽在线观看 | 欧美午夜特黄aaaaaa片 | 国产精品第一区揄拍无码 | 毛片内射-百度 | 水蜜桃色314在线观看 | 国产黑色丝袜在线播放 | 国产精品手机免费 | 国产午夜精品一区二区三区嫩草 | 在线成人www免费观看视频 | 日韩精品成人一区二区三区 | 亚洲综合精品香蕉久久网 | 玩弄人妻少妇500系列视频 | 亚洲精品一区国产 | 内射巨臀欧美在线视频 | 亚洲日韩av一区二区三区中文 | 曰本女人与公拘交酡免费视频 | 青青久在线视频免费观看 | 婷婷色婷婷开心五月四房播播 | 99国产欧美久久久精品 | 亚洲中文无码av永久不收费 | 国产超级va在线观看视频 | 日本成熟视频免费视频 | 国内揄拍国内精品人妻 | 国产av人人夜夜澡人人爽麻豆 | 久久精品女人的天堂av | 永久免费精品精品永久-夜色 | 国产69精品久久久久app下载 | 久久97精品久久久久久久不卡 | 久久精品女人的天堂av | 人人妻人人澡人人爽欧美一区九九 | 国产 浪潮av性色四虎 | 国产无av码在线观看 | 风流少妇按摩来高潮 | 一二三四在线观看免费视频 | 久久久久亚洲精品中文字幕 | 精品久久综合1区2区3区激情 | 亚洲综合精品香蕉久久网 | 无套内谢老熟女 | 99精品无人区乱码1区2区3区 | 久久久久成人精品免费播放动漫 | 台湾无码一区二区 | 国产黄在线观看免费观看不卡 | 99久久久国产精品无码免费 | 成人亚洲精品久久久久软件 | 激情亚洲一区国产精品 | 亚洲成av人片天堂网无码】 | 99精品久久毛片a片 | 老熟妇仑乱视频一区二区 | 色欲av亚洲一区无码少妇 | 成人片黄网站色大片免费观看 | 久久午夜无码鲁丝片 | 人人妻人人澡人人爽人人精品 | 欧美xxxx黑人又粗又长 | 欧美日本精品一区二区三区 | 国产99久久精品一区二区 | 国语精品一区二区三区 | 成人性做爰aaa片免费看不忠 | 国产三级久久久精品麻豆三级 | 日韩精品a片一区二区三区妖精 | 一个人免费观看的www视频 | 国产极品美女高潮无套在线观看 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 久久综合网欧美色妞网 | 色情久久久av熟女人妻网站 | 亚洲第一网站男人都懂 | 亚洲熟妇色xxxxx欧美老妇y | 丰满人妻被黑人猛烈进入 | 我要看www免费看插插视频 | 伊人久久大香线蕉亚洲 | 国产精品亚洲一区二区三区喷水 | 国产情侣作爱视频免费观看 | 初尝人妻少妇中文字幕 | 亚洲精品国偷拍自产在线观看蜜桃 | 亚洲精品午夜国产va久久成人 | 日韩av无码中文无码电影 | √天堂资源地址中文在线 | 亚洲成a人片在线观看日本 | 日本饥渴人妻欲求不满 | 正在播放老肥熟妇露脸 | 九九久久精品国产免费看小说 | 波多野42部无码喷潮在线 | 精品乱子伦一区二区三区 | 欧美熟妇另类久久久久久多毛 | 无码av岛国片在线播放 | 2020久久超碰国产精品最新 | 国内精品人妻无码久久久影院蜜桃 | 中文字幕无码av激情不卡 | 亚洲中文字幕无码中文字在线 | 99久久人妻精品免费一区 | 日本在线高清不卡免费播放 | 国产综合久久久久鬼色 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 中文字幕乱码人妻无码久久 | 99国产欧美久久久精品 | 亚洲呦女专区 | 国产精品高潮呻吟av久久4虎 | 国内精品久久毛片一区二区 | 大屁股大乳丰满人妻 | 在线观看欧美一区二区三区 | 纯爱无遮挡h肉动漫在线播放 | 扒开双腿吃奶呻吟做受视频 | 野狼第一精品社区 | 日韩欧美成人免费观看 | 曰本女人与公拘交酡免费视频 | 三级4级全黄60分钟 | 国产九九九九九九九a片 | 欧美老熟妇乱xxxxx | 永久免费精品精品永久-夜色 | 成 人 网 站国产免费观看 | 欧美 亚洲 国产 另类 | 亚洲国产日韩a在线播放 | 亚洲乱码中文字幕在线 | 无码精品人妻一区二区三区av | 欧美 日韩 亚洲 在线 | aa片在线观看视频在线播放 | 兔费看少妇性l交大片免费 | 露脸叫床粗话东北少妇 | 精品无人国产偷自产在线 | 牲欲强的熟妇农村老妇女视频 | 精品久久久中文字幕人妻 | 伊人久久大香线蕉午夜 | 久久伊人色av天堂九九小黄鸭 | 久久精品中文字幕大胸 | 国产成人无码a区在线观看视频app | 性开放的女人aaa片 | 亚洲精品久久久久久久久久久 | 性欧美大战久久久久久久 | 99久久久无码国产aaa精品 | 日本精品少妇一区二区三区 | 男女下面进入的视频免费午夜 | 欧美精品无码一区二区三区 | 亚洲精品中文字幕 | 亚洲色欲久久久综合网东京热 | 亚洲精品一区二区三区在线 | 99re在线播放 | 色婷婷av一区二区三区之红樱桃 | 亚洲熟妇色xxxxx欧美老妇 | 久久久国产一区二区三区 | 又紧又大又爽精品一区二区 | 国产综合色产在线精品 | 牲交欧美兽交欧美 | 色一情一乱一伦一视频免费看 | 色婷婷av一区二区三区之红樱桃 | 日本一区二区更新不卡 | 亚洲中文字幕乱码av波多ji | 中文字幕av日韩精品一区二区 | av无码电影一区二区三区 | 久久99热只有频精品8 | 中文字幕无码视频专区 | 国产精品.xx视频.xxtv | 国产av久久久久精东av | 亚洲日韩中文字幕在线播放 | 久久精品女人天堂av免费观看 | 亚洲成在人网站无码天堂 | 四虎影视成人永久免费观看视频 | 麻豆国产97在线 | 欧洲 | 精品人妻av区 | 国产成人无码区免费内射一片色欲 | 国产午夜福利100集发布 | 天天拍夜夜添久久精品 | 男女作爱免费网站 | 国产婷婷色一区二区三区在线 | 国产高清av在线播放 | aⅴ亚洲 日韩 色 图网站 播放 | 免费看男女做好爽好硬视频 | 国产又爽又猛又粗的视频a片 | 亚洲国产高清在线观看视频 | 在线观看免费人成视频 | 亚洲日韩av一区二区三区中文 | 天干天干啦夜天干天2017 | 久久综合激激的五月天 | 一个人免费观看的www视频 | 国产精品99久久精品爆乳 | 欧美丰满少妇xxxx性 | 国产亚洲人成a在线v网站 | 成人免费视频在线观看 | 国产精品亚洲一区二区三区喷水 | 又大又黄又粗又爽的免费视频 | 98国产精品综合一区二区三区 | 老司机亚洲精品影院 | 天海翼激烈高潮到腰振不止 | 无码一区二区三区在线 | 亚洲国产精品毛片av不卡在线 | 三上悠亚人妻中文字幕在线 | 亚洲欧美中文字幕5发布 | 亚洲男女内射在线播放 | 欧美成人免费全部网站 | 国产精品永久免费视频 | 天天拍夜夜添久久精品 | 日产国产精品亚洲系列 | 欧美刺激性大交 | 亚洲区小说区激情区图片区 | 99精品视频在线观看免费 | 国产乱人无码伦av在线a | 欧美日韩在线亚洲综合国产人 | 亚洲国产精品无码一区二区三区 | 性做久久久久久久免费看 | 色五月丁香五月综合五月 | 久久久婷婷五月亚洲97号色 | 又粗又大又硬毛片免费看 | 久久精品人人做人人综合试看 | 亚洲区小说区激情区图片区 | 天下第一社区视频www日本 | 精品乱码久久久久久久 | 亚洲欧美综合区丁香五月小说 | 西西人体www44rt大胆高清 | 在线播放免费人成毛片乱码 | 国产97色在线 | 免 | 牛和人交xxxx欧美 | 亚洲色偷偷偷综合网 | 鲁鲁鲁爽爽爽在线视频观看 | 红桃av一区二区三区在线无码av | 人人澡人人透人人爽 | 色狠狠av一区二区三区 | 国产成人无码av片在线观看不卡 | 国产xxx69麻豆国语对白 | 三级4级全黄60分钟 | 亚洲热妇无码av在线播放 | 强开小婷嫩苞又嫩又紧视频 | 蜜臀av在线播放 久久综合激激的五月天 | 国产精品久久福利网站 | 日日摸天天摸爽爽狠狠97 | 日韩无套无码精品 | 男女爱爱好爽视频免费看 | 中文精品久久久久人妻不卡 | 无码精品人妻一区二区三区av | 又色又爽又黄的美女裸体网站 | 国产乱码精品一品二品 | 国产精品免费大片 | 欧美黑人性暴力猛交喷水 | 婷婷五月综合激情中文字幕 | 久久精品中文闷骚内射 | v一区无码内射国产 | 精品少妇爆乳无码av无码专区 | 高清不卡一区二区三区 | 波多野结衣高清一区二区三区 | 欧美日韩视频无码一区二区三 | 亚洲国产日韩a在线播放 | 图片小说视频一区二区 | 国产成人午夜福利在线播放 | 久久熟妇人妻午夜寂寞影院 | 国产黑色丝袜在线播放 | 一本一道久久综合久久 | 欧美野外疯狂做受xxxx高潮 | 人人妻人人澡人人爽欧美一区九九 | 少妇被粗大的猛进出69影院 | 日韩av无码一区二区三区 | 无码福利日韩神码福利片 | 成人片黄网站色大片免费观看 | 九九在线中文字幕无码 | 无遮挡国产高潮视频免费观看 | 欧美色就是色 | 亚洲中文字幕无码一久久区 | 国产亚洲美女精品久久久2020 | 丰满少妇女裸体bbw | 精品熟女少妇av免费观看 | 亚洲中文字幕在线无码一区二区 | 免费观看黄网站 | 我要看www免费看插插视频 | 日韩少妇白浆无码系列 | 亚洲成在人网站无码天堂 | 狂野欧美性猛交免费视频 | av在线亚洲欧洲日产一区二区 | 久久精品人人做人人综合 | 亚洲熟女一区二区三区 | 一本久道高清无码视频 | 野外少妇愉情中文字幕 | 亚洲精品综合一区二区三区在线 | 亚洲精品一区二区三区在线观看 | 正在播放老肥熟妇露脸 | 国产97在线 | 亚洲 | 少妇人妻偷人精品无码视频 | 成 人影片 免费观看 | 日日碰狠狠躁久久躁蜜桃 | 日日橹狠狠爱欧美视频 | 中文精品无码中文字幕无码专区 | 中文字幕中文有码在线 | 国产精品自产拍在线观看 | 亚洲s色大片在线观看 | 日本一区二区三区免费播放 | 国产sm调教视频在线观看 | 色欲av亚洲一区无码少妇 | 51国偷自产一区二区三区 | 99久久亚洲精品无码毛片 | 久久97精品久久久久久久不卡 | 久久精品一区二区三区四区 | 老头边吃奶边弄进去呻吟 | 亚洲综合久久一区二区 | 男女下面进入的视频免费午夜 | 夜精品a片一区二区三区无码白浆 | 国产av久久久久精东av | 免费观看激色视频网站 | 免费人成在线视频无码 | 国产精品国产三级国产专播 | 国产无遮挡又黄又爽又色 | 国产97人人超碰caoprom | 亚洲狠狠色丁香婷婷综合 | 97久久国产亚洲精品超碰热 | 日日摸天天摸爽爽狠狠97 | 久久亚洲国产成人精品性色 | 国内少妇偷人精品视频免费 | 少妇无码一区二区二三区 | 久久精品国产亚洲精品 | 成人欧美一区二区三区 | 亚洲无人区一区二区三区 | 中文无码伦av中文字幕 | 亚洲日韩中文字幕在线播放 | 亚洲色偷偷男人的天堂 | 女人被男人躁得好爽免费视频 | 久久精品99久久香蕉国产色戒 | 一本久久伊人热热精品中文字幕 | 免费看少妇作爱视频 | 4hu四虎永久在线观看 | 国产精品爱久久久久久久 | 久久亚洲精品成人无码 | 无码精品人妻一区二区三区av | 99riav国产精品视频 | 天天摸天天碰天天添 | 亚洲自偷精品视频自拍 | 3d动漫精品啪啪一区二区中 | 国产极品视觉盛宴 | 国产 精品 自在自线 | 婷婷五月综合缴情在线视频 | 日韩欧美中文字幕公布 | 久久国产劲爆∧v内射 | 亚洲色www成人永久网址 | 2020最新国产自产精品 | 亚洲男人av天堂午夜在 | 亚洲天堂2017无码中文 | 国产一区二区三区四区五区加勒比 | 性色欲网站人妻丰满中文久久不卡 | 水蜜桃色314在线观看 | 精品久久久中文字幕人妻 | 国产精品国产自线拍免费软件 | 国产无遮挡吃胸膜奶免费看 | 欧美 亚洲 国产 另类 | 丰满人妻一区二区三区免费视频 | 免费观看的无遮挡av | 真人与拘做受免费视频一 | 精品无码成人片一区二区98 | 无码人妻精品一区二区三区下载 | 一本久道久久综合狠狠爱 | 国产精品99爱免费视频 | 国产xxx69麻豆国语对白 | 亚洲 另类 在线 欧美 制服 | 日日噜噜噜噜夜夜爽亚洲精品 | 荫蒂添的好舒服视频囗交 | 欧美亚洲国产一区二区三区 | 国产欧美熟妇另类久久久 | 欧美一区二区三区 | 亚洲欧美日韩成人高清在线一区 | 亚洲区欧美区综合区自拍区 | 麻豆成人精品国产免费 | 亚洲一区二区三区香蕉 | 国产午夜视频在线观看 | 亚洲色大成网站www | 国产区女主播在线观看 | 人妻中文无码久热丝袜 | 天堂一区人妻无码 | 无人区乱码一区二区三区 | 荫蒂添的好舒服视频囗交 | 精品国产青草久久久久福利 | 性欧美熟妇videofreesex | 精品乱子伦一区二区三区 | 国内精品人妻无码久久久影院蜜桃 | 亚洲另类伦春色综合小说 | 大乳丰满人妻中文字幕日本 | 欧美丰满熟妇xxxx性ppx人交 | 久久人人爽人人人人片 | 蜜臀av无码人妻精品 | 人妻体内射精一区二区三四 | 曰韩无码二三区中文字幕 | 亚洲精品国产精品乱码视色 | 无码国产激情在线观看 | 四虎4hu永久免费 | 强伦人妻一区二区三区视频18 | 久久天天躁狠狠躁夜夜免费观看 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 亚洲欧美日韩成人高清在线一区 |