青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

牽著老婆滿街逛

嚴(yán)以律己,寬以待人. 三思而后行.
GMail/GTalk: yanglinbo#google.com;
MSN/Email: tx7do#yahoo.com.cn;
QQ: 3 0 3 3 9 6 9 2 0 .

STL實(shí)踐指南

作者:Jeff Bogan
原文:http://www.codeproject.com/vcpp/stl/PracticalGuideStl.asp
翻譯:Winter
Winter注: 這是一篇非常不錯(cuò)的文章,以前周翔已經(jīng)翻譯過了。只是感覺翻譯得有些欠妥之處,特別是一些術(shù)語的翻譯,因此這里重新翻譯。

1 介紹

對(duì)于當(dāng)今所有C++程序員來說,STL(標(biāo)準(zhǔn)模板庫的縮寫)都是非常不錯(cuò)的技術(shù)。但我必須要提醒的是要想習(xí)慣使用有一定難度,例如,會(huì)有很陡峭的學(xué)習(xí)曲線,其使用許多名字也不是憑直覺就可以知道其意思(或許是因?yàn)樗泻糜浀拿侄急挥霉饬耍5坏┠銓W(xué)會(huì)了STL,你將會(huì)因此而受益匪淺。和MFC的容器相比,STL更加靈活且功能強(qiáng)大。

其優(yōu)勢(shì)如下:

  1. 能方便的排序和搜索。
  2. 更安全且更容易調(diào)試。
  3. 你能讀懂Unix程序員的代碼注1
  4. 將為你的簡(jiǎn)歷上增加技能。

2 背景

寫本文檔的目的在于讓讀者可以在這富有挑戰(zhàn)性的計(jì)算機(jī)科學(xué)領(lǐng)域有個(gè)良好的開端,不必費(fèi)力地了解那無窮無盡的行話術(shù)語和沉悶的規(guī)則,那些行話和規(guī)則只是STLer們用于自娛的創(chuàng)造品。

3 使用代碼

本文檔中的代碼對(duì)讀者在使用STL實(shí)踐之路上有很強(qiáng)的指導(dǎo)作用。

4 定義

  • 模板(template)-- 類(以及結(jié)構(gòu)、數(shù)據(jù)類型、和函數(shù))的宏。有時(shí)也叫cookie cutter. 同時(shí)和已知范型(generic)形式一樣--一個(gè)類模板叫范型類,同樣,一個(gè)函數(shù)模板叫范型函數(shù)。
  • STL -- 標(biāo)準(zhǔn)模板庫,由一群聰明人寫的模板,現(xiàn)在作為標(biāo)準(zhǔn)C++語言的一部分被所有人使用。
  • 容器(container) -- 可容納一定數(shù)據(jù)的類。在STL中有vector, set, map, multimap, deque等容器。
  • vector -- 一個(gè)基礎(chǔ)的數(shù)據(jù)模板,是一種容器。
  • 迭代器(Iterator) -- 一個(gè)非常有意思的詞,其實(shí)是STL容器內(nèi)部元素的指針。它同時(shí)完成其他許多功能。

5 Hello Word 程序

I always wanted to write one and here is my golden 24 karet opportunity: a hello world program. 這個(gè)程序把一個(gè)字符串轉(zhuǎn)換為一個(gè)字符vector,然后以逐個(gè)字符顯示整個(gè)字符串。vector就像是盛放變長(zhǎng)數(shù)組的花園,在STL所有容器中,大約有一半是基于vector的,故可以這么說,尚若你掌握了這個(gè)程序,那么你就理解了整個(gè)STL的一半了

//?Program:?Vector?Demo?1
//?Purpose:?用于演示STL?vector

//?#include?"stdafx.h"?-?如果你使用預(yù)編譯需要包含此文件[[#ExplainIn2][注2]]
#include?<vector>??//?STL?vector?頭文件.?注意,并沒有".h"
#include?<iostream>??//?需要用到?cout
using?namespace?std;??//?確保命名空間是?std

char*?szHW?=?"Hello?World";??
//?眾所周知,這是個(gè)以NULL結(jié)尾的字符數(shù)組?

