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

兔子的技術博客

兔子

   :: 首頁 :: 聯系 :: 聚合  :: 管理
  202 Posts :: 0 Stories :: 43 Comments :: 0 Trackbacks

留言簿(10)

最新評論

閱讀排行榜

評論排行榜

轉載自癡癡笑笑的博客,略有刪改。

盡管 C++ 社區對 C++ 0x 很是追捧,但是各廠商對于新標準的支持并不熱乎。盼星星盼月亮,微軟作為 Windows 平臺上最強勢的 C++ 編譯器廠商也終于在 Visual Studio 2010 中開始支持 C++ 0x 的特性。

Visual Studio 2010 中的 Visual C++ 編譯器,即 VC10, 包含了 4 個 C++ 0x 的語言特性:lambda 表達式,自動類型推演(auto 關鍵字),靜態斷言(static_assert)和右值引用(rvalue reference)。

Lambda 表達式

使用過函數式編程語言(如 LISP、 F#)或一些動態語言(如 Python、Javascript)的大俠對于 lambda 表達式一定不會陌生。在 C++ 0x 中,引入了 lambda 表達式來定義無名仿函數。下面是一個 lambda 表達式的簡單例子:

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            
#include <algorithm>
            #include <iostream>
            #include <ostream>
            #include <vector>
             
            using namespace std;
             
            int main() {
            vector<int> v;
             
            for (int i = 0; i < 10; ++i) {
            v.push_back(i);
            }
             
            for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
            cout << endl;
             
            return 0;
            }

運行結果如下:

0 1 2 3 4 5 6 7 8 9

for_each 一行中,中括號 [] 稱為 lambda introducer,它告訴編譯器接下來的是一個 lambda 表達式;接下來 (int n) 是 lambda 表達式的參數聲明;最后大括號里邊就是“函數體”了。

注意這里因為 lambda 表達式生成的是 functor,所以“函數體”實際上是指這個 functor 的 operator() 的調用部分。你也許會問:那么返回值呢?缺省情況下 lambda 表達式生成的 functor 調用返回類型為 void。

為了方便,以下會用“lambda 返回 void”的簡短表述來代替冗長啰嗦的表述—— lambda 表達式生成一個 functor 類型,這個 functor 類型的函數調用操作符(operator()),返回的類型是 void。
請大家一定記住:lambda 表達式生成了類型,并構造該類型的實例。

下面的例子中 lambda 表達式的“函數體”包含多條語句:

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            
#include <algorithm>
            #include <iostream>
            #include <ostream>
            #include <vector>
             
            using namespace std;
             
            int main() {
            vector<int> v;
            for (int i = 0; i < 10; ++i) {
            v.push_back(i);
            }
             
            for_each(v.begin(), v.end(), [](int n) {
            cout << n;
             
            if (n % 2 == 0) {
            cout << " even ";
            } else {
            cout << " odd ";
            }
            });
            cout << endl;
             
            return 0;
            }

上文提到了 lambda 表達式缺省情況下返回 void,那么如果需要返回其他類型呢?答案是:lambda 表達式的“函數體”中如果有一個 return 的表達式,例如 { return expression; },那么編譯器將自動推演 expression 的類型作為返回類型。

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            
#include <algorithm>
            #include <deque>
            #include <iostream>
            #include <iterator>
            #include <ostream>
            #include <vector>
             
            using namespace std;
             
            int main() {
            vector<int> v;
             
            for (int i = 0; i < 10; ++i) {
            v.push_back(i);
            }
             
            deque<int> d;
             
            transform(v.begin(), v.end(), front_inserter(d), [](int n) { return n * n * n; });
             
            for_each(d.begin(), d.end(), [](int n) { cout << n << " "; });
            cout << endl;
             
            return 0;
            }

上例中返回值 n * n * n 很簡單,類型推演是顯而易見的。但是如果 lambda 表達式中有非常復雜的表達式時,編譯器可能無法推演出其類型,或者是推演出現二義性,這時候你可以顯式地指明返回值類型。如下所示:

1
            2
            3
            4
            5
            6
            7
            
transform(v.begin(), v.end(), front_inserter(d), [](int n) -> double {
            if (n % 2 == 0) {
            return n * n * n;
            } else {
            return n / 2.0;
            }
            });

“-> double”顯式地指明了 lambda 表達式的返回類型是 double。

以上例子中的 lambda 都是無狀態的,不包含任何數據成員。很多時候我們需要 lambda 包含數據成員以保存狀態,這一點可以通過“捕獲”局部變量來實現。

Lambda 表達式的導入符(lambda introducer)是空的,也就是“[]”,表明該 lambda 是一個無狀態的。但是在 lambda導入符中可以指定一個“捕獲列表”,下面的代碼中的 lambda 使用了局部變量 x 和 y,將值介于 x 和 y 之間的元素從集合中刪除:

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            
int main() {
            vector<int> v;
            for (int i = 0; i < 10; ++i) {
            v.push_back(i);
            }
             
            int x = 0;
            int y = 0;
             
            cout << "Input: ";
            cin >> x >> y;
            v.erase(remove_if(v.begin(), v.end(), [x, y](int n) { return x < n && n < y; }), v.end());
            for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
            cout << endl;
             
            return 0;
            }

運行結果如下:

Input: 4 7
0 1 2 3 4 7 8 9

上面代碼中很重要的一點信息是:lambda 中捕獲的局部變量是以“傳值”的方式傳給匿名函數對象的。在匿名函數對象中,保存有“捕獲列表”中局部變量的拷貝。這一點使得匿名函數對象的生命周期能夠長于 main 中的 x、y 局部變量。然而這樣的傳值方式帶來幾個限制:

  1. lambda中的這兩個拷貝并不能被改變,因為缺省情況下函數對象的 operator() 是const
  2. 有的對象的拷貝操作開銷很大或者不可能(例如如果上面代碼中的 x、y 是數據庫鏈接或者某個 singleton)
  3. 即使在lambda內部修改了 m_a、m_b 也不能夠影響外邊main函數中的 x 和 y

既然有了“傳值”,你一定猜到了還會有“傳引用”。Bingo! 你是對的。

在討論“傳引用”之前,我們先來看看另一個比較有用的東西。假設你有一大堆的局部變量需要被 lambda 使用,那么你的“捕獲列表”將會寫的很長,這肯定不是件愉快的事情。

好在 C++ 委員會的老頭們也想到了,C++ 0x 中提供了一個省心的東西:如果捕獲列表寫成 [=],表示 lambda 將捕獲所有的局部變量,當然也是傳值方式。這種方式姑且被稱為“缺省捕獲”:

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            
int main() {
            vector<int> v;
            for (int i = 0; i < 10; ++i) {
            v.push_back(i);
            }
             
            int x = 0;
            int y = 0;
             
            cout << "Input: ";
            cin >> x >> y; // EVIL!
            v.erase(remove_if(v.begin(), v.end(), [=](int n) { return x < n && n < y; }), v.end());
            for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
            cout << endl;
             
            return 0;
            }

當編譯器在 lambda 的作用范圍內看到局部變量 x、y 時,它會以傳值的方式從 main 函數中將它們捕獲。

下面我們來看如何突破前面提到的 3 點限制。

第 1 點,修改 lambda 表達式中的局部變量拷貝(e.g. m_a, m_b)。缺省情況下,lambda 的 operator() 是 const 修飾的,但是你可以使用 mutable 關鍵字改變這一點:

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            
int main() {
            vector<int> v;
            for (int i = 0; i < 10; ++i) {
            v.push_back(i);
            }
             
            int x = 1;
            int y = 1;
             
            for_each(v.begin(), v.end(), [=](int& r) mutable {
            const int old = r;
            r *= x * y;
            x = y;
            y = old;
            });
             
            for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
            cout << endl;
            cout << x << ", " << y << endl;
             
            return 0;
            }

運行結果如下:

0 0 0 6 24 60 120 210 336 504
1, 1

這里我們解決了第 1 個限制,但是卻產生了一個新的限制:

  1. lambda 中對捕獲變量的修改并不會影響到 main 函數中的局部變量,因為 lambda 捕獲局部變量使用的是傳值方式

下面該“傳引用”的方式登場了,它能夠有效地解決2,3,4三個限制。傳引用的語法為: lambda-introducer [&x, &y],這里的捕獲列表應該理解為:X& x, Y& y,因為我們實際上是取的 x、y 的引用而不是地址。

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            
int main() {
             
            vector<int> v;
            for (int i = 0; i < 10; ++i) {
            v.push_back(i);
            }
             
            int x = 1;
            int y = 1;
             
            for_each(v.begin(), v.end(), [&x, &y](int& r) {
            const int old = r;
            r *= x * y;
            x = y;
            y = old;
            });
             
            for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
            cout << endl;
            cout << x << ", " << y << endl;
             
            return 0;
            }

運行結果如下:

0 0 0 6 24 60 120 210 336 504
8, 9

注意:當你使用 lambda 時,VC10 編譯器會為 lambda 的定義部分自動禁用 C4512 警告。

當以傳引用方式捕獲局部變量時,lambda 的函數對象在自己內部以引用方式保存 main 函數中的局部變量。當然因為使用的是局部對象的引用,使用lambda表達式時一定要注意不能夠超出局部變量的生命周期。

和上文提高的[=]類似,我們可以用[&]來以“傳引用”的方式捕獲所有的局部變量。

到目前為止,局部變量的捕獲方式要么是“值語義”要么是“引用語義”,那么可以混合這兩種方式嗎?可以!例如:[a, b, c, &d, e, &f, g],其中變量 d 和 f 是按引用語義捕獲,而 a、b、c、e 和 g 是按值語義捕獲。

另外很有用的一點是:你可以指定一個缺省捕獲,然后重載某些局部變量的捕獲方式。下邊例子中[=, &sum, &product] 告訴編譯器用值語義方式捕獲所有的局部變量,但是有兩個例外 - sum和product是按引用語義來捕獲。

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            27
            28
            29
            30
            31
            32
            
int main() {
             
            vector<int> v;
            for (int i = 0; i < 10; ++i) {
            v.push_back(i);
            }
             
            int sum = 0;
            int product = 1;
            int x = 1;
            int y = 1;
             
            for_each(v.begin(), v.end(), [=, &sum, &product](int& r) mutable {
            sum += r;
             
            if (r != 0) {
            product *= r;
            }
             
            const int old = r;
            r *= x * y;
            x = y;
            y = old;
            });
             
            for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
            cout << endl;
            cout << "sum: " << sum << ", product: " << product << endl;
            cout << "x: " << x << ", y: " << y << endl;
             
            return 0;
            }

運行結果如下:

0 0 0 6 24 60 120 210 336 504
sum: 45, product: 362880
x: 1, y: 1

再來看看下邊的代碼,在lambda中使用類成員變量:

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            
class Kitty {
             
            public:
            explicit Kitty(int toys) : m_toys(toys) {}
             
            void meow(const vector<int>& v) const {
            for_each(v.begin(), v.end(), [m_toys](int n) {
            cout << "If you gave me " << n << " toys, I would have " << n + m_toys << " toys total." << endl;
            });
            }
             
            private:
            int m_toys;
            };
             
            int main() {
            vector<int> v;
            for (int i = 0; i < 3; ++i) {
            v.push_back(i);
            }
             
            Kitty k(5);
            k.meow(v);
             
            return 0;
            }

不幸的是,編譯這段代碼將產生這樣的錯誤:

error C3480: 'Kitty::m_toys': a lambda capture variable must be from an enclosing function scope

為什么呢?lambda表達式能夠讓你不活局部變量,但是類的數據成員并不是局部變量。解決方案呢?別著急。lambda 為捕獲類的數據成員大開方便之門,你可以捕獲this指針。

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            
class Kitty {
            public:
            explicit Kitty(int toys) : m_toys(toys) {}
            void meow(const vector<int>& v) const {
            for_each(v.begin(), v.end(), [this](int n) {
            cout << "If you gave me " << n << " toys, I would have " << n + m_toys << " toys total." << endl;
            });
            }
             
            private:
            int m_toys;
            };
             
            int main() {
            vector<int> v;
            for (int i = 0; i < 3; ++i) {
            v.push_back(i);
            }
             
            Kitty k(5);
            k.meow(v);
             
            return 0;
            }

運行結果如下:

If you gave me 0 toys, I would have 5 toys total.
If you gave me 1 toys, I would have 6 toys total.
If you gave me 2 toys, I would have 7 toys total.

當 lambda 表達式捕獲“this”時,編譯器看到 m_toys 后會在 this 所指向對象的范圍內進行名字查找,m_toys 被隱式地推演為 this->m_toys。當然你也可以讓編譯器省省力氣,顯式地在捕獲列表中使用 this->m_toys。另外,lambda 比較智能,你也可以隱式地捕獲 this 指針,如下所示:

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            
class Kitty {
             
            public:
            explicit Kitty(int toys) : m_toys(toys) { }
            void meow(const vector<int>& v) const {
            for_each(v.begin(), v.end(), [=](int n) {
            cout << "If you gave me " << n << " toys, I would have " << n + m_toys << " toys total." << endl;
            });
            }
             
            private:
            int m_toys;
            };
             
            int main() {
            vector<int> v;
            for (int i = 0; i < 3; ++i) {
            v.push_back(i);
            }
             
            Kitty k(5);
            k.meow(v);
            }

運行結果如下:

If you gave me 0 toys, I would have 5 toys total.
If you gave me 1 toys, I would have 6 toys total.
If you gave me 2 toys, I would have 7 toys total.

注意你也可以在上面代碼中用 [&],但是結果是一樣的——this 指針永遠是按值語義被傳遞(捕獲)的。你也不能夠使用 [&this],呵呵。

如果你的 lambda 表達式是沒有參數的,那么 lambda 表達式的導入符后邊的括號()也可以省掉。例如:

1
            2
            3
            4
            5
            6
            7
            8
            
int main() {
            vector<int> v;
            int i = 0;
            generate_n(back_inserter(v), 10, [&] { return i++; });
            for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
            cout << endl;
            cout << "i: " << i << endl;
            }

上邊是 [&]() { return i++; }的簡寫形式,個人認為省掉括號并不是什么好的 coding style。如果你需要用到mutable或者指定lambda的返回類型,空的括號就不能夠省略了。

最后,既然 lambda 表達式生成是普通的函數對象,所以函數對象支持的用法 lambda 都支持。例如和 tr1 的 function 一起使用,看看下邊的代碼,是不是很酷?

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            
using namespace std;
            using namespace std::tr1;
             
            void meow(const vector<int>& v, const function<void (int)>& f) {
            for_each(v.begin(), v.end(), f);
            cout << endl;
            }
             
            int main() {
            vector<int> v;
            for (int i = 0; i < 10; ++i) {
            v.push_back(i);
            }
             
            meow(v, [](int n) { cout << n << " "; });
            meow(v, [](int n) { cout << n * n << " "; });
             
            function<void (int)> g = [](int n) { cout << n * n * n << " "; };
            meow(v, g);
             
            return 0;
            }

運行結果:

0 1 2 3 4 5 6 7 8 9
0 1 4 9 16 25 36 49 64 81
0 1 8 27 64 125 216 343 512 729

auto 關鍵字

auto 這個關鍵字來自 C++ 98 標準。在 C++ 98 中它沒有什么作用,C++ 0x 中“借用”它來作為自動類型推演(automatic type deduction)。當 auto 出現在聲明中時,它表示“請用初始化我的表達式類型作為我的類型”,例如下面代碼:

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            27
            28
            
#include <iostream>
            #include <map>
            #include <ostream>
            #include <regex>
            #include <string>
             
            using namespace std;
            using namespace std::tr1;
             
            int main() {
            map<string, string> m;
             
            const regex r("(\\w+) (\\w+)");
             
            for (string s; getline(cin, s); ) {
            smatch results;
             
            if (regex_match(s, results, r)) {
            m[results[1]] = results[2];
            }
            }
             
            for (auto i = m.begin(); i != m.end(); ++i) {
            cout << i->second << " are " << i->first << endl;
            }
             
            return 0;
            }

運行結果如下:

cute kittens
ugly puppies
evil goblins
^Z
kittens are cute
goblins are evil
puppies are ugly

上面例子中i的類型在編譯時推演為 map::iterator, 有了 auto 關鍵字你再也不用寫又長又煩的代碼了。(注意 m.begin() 返回類型是 iterator, 而不是 const_iterator, 因為這里的 m 并不是 const。C++0x 中的 cbegin() 能夠解決這個問題,它返回 non-const 容器的 const 迭代器。)

Lambda 表達式和 auto 關鍵字的配合

上文中提到了用 tr1::functions 來存儲 lambda 表達式,但是不建議那樣做除非不得已,因為 tr1::functions 的開銷問題。如果你需要復用 lambda 表達式或者像給它命名,那么 auto 是更好的選擇。

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            27
            28
            29
            30
            31
            32
            33
            34
            35
            36
            37
            38
            39
            40
            41
            42
            43
            44
            45
            46
            47
            48
            49
            50
            51
            52
            53
            
#include <algorithm>
            #include <iostream>
            #include <ostream>
            #include <vector>
             
            using namespace std;
             
            template <typename T, typename Predicate> void keep_if(vector<T>& v, Predicate pred) {
            auto notpred = [&](const T& t) {
            return !pred(t);
            };
             
            v.erase(remove_if(v.begin(), v.end(), notpred), v.end());
            }
             
            template <typename Container> void print(const Container& c) {
            for_each(c.begin(), c.end(), [](const typename Container::value_type& e) { cout << e << " "; });
            cout << endl;
            }
             
            int main() {
            vector<int> a;
             
            for (int i = 0; i < 100; ++i) {
            a.push_back(i);
            }
             
            vector<int> b;
             
            for (int i = 100; i < 200; ++i) {
            b.push_back(i);
            }
             
            auto prime = [](const int n) -> bool {
            if (n < 2) {
            return false;
            }
             
            for (int i = 2; i <= n / i; ++i) {
            if (n % i == 0) {
            return false;
            }
            }
            return true;
            };
             
            keep_if(a, prime);
            keep_if(b, prime);
            print(a);
            print(b);
             
            return 0;
            }

運行結果如下:

2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199

上面代碼中 notpred 是一個 lambda 表達式的否定式。這個例子中我們不能夠使用 C++ 98 的 not1(),因為 not1 要求你的謂詞是從 unary_function 派生的,但是 lambda 并不要求這點,所以很多情況下使用 lambda 更靈活。

靜態斷言 static_assert

斷言(assertion)是提高代碼質量的有效武器。C++標準庫中的 assert、MFC 中的 ASSERT /VERIFY 宏都是斷言的例子,它們的共同點是在運行時對程序狀態進行判斷,例如檢查函數的參數有效性、檢查類的不變式等。而 C++ 0x 中的靜態斷言呢,和運行時的斷言不一樣,它是編譯時執行檢查的。看下面的例子:

1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            
template <int N> struct Kitten {
            static_assert(N < 2, "Kitten<N> requires N < 2.");
            };
             
            int main() {
            Kitten<1> peppermint;
            Kitten<3> jazz;
             
            return 0;
            }

編譯結果如下:

staticfluffykitten.cpp(2) : error C2338: Kitten<N> requires N < 2.
staticfluffykitten.cpp(8) : see reference to class template instantiation 'Kitten<N>' being compiled
with
[
N=3
]

上面例子中用 static_assert 對模板參數 N 進行了檢查,如果斷言失敗編譯器將使用用戶自定義的錯誤消息。

轉自:http://wutiam.net/2010/06/lambdas-auto-and-static-assert-c-0x-features-in-vc10/

posted on 2011-02-18 09:29 會飛的兔子 閱讀(2733) 評論(0)  編輯 收藏 引用 所屬分類: C++及開發環境
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            久久夜色精品国产噜噜av| 欧美日韩国产不卡| 国产偷国产偷精品高清尤物| 久久男女视频| 欧美日韩色综合| 美腿丝袜亚洲色图| 欧美三级特黄| 欧美成人亚洲| 韩国成人精品a∨在线观看| 亚洲精品在线视频| 国产精品久久久久久久一区探花 | 激情综合色丁香一区二区| 亚洲人午夜精品| 激情一区二区三区| 老巨人导航500精品| 久久动漫亚洲| 亚洲丰满少妇videoshd| 亚洲网址在线| 99亚洲伊人久久精品影院红桃| 久久成人18免费网站| 午夜精品免费视频| 欧美日韩一区二区三区视频| 一区二区三区精品国产| 亚洲精品自在久久| 在线看无码的免费网站| 一区二区三区国产精华| 亚洲国产导航| 久久久久久网址| 久久综合图片| 国产专区综合网| 亚洲欧美一区二区在线观看| 国产一区观看| 久久国产欧美精品| 亚洲欧美综合| 日韩视频免费看| 久久久亚洲高清| 免费h精品视频在线播放| 国产亚洲欧洲一区高清在线观看 | 欧美精品一区二区三区一线天视频| 噜噜噜噜噜久久久久久91| 蜜臀va亚洲va欧美va天堂| 亚洲最新视频在线| 欧美激情91| 亚洲美女av黄| 在线视频一区二区| 欧美日韩在线大尺度| 91久久在线观看| 99精品国产一区二区青青牛奶| 中国成人在线视频| 亚洲视频在线一区| 欧美激情一二区| 欧美成人首页| 亚洲精品乱码久久久久久蜜桃91| 欧美福利影院| 亚洲人成人77777线观看| 国内精品久久久久久久果冻传媒| 亚洲国产精选| 夜夜爽www精品| 欧美日韩色综合| 一区二区欧美激情| 午夜日韩av| 亚洲人体1000| 欧美日韩国产小视频| 99精品视频免费观看视频| 一本一道久久综合狠狠老精东影业| 欧美精品一区在线播放| 麻豆精品视频| 在线观看欧美精品| 久久人人爽人人爽爽久久| 亚洲福利电影| 欧美一进一出视频| 在线日韩欧美视频| 亚洲综合社区| 亚洲精品久久久久久久久久久久| 欧美国产日韩一区二区三区| 夜夜精品视频| 久久精品国产亚洲高清剧情介绍| 久久综合九色综合久99| 亚洲精品久久久久久久久久久久久| 欧美精品www在线观看| 亚洲精品美女久久7777777| 国产精品videossex久久发布| 欧美成va人片在线观看| 在线观看成人av| 亚洲欧美视频在线观看| 午夜精品网站| 欧美第一黄网免费网站| 9国产精品视频| 亚洲精品一区二区三区99| 欧美日韩高清在线观看| 欧美一区=区| 国产精品99久久不卡二区| 小黄鸭精品aⅴ导航网站入口| 亚洲第一综合天堂另类专| 久久精品国产2020观看福利| 91久久精品国产91久久| 久热国产精品| 夜夜爽夜夜爽精品视频| 久热精品视频在线观看| 亚洲欧美日韩天堂一区二区| 91久久精品美女高潮| 国产自产2019最新不卡| 欧美激情在线播放| 久久夜色精品国产亚洲aⅴ | 久久精品一本| 亚洲欧美成人一区二区三区| 亚洲精品一区二| 久久久久国产精品www| 亚洲欧美一区二区原创| 亚洲线精品一区二区三区八戒| 在线观看亚洲一区| 国产精品五区| 国产精品qvod| 欧美午夜精品理论片a级大开眼界 欧美午夜精品理论片a级按摩 | 久久久久天天天天| 亚洲午夜小视频| 亚洲精品影院在线观看| 亚洲高清不卡一区| 在线日韩一区二区| 亚洲成人资源网| 亚洲成人中文| 亚洲国产婷婷香蕉久久久久久99 | 亚洲天堂免费观看| 亚洲精品在线视频观看| 亚洲精品中文字幕女同| 亚洲精品一二区| 99精品国产福利在线观看免费 | 久久激情久久| 欧美jizz19性欧美| 欧美日本中文字幕| 国产欧美精品日韩| 亚洲高清在线观看一区| 亚洲裸体视频| 欧美一级在线播放| 欧美 日韩 国产在线| 99一区二区| 欧美综合二区| 欧美理论在线播放| 国产一区二区中文| 夜夜爽www精品| 久久精品国产99精品国产亚洲性色 | 亚洲国产成人午夜在线一区| 99国产精品久久久久老师| 午夜精品久久久久久久久久久久久| 亚洲一区二区三区在线| 久久久久久国产精品mv| 亚洲激情女人| 久久国产天堂福利天堂| 欧美日韩精品免费观看视一区二区| 国产性色一区二区| 99亚洲伊人久久精品影院红桃| 久久久久88色偷偷免费| 亚洲精品免费一二三区| 欧美在线关看| 国产精品电影网站| 亚洲国产视频直播| 久久精品国产精品亚洲| 亚洲精品免费看| 久久久综合视频| 国产精品永久入口久久久| 亚洲精品一级| 免费日韩一区二区| 午夜久久美女| 欧美午夜无遮挡| 亚洲欧洲在线看| 久久在线观看视频| 亚洲一区精彩视频| 欧美另类在线播放| 亚洲国产精品t66y| 久久九九久久九九| 一区二区电影免费在线观看| 老色鬼久久亚洲一区二区| 国产欧美精品一区二区三区介绍 | 亚洲精品国精品久久99热| 久久午夜av| 性欧美xxxx视频在线观看| 欧美日韩免费区域视频在线观看| 国产日韩欧美中文在线播放| 久久久精品一区二区三区| 国产乱码精品一区二区三区不卡| 一区二区高清在线| 亚洲日韩视频| 欧美激情第五页| 亚洲国产日韩欧美在线动漫| 蜜臀久久99精品久久久久久9| 欧美中文字幕在线| 国产主播精品| 久久婷婷国产综合精品青草| 性8sex亚洲区入口| 国产性天天综合网| 久久久久久久尹人综合网亚洲| 亚洲一区网站| 国产视频观看一区| 久久噜噜噜精品国产亚洲综合| 欧美在线免费| 亚洲成人资源网| 亚洲欧洲日夜超级视频| 欧美久久在线| 亚洲在线视频一区| 午夜精品在线|