int?main(int?argc,?char*?argv[])
{
??vector?
<char>?vec;??//?一個(gè)字符類型的vector(相當(dāng)于STL中的數(shù)組)

??
//?為字符vector定義迭代器
??vector?<char>::iterator?vi;

??
//?初始化字符vector,循環(huán)整個(gè)字符串,把每個(gè)字符放入vector中,直至字符串末尾的NULL字符
??char*?cptr?=?szHW;??//??Hello?World?字符串的首地址
??while?(*cptr?!=?'\0')
??
{??vec.push_back(*cptr);??cptr++;??}
??
//?push_back?函數(shù)把數(shù)據(jù)插入vector的最后?

??
//?把存在STL數(shù)組中的每個(gè)字符打印到屏幕上
??for?(vi=vec.begin();?vi!=vec.end();?vi++)??
??
//?這就是在STL中循環(huán)的標(biāo)準(zhǔn)判斷方式-?經(jīng)常使用?"!="?而不是?"<"?
??
//?某些容器可能并沒有重載操作符?"<"?。?
??
//begin()和end()會(huì)得到vector的開頭和結(jié)尾兩個(gè)元素的迭代器(指針)?
??{??cout?<<?*vi;??}??//?使用間接操作符(*)從迭代器中取得數(shù)據(jù)
??cout?<<?endl;??//?輸出完畢,打印?"\n"

??
return?0;
}

push_back 是用來向vector或deque容器中插入數(shù)據(jù)的標(biāo)準(zhǔn)函數(shù)。insert是類似功能的函數(shù),適用于所有容器,但用法更復(fù)雜。end()實(shí)際上表示在最后的位置再加一,以便循環(huán)可以正常執(zhí)行 - 它返回的指針指向最靠近數(shù)組界限的數(shù)據(jù)。就像普通循環(huán)中的數(shù)組,比如for (i=0; i<6; i++) {ar[i] = i;} ——ar[6]是不存在的,在循環(huán)中不會(huì)達(dá)到這個(gè)元素,所以在循環(huán)中不會(huì)出現(xiàn)問題。

6 STL的煩惱之一:

STL令人煩惱的地方是在它初始化的時(shí)候。STL中容器的初始化比C/C++數(shù)組初始化要麻煩的多。你只能一個(gè)元素一個(gè)元素地來,或者先初始化一個(gè)普通數(shù)組再通過轉(zhuǎn)化填放到容器中。我認(rèn)為人們通常可以這樣做:

//?Program:?Initialization?Demo
//?Purpose:?To?demonstrate?initialization?of?STL?vectors

#include?
<cstring>??//?same?as?<string.h>
#include?<vector>
using?namespace?std;

int?ar[10]?=?{??12,?45,?234,?64,?12,?35,?63,?23,?12,?55??};
char*?str?=?"Hello?World";

int?main(int?argc,?char*?argv[])
{
??vector?
<int>?vec1(ar,?ar+10);
??vector?
<char>?vec2(str,?str+strlen(str));
??
return?0;
}

在編程中,有很多種方法來完成同樣的工作。另一種填充向量的方法是用更加熟悉的方括號(hào),例如:
//?Program:?Vector?Demo?2
//?Purpose:?To?demonstrate?STL?vectors?with
//?counters?and?square?brackets

#include?
<cstring>
#include?
<vector>
#include?
<iostream>
using?namespace?std;

char*?szHW?=?"Hello?World";
int?main(int?argc,?char*?argv[])
{
??vector?
<char>?vec(strlen(sHW));?
??
//?The?argument?initializes?the?memory?footprint
??int?i,?k?=?0;
??
char*?cptr?=?szHW;
??
while?(*cptr?!=?'\0')
??
{??vec[k]?=?*cptr;??cptr++;??k++;??}
??
for?(i=0;?i<vec.size();?i++)
??
{??cout?<<?vec[i];??}
??cout?
<<?endl;
??
return?0;
}

這個(gè)例子更加清晰,但沒有使用迭代器(iterator)操作,并且定義了額外的整數(shù)作為下標(biāo),而且,你必須清楚地在程序中說明為vector分配多少內(nèi)存空間。

7 命名空間(namespace)

與STL相關(guān)的概念是命名空間(namespace)。STL定義在std命名空間中。有3種方法聲明使用的命名空間:

  1. 用using關(guān)鍵字使用這個(gè)命名空間,在文件的頂部,但在聲明的頭文件下面加入:
using namespace std;
最于簡(jiǎn)單工程來說,這是最簡(jiǎn)單也是最佳方式。直接把你的代碼定位到std命名空間,

This is the simplest and best for simple projects, limits you to the std namespace, anything you add is improperly put in the std namespace (I think you go to heck for doing this).

  1. Specify each and every template before use (like prototyping)

using std::cout; using std::endl; using std::flush; using std::set; using std::inserter;

This is slightly more tedious, although a good mnemonic for the functions that will be used, and you can interlace other namespaces easily.

  1. EVERY time you use a template from the std namespace, use the std scope specifier.

typedef std::vector VEC_STR;

This is tedious but the best way if you are mixing and matching lots of namespaces. Some STL zealots will always use this and call anyone evil who does not. Some people will create macros to simplify matters.

In addition, you can put using namespace std within any scope, for example, at the top of a function or within a control loop. Some Tips

To avoid an annoying error code in debug mode, use the following compiler pragma:

#pragma warning(disable: 4786)

Another gotcha is: you must make sure that the spaces are placed between your angle brackets and the name. This is because >> is the bit shift operator, so:

vector <list<int>> veclis;

will give an error. Instead, write it:

vector > veclis;

to avoid compilation errors. Another Container - The set

This is the explanation lifted from the MS help file of the set: "The template class describes an object that controls a varying-length sequence of elements of type const Key. Each element serves as both a sort key and a value. The sequence is represented in a way that permits lookup, insertion, and removal of an arbitrary element with a number of operations proportional to the logarithm of the number of elements in the sequence (logarithmic time). Moreover, inserting an element invalidates no iterators, and removing an element invalidates only those iterators that point at the removed element."

An alternate, more practical, definition is: A set is a container that contains all unique values. This is useful for cases in which you are required to collect the occurrence of value. It is sorted in an order that is specified at the instantiation of the set. If you need to store data with a key/value pair, then a map is a better choice. A set is organized as a linked list, is faster than a vector on insertion and removal, but slightly slower on search and addition to end.

An example program would be:

// Program: Set Demo // Purpose: To demonstrate STL sets

#include #include #include using namespace std;

int main(int argc, char* argv[]) { set strset; set ::iterator si; strset.insert("cantaloupes"); strset.insert("apple"); strset.insert("orange"); strset.insert("banana"); strset.insert("grapes"); strset.insert("grapes"); // This one overwrites the previous occurrence for (si=strset.begin(); si!=strset.end(); si++) { cout << *si << " "; } cout << endl; return 0; }

// Output: apple banana cantaloupes grapes orange

If you want to become an STL fanatic, you can also replace the output loop in the program with the following lines.

copy(strset.begin(), strset.end(), ostream_iterator(cout, " "));

While instructive, I find this personally less clear and prone to error. If you see it, now you know what it does. All the STL Containers

Containers pre-date templates and are computer science concepts that have been incorporated into STL. The following are the seven containers implemented in STL.

* vector - Your standard safe array. It is expanded in the "front" direction only. * deque - Functionally the same as a vector. Internally, it is different. It can be expanded in both the front and back. * list - Can only be traversed one step at time. If you are already familiar with the concept of a list, an STL list is doubly linked (contains pointer to both the previous and next value). * set - contains unique values that are sorted. * map - sorted set of paired values, one of which is the key on which sorts and searches occur, and the value which is retrieved from the container. E.g. instead of ar[43] = "overripe", a map lets you do this ar["banana"] = "overripe". So if you wanted to draw up a bit of information keyed on full name is easily done. * multiset - same as a set, but does not necessarily have unique values. * multimap - same as a map, but does not necessarily have unique keys.

Note: If you are reading the MFC help then you will also come across the efficiency statement of each container. I.E. (log n * n) insertion time. Unless you are dealing with very large number of values, you should ignore this. If you start to get a noticeable lag or are dealing with time critical stuff then you should learn more about the proper efficiency of various containers. How to Use a Map with some Class

The map is a template that uses a key to obtain a value.

Another issue is that you will want to use your own classes instead of data types, like int that has been used up to now. To create a class that is "template-ready", you must be ensure that the class contains certain member functions and operators. The basics are:

* default constructor (empty, usually) * copy constructor * overload "="

You would overload more operators as required in a specific template, for example, if you plan to have a class that is a key in a map you would have to overload relational operators. But that is another story.

// Program: Map Own Class // Purpose: To demonstrate a map of classes

#include #include #include #include using namespace std;

class CStudent { public : int nStudentID; int nAge; public : // Default Constructor - Empty CStudent() { } // Full constructor CStudent(int nSID, int nA) { nStudentID=nSID; nAge=nA; } // Copy constructor CStudent(const CStudent& ob) { nStudentID=ob.nStudentID; nAge=ob.nAge; } // Overload = void operator = (const CStudent& ob) { nStudentID=ob.nStudentID; nAge=ob.nAge; } };

int main(int argc, char* argv[]) { map mapStudent;

mapStudent["Joe Lennon"] = CStudent(103547, 22); mapStudent["Phil McCartney

// Access via the name cout << "The Student number for Joe Lennon is " << (mapStudent["Joe Lennon"].nStudentID) << endl;

return 0; }

TYPEDEF

If you like to use typedef, this an example:

typedef set SET_INT; typedef SET_INT::iterator SET_INT_ITER

One convention is to make them upper case with underscores. ANSI / ISO string

ANSI/ISO strings are commonly used within STL containers. It is your standard string class, widely praised except for its deficiency of no format statement. You must instead use << and the iostream codes (dec, width, etc.) to string together your string.

Use c_str() to retrieve a character pointer, when necessary. Iterators

I said that iterators are pointers, but there is more. They look like pointers, act like pointers, but they are actually embedded in which the indirection operator (unary *) and -> have been overloaded to return a value from the container. It is a bad idea to store them for any length of time, as they usually invalid after a value has been added or removed from a container. They are something like handles in this regard. The plain iterator can be altered, so that the container is to be traversed in different ways:

* iterator - For any container other than the vector, you can only step one at a time in a forward direction through the container. That is you can only use the ++ operator, not the -- or += operator on it. For vector only you can use any of +=, --, -=, ++, and all the comparison operators <, <=, >, >=, =, . * reverse_iterator - If you want to step backwards instead of forwards through a non-vector container, replace iterator with reverse_iterator, begin() with rbegin(), and end() with rend(), ++ will then traverse backwards. * const_iterator - a forward iterator that returns a const value. Use this if you want to make it clear that this points to a read-only value. * const_reverse_iterator - a reverse iterator that returns a const value.

Sorting Order in Sets and Maps

Templates have other parameters besides the type of value. You can also pass callback functions (known as predicates - this is a function of one argument that returns a bool value). For example, say you want a set of strings that are automatically sorting in ascending order. You would simply create a set class in this way:

set > set1

greater is another template for a function (generic function) which is used to sort values, as they are placed into the container. If you wanted the set to be sorted in descending order, you would write:

set > set1

There are many other cased you must pass a predicate as parameter to the STL class, in algorithms, described below. STL Annoyance #2 - Long Error Messages

The templated names get expanded for the compiler, so when the compiler chokes on something, it spits out extremely long error messages that are difficult to read. I have found no good way around this. The best is to develop the ability to find and focus on the end of the error code where the explanation is located. Another related annoyance: if you double click on the template error, it will take you to the point in the code within the template code, which is also difficult to read. Sometimes, it is best just to carefully re-examine your code, and ignore the error messages completely. Algorithms

Algorithms are functions that apply to templates. This is where the real power of STL starts to show up. You can learn a few function names that usually apply to most of the template containers. You can sort, search, manipulate, and swap with the greatest of ease. They always contain a range within which the algorithm performs. E.g.: sort(vec.begin()+1, vec.end()-1) sorts everything but the first and last values.

The container itself is not passed to the algorithm, just two iterators from the container that bookend a range. In this way, algorithms are not restricted by containers directly, but by the iterators supported by that specific algorithm. In addition, many times you will also pass a name of a specially prepared function (those afore mentioned predicates) as an argument. You can even pass plain old values.

Example of algorithms in play:

?

//?Program:?Test?Score?//?Purpose:?To?demonstrate?the?use?of?algorithm?//?with?respect?to?a?vector?of?test?scores?

#include?
//?If?you?want?to?use?an?//?algorithm?this?is?the?header?used.?#include?//?(For?Accumulate)?#include?#include?using?namespace?std;?

int?testscore[]?=?{67,?56,?24,?78,?99,?87,?56};?

//?predicate?that?evaluates?a?passed?test?bool?passed_test(int?n)?{?return?(n?>=?60);?}?

//?predicate?that?evaluates?a?failed?test?bool?failed_test(int?n)?{?return?(n?<?60);?}?

int?main(int?argc,?char*?argv[])?{?int?total;?//?Initialize?a?vector?with?the?data?in?the?testscore?array?vector?vecTestScore(testscore,?testscore?+?sizeof(testscore)?/?sizeof(int));?vector?::iterator?vi;?

//?Sort?and?display?the?vector?sort(vecTestScore.begin(),?vecTestScore.end());?cout?<<?"Sorted?Test?Scores:"?<<?endl;?for?(vi=vecTestScore.begin();?vi?=?vecTestScore.end();?vi++)?{?cout?<<?*vi?<<?",?";?}?cout?<<?endl;?

//?Display?statistics?

//?min_element?returns?an?iterator?to?the?//?element?that?is?the?minimum?value?in?the?range?//?Therefor?*?operator?must?be?used?to?extract?the?value?vi?=?min_element(vecTestScore.begin(),?vecTestScore.end());?cout?<<?"The?lowest?score?was?"?<<?*vi?<<?"."?<<?endl;?

//?Same?with?max_element?vi?=?max_element(vecTestScore.begin(),?vecTestScore.end());?cout?<<?"The?highest?score?was?"?<<?*vi?<<?"."?<<?endl;?

//?Use?a?predicate?function?to?determine?the?number?who?passed?cout?<<?count_if(vecTestScore.begin(),?vecTestScore.end(),?passed_test)?<<?"?out?of?"?<<?vecTestScore.size()?<<?"?students?passed?the?test"?<<?endl;?

//?and?who?failed?cout?<<?count_if(vecTestScore.begin(),?vecTestScore.end(),?failed_test)?<<?"?out?of?"?<<?vecTestScore.size()?<<?"?students?failed?the?test"?<<?endl;?

//?Sum?the?scores?total?=?accumulate(vecTestScore.begin(),?vecTestScore.end(),?0);?//?Then?display?the?Average?cout?<<?"Average?score?was?"?<<?(total?/?(int)(vecTestScore.size()))?<<?endl;?

return?0;?}
?

?

See you later, Allocator

These are used in the initialization stages of a template. They are mysterious behind the scenes type of creatures, and really only of concern if you are doing high level memory optimization, and are best considered to be black boxes. Usually, you never even specify them as they are default parameters that are generally not tinkered with. It is best to know what they are though in case they show up on one of those employment tests. Derive or Embed Templates

Any way that you use a regular class, you can use an STL class.

It can be embedded:

?

class?CParam?{?string?name;?string?unit;?vector?vecData;?};?

?

or used as a base class:

?

class?CParam?:?public?vector?{?string?name;?string?unit;?};?

?

Derivation should be used with some caution. It is up to you as to the form that fits your programming style. Templates within Templates

To create a more complex data structure, you can nest a template within a template. It is best to typedef beforehand on the internal template as you will certainly need to use the inner template again.

?

//?Program:?Vector?of?Vectors?Demo?//?Purpose:?To?demonstrate?nested?STL?containers?

#include?#include?

using?namespace?std;?

typedef?vector?VEC_INT;?

int?inp[2][2]?=?{{1,?1},?{2,?0}};?//?Regular?2x2?array?to?place?into?the?template?int?main(int?argc,?char*?argv[])?{?int?i,?j;?vector?vecvec;?//?if?you?want?to?do?this?in?all?one?step?it?looks?like?this?//?vector?>?vecvec;?

//?Fill?it?in?with?the?array?VEC_INT?v0(inp[0],?inp[0]+2);?//?passing?two?pointers?//?for?the?range?of?values?to?be?copied?to?the?vector?VEC_INT?v1(inp[1],?inp[1]+2);?

vecvec.push_back(v0);?vecvec.push_back(v1);?

for?(i=0;?i<2;?i++)?{?for?(j=0;?j<2;?j++)?{?cout?<<?vecvec[i][j]?<<?"?";?}?cout?<<?endl;?}?return?0;?}?

?

// Output: // 1 1 // 2 0

Although cumbersome to initialize, once completed and filled in, you have a 2 dimensional array that is indefinitely expandable (until memory space runs out). The same can be done for any combination of containers, as the situation requires. Conclusion

STL is useful, but not without its annoyances. As the Chinese say: if you learn it, you will be like a tiger with the claws of a lion.

20 譯者注

[ 注1 ] STL是可以跨平臺(tái)的,此處是對(duì)使用Windows平臺(tái)的讀者來說。
[ 注2 ] 在使用VC時(shí),如果選擇預(yù)編譯,則每個(gè)cpp文件開頭必須包含一個(gè)頭文件:"stdafx.h"

-- WinterWen - 25 Jun 2005

posted on 2006-04-25 22:41 楊粼波 閱讀(490) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 文章收藏

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久人人爽爽爽人久久久| 免费一级欧美片在线播放| 中文无字幕一区二区三区| 国产一区清纯| 农村妇女精品| 久久久久久久久蜜桃| 亚洲综合色丁香婷婷六月图片| 久久久亚洲成人| 亚洲一区二区三区影院| 91久久精品日日躁夜夜躁欧美| 久久天天躁狠狠躁夜夜av| 欧美亚洲专区| 亚洲永久字幕| 亚洲午夜久久久久久尤物| 夜夜嗨av色综合久久久综合网| 91久久一区二区| 在线观看亚洲a| 国产精品电影网站| 国产精品激情av在线播放| 国产精品成人播放| 国产欧美日韩综合一区在线播放| 欧美国产高潮xxxx1819| 亚洲国产婷婷香蕉久久久久久99| 欧美成人小视频| 亚洲大胆人体在线| 亚洲精品在线二区| 亚洲国产视频直播| 亚洲一区二区三区国产| 亚洲欧美在线磁力| 久久久久久国产精品一区| 亚洲午夜在线视频| 久久er99精品| 欧美激情第10页| 国产精品亚洲精品| 亚洲国产aⅴ天堂久久| 国产欧美精品一区二区色综合| 亚洲人成7777| 久久精品日韩| 久久青草欧美一区二区三区| 亚洲永久视频| 久久米奇亚洲| 欧美日韩在线免费| 欧美日韩成人一区| 国产亚洲精品一区二区| 亚洲国产欧美不卡在线观看| 国产精品99久久久久久久久久久久| 欧美亚洲免费| 亚洲影院一区| 欧美国产日韩一区二区在线观看 | 午夜久久tv| 欧美福利一区| 亚洲一区在线播放| 欧美激情中文不卡| 国外成人在线视频网站| 99re66热这里只有精品3直播| 久久精品视频在线看| 亚洲国产精品久久人人爱蜜臀 | 久久久精品国产一区二区三区| 欧美激情亚洲视频| 亚洲日韩欧美一区二区在线| 欧美中文字幕在线| 国内不卡一区二区三区| 欧美一区二区日韩| 亚洲小视频在线| 欧美三区在线视频| 日韩午夜免费视频| 午夜天堂精品久久久久| 亚洲伊人伊色伊影伊综合网| 欧美日韩播放| 亚洲在线观看视频| 亚洲精品日韩在线观看| 亚洲在线观看视频网站| 国产精品久久亚洲7777| 一区二区三区 在线观看视| 亚洲日本激情| 欧美日韩第一区日日骚| 亚洲精品综合| 亚洲视频视频在线| 国产精品v欧美精品∨日韩| 亚洲女同性videos| 亚洲午夜电影网| 国产精品一区二区久久| 久久久久久日产精品| 欧美在线不卡视频| 最新国产精品拍自在线播放| 亚洲第一区色| 欧美精品一卡| 免费国产一区二区| 乱中年女人伦av一区二区| 国产一区久久| 91久久国产综合久久| 欧美国产成人精品| 国产在线一区二区三区四区 | 欧美丰满少妇xxxbbb| 亚洲国产日韩一级| 亚洲日本视频| 国产日韩在线一区| 久久亚洲风情| 免费在线观看精品| 一区二区高清视频在线观看| 一本色道久久综合狠狠躁篇怎么玩| 国产欧美日韩三区| 麻豆精品传媒视频| 欧美专区在线观看一区| 亚洲毛片视频| 亚洲欧美成人网| 日韩午夜剧场| 午夜精品短视频| 国产一区二区三区精品久久久| 欧美本精品男人aⅴ天堂| 欧美国产日韩一二三区| 久久综合九色综合久99| 欧美精品午夜视频| 国产视频亚洲| 欧美成黄导航| 国产精品v日韩精品| 亚洲电影在线看| 国产麻豆成人精品| 欧美激情第10页| 伊人夜夜躁av伊人久久| 亚洲素人一区二区| 亚洲一二三区在线| 久久综合九色综合欧美狠狠| 亚洲深夜福利视频| 欧美久久精品午夜青青大伊人| 久久丁香综合五月国产三级网站| 羞羞色国产精品| 欧美一二区视频| 欧美激情精品久久久久久| 欧美18av| 国产小视频国产精品| 亚洲伊人网站| 亚洲午夜小视频| 午夜精品久久久久久久99樱桃| 亚洲欧美国产日韩天堂区| 欧美大片免费观看在线观看网站推荐| 久久免费99精品久久久久久| 欧美天天视频| 久久精品综合网| 国内精品久久久久久影视8| 亚洲午夜激情网站| 久久成人18免费观看| 国产精品高潮呻吟久久av黑人| 久久人91精品久久久久久不卡 | 午夜精品电影| 亚洲一区在线免费观看| 欧美高清一区二区| 欧美黄色日本| 欧美一区二区三区免费观看| 国产精品99久久99久久久二8| 亚洲国产另类久久精品| 亚洲一级二级在线| 在线亚洲一区二区| 欧美日韩另类在线| 日韩午夜三级在线| 一本高清dvd不卡在线观看| 欧美激情网站在线观看| 一本色道久久综合亚洲91| 亚洲天堂成人在线视频| 国产精品一区久久久| 欧美一区二区三区另类 | 亚洲线精品一区二区三区八戒| 免费亚洲婷婷| 亚洲国产日韩美| 午夜久久久久久久久久一区二区| 欧美体内谢she精2性欧美| 性欧美办公室18xxxxhd| 久久精品一区二区三区四区| 国产精品激情| 久久国产一区| 久久精品国产久精国产一老狼 | 先锋亚洲精品| 亚洲国产成人不卡| 欧美另类视频| 午夜宅男欧美| 蜜桃久久av一区| 国产精品久久久一区二区三区| 久久国产精品第一页| 欧美成人精品三级在线观看 | 国产精品爽爽ⅴa在线观看| 欧美影院精品一区| 欧美国产日韩免费| 在线亚洲观看| 影音先锋欧美精品| 欧美精品v国产精品v日韩精品| 欧美激情一区二区三区蜜桃视频| 亚洲图片自拍偷拍| 国产欧美日本| 欧美日韩国产色综合一二三四| 亚洲天堂免费在线观看视频| 欧美福利视频| 午夜精品久久久久久久99黑人| 亚洲国产精品久久久久秋霞蜜臀| 欧美日韩xxxxx| 亚洲视频在线观看网站| 亚洲电影av在线| 欧美制服第一页| 亚洲永久视频| 亚洲欧洲精品一区二区| 韩日在线一区|