<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【譯】VC10中的C++0x特性 part 1:Lambdas,auto,以及 static_assert

       

      【譯】VC10中的C++0x特性 part 1:Lambdas,auto,以及 static_assert 

      原文來源:vcblog 翻譯:羅朝輝 (http://www.rzrgm.cn/kesalin/)
      本文遵循“署名-非商業用途-保持一致”創作公用協議
       

      簡介

      這一系列文章介紹Microsoft Visual Studio 2010 中支持的C++ 0x特性,目前有三部分。 
      Part 1 :介紹了Lambdas, 賦予新意義的auto,以及 static_assert; 
      Part 2( 1 , 2 ):介紹了右值引用(Rvalue References); 
      Part 3 :介紹了表達式類型(decltype)

       

      VC10中的C++0x特性 Part 1,2,3 譯文打包下載(doc 和 pdf 格式): 點此下載

      本文是 Part 1。

      Microsoft Visual Studio 2010 九月社區技術預覽版 (CTP)所帶的Visual C++編譯器對四個C++0x語言特性提供了支持,也就是 lambdas ,auto ,static_assert ,以及 rvalue references (右值引用,譯注:后面不再對這個詞進行翻譯)。今天,我將詳細介紹前三個特性。(很快我將貢獻一整篇幅的文章來解釋右值引用,僅僅是因為再在這里解釋的話將會加大這篇已經很長的文章的篇幅)

      首先,說明一些事情:

       

      1,今天的這篇文章是由 Stephan T. Lavavej,Visual C++庫的開發人員以及C, A, 與 T讀者投書欄帶給你們的。注意作為庫的開發人員,我并沒有實現這些特性。那是 Jonathan Caves,前端編譯器開發者,選舉標準委員會成員以及所有“忍者”(鮮為人知的高手)的成果。

       

      2,我將 Visual C++ compiler in VS 2010 簡稱為 VC10 ( VS 2008 包含 VC9,VS 2005 包含 VC8,等等。 - 10 并不比 2010 簡短)

       

      3,C++0x 指的是即將到來的 C++ 標準,現在還在起草中。(C++標準委員會希望它可以在 2009 年完成,稱作 C++ 09;玩笑話說如果它推遲到 2010 或者更晚的話,“x” 將是十六進制的了)。 C++ 98 和C++ 03 指的是當前的 C++ 標準。(在這里不回顧歷史了, C++ 標準 2003 僅僅是最初的 C++ 1998 標準 的“補丁”版,對大部分人來說可以忽略兩者間的區別。C++ 03 和 C++ 0x 模樣雖然看起來差不多,但完全不同)

       

      4,我要感謝標準委員會開發出這些奇妙而有用并富有藝術的特性。他們也在以下站點上提供了重要的文檔:

       

      C++0x 語言特性:

      http://open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2705.html

      C++0x 庫特性:
      http://open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2706.html

      C++0x 進行中的草案:

      http://open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2798.pdf

       

      5,總是會有bug的(雖然希望不會太多),這也就是發布 CTP 版本的主要目的(讓用戶測試發現 bug )。請通過 Microfsoft 把這些 bug 報告給我們。

       

      現在,讓我們來審視這些特性吧!

       

      lambdas

       

      在 C++ 0x 中,“lambda 表達式” 隱式定義并構建不具名函數對象 ,這些對象就像手寫函數對象一樣。下面是 lambda “Hello,World”入門級的示例:

       

      C:/Temp>type meow.cpp

      #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;

      }

       

      C:/Temp>cl /EHsc /nologo /W4 meow.cpp > NUL && meow

      0 1 2 3 4 5 6 7 8 9

       

      [] 操作符是 lambda 導引符, 它告訴編譯器一個 lambda 表達式開始了。 (int n) 是 lambda 參數聲明,它告訴編譯器不具名函數對象類的函數調用操作符帶有哪些參數, { cout << n << " "; }   是復合 聲明 ,它是不具名函數對象類 的 函數調用操作 符 的函數體。不具名函數對象類 的 函數調用操作 符 默認返回 void 。

       

      這樣,C++0x 在內部將它轉換成如你在C++ 98 下編寫的一樣代碼:

       

      C:/Temp>type meow98.cpp

      #include <algorithm>

      #include <iostream>

      #include <ostream>

      #include <vector>

      using namespace std;

       

      struct LambdaFunctor {

          void operator()(int n) const {

              cout << n << " ";

          }

      };

       

      int main() {

          vector<int> v;

       

          for (int i = 0; i < 10; ++i) {

              v.push_back(i);

          }

       

          for_each(v.begin(), v.end(), LambdaFunctor() );

          cout << endl;

      }

       

      C:/Temp>cl /EHsc /nologo /W4 meow98.cpp > NUL && meow98

      0 1 2 3 4 5 6 7 8 9

       

      現在我將不再累述類似 “不具名函數對象類的函數調用操作符默認返回 void ”這樣的話,開始換用“lambda 函數返回 void ”的說法,但是記住 lambda 表達式做了些什么是很重要的,那就是:定義類并構建對象。

       

      當然,lambda 的復合聲明部分(函數體部分)可以包含多個聲明語句,譬如:

       

      C:/Temp>type multimeow.cpp

      #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;

      }

       

      C:/Temp>cl /EHsc /nologo /W4 multimeow.cpp > NUL && multimeow

      0 even 1 odd 2 even 3 odd 4 even 5 odd 6 even 7 odd 8 even 9 odd

       

      lambda 函數也并不總是必須返回 void 。如果 lambda 的復合聲明語句像是這樣的 { return expression ; } ,那么 lambda 的返回類型就會自動地被推斷成 expression 的類型

       

      C:/Temp>type cubicmeow.cpp

      #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;

      }

       

      C:/Temp>cl /EHsc /nologo /W4 cubicmeow.cpp > NUL && cubicmeow

      729 512 343 216 125 64 27 8 1 0

       

      在這里,  n * n * n  的類型是 int ,所以 lambda 函數返回 int 。

       

      有著復雜復合聲明語句的 lambda 函數不會自動推斷返回類型,你必須顯式指定返回類型。

       

      C:/Temp>type returnmeow.cpp

      #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<double> d;

       

          transform(v.begin(), v.end(), front_inserter(d), [](int n) -> double {

              if (n % 2 == 0) {

                  return n * n * n;

              } else {

                  return n / 2.0;

              }

          } );

       

          for_each(d.begin(), d.end(), [](double x) { cout << x << " "; });

          cout << endl;

      }

       

      C:/Temp>cl /EHsc /nologo /W4 returnmeow.cpp > NUL && returnmeow

      4.5 512 3.5 216 2.5 64 1.5 8 0.5 0

       

      -> double 是可選的 lambda 返回類型從句。為什么它不放在左邊(譯注:返回類型一般在函數左邊聲明),就像程序員一直以來在C函數中做的那樣?因為那樣的話 lambda 導引符 [] 就不會第一個出現了,而正是它告訴編譯器一個 lambda 函數開始了。(核心工作組最擅長解決這樣的問題;嘗試猜測C++ 中一個給定的概念是否是可被解析的會讓我頭疼。)

       

      如果忘記了指定 lambda返回類型從句,編譯器就會抱怨每一個返回語句:

       

      C:/Temp>cl /EHsc /nologo /W4 borkedreturnmeow.cpp

      borkedreturnmeow.cpp

      borkedreturnmeow.cpp(20) : error C3499: a lambda that has been specified to have a void return type cannot return a value

      borkedreturnmeow.cpp(22) : error C3499: a lambda that has been specified to have a void return type cannot return a value

       

       

      到目前 為 止我所介 紹 的 lambda 都是無狀 態 的:它 們 不包含數據成 員 。你也可以有有狀 態 的 lambda , 這 是通 過 “ 傳遞 ” (原文用 加引號的 capturing 這個詞,在這里我翻譯成傳遞似乎不太妥,故我都加括號引用原文,下同 )局部 變 量來 實現 的。 空的 lambda 導 引符 [] 意味著 “ 一個無狀 態 的 lambda” ,但在 lambda 導 引符 [] 中你可以指定 capture-list 

       

      C:/Temp>type capturekittybyvalue.cpp

      #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);

          }

       

          int x = 0;

          int y = 0;

       

          // op>>() leaves newlines on the input stream,

          // which can be extremely confusing. I recommend

          // avoiding it, and instead using non-member

          // getline(cin, str) to read whole lines and

          // then parse them. But in the interests of

          // brevity, I'll use evil op>>():

       

          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;

      }

       

      C:/Temp>cl /EHsc /nologo /W4 capturekittybyvalue.cpp > NUL && capturekittybyvalue

      Input: 4 7

      0 1 2 3 4 7 8 9

      如果你忘 記 了 capture-list , 編譯 器就會抱怨:

      C:/Temp>cl /EHsc /nologo /W4 borkedcapturekittybyvalue.cpp

      borkedcapturekittybyvalue.cpp

      borkedcapturekittybyvalue.cpp(27) : error C3493: 'x' cannot be implicitly captured as no default capture mode has been specified

      borkedcapturekittybyvalue.cpp(27) : error C3493: 'y' cannot be implicitly captured as no default capture mode has been specified

       

      (我很快就會解 釋 默 認 的傳遞 ( capture ))

      記著,lambda 表達式隱式地定義了一個不具名函數對象類。復合聲明語句 { return x < n && n < y; }  在這個類中被當作函數調用操作符的函數體。雖然從詞法結構上看復合聲明語句是在 main() 塊之內,但在概念上它是在 main() 塊之外的,因此如果不傳遞( capture ) 到 lambda 中去,就不能在其中使用來自main() 中的局部變量。

      上面的代碼在內部被翻譯成:

      C:/Temp>type capturekittybyvalue98.cpp

      #include <algorithm>

      #include <iostream>

      #include <iterator>

      #include <ostream>

      #include <vector>

      using namespace std;

       

      class LambdaFunctor {

      public:

          LambdaFunctor(int a, int b) : m_a(a), m_b(b) { }

       

          bool operator()(int n) const { return m_a < n && n < m_b; }

       

      private:

          int m_a;

          int m_b;

      };

       

      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(), LambdaFunctor(x, y) ), v.end());

       

          copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));

          cout << endl;

      }

       

      C:/Temp>cl /EHsc /nologo /W4 capturekittybyvalue98.cpp > NUL && capturekittybyvalue98

      Input: 4 7

      0 1 2 3 4 7 8 9

       

      在這里你可以清楚地看到是 “按值” 傳遞(captures)的。函數對象存儲了局部變量的拷貝。這就使得函數對象可以比通過傳遞(capture)來創建它們的局部變量有更長的生命期。但是,要注意:(a)在 lambda 中不能修改通過傳遞(capture)獲得的拷貝,因為默認情況下函數調用操作符是 const 屬性的,(b)一些對象的拷貝開銷是昂貴的,(c)局部變量的更新不會反應到通過傳遞(capture)獲得的拷貝(在語義上它們是原始值)。很快我就會解釋如有需要應該如何來處理以上情況。

       

      但是首先,你可以“按值傳遞(capture)任何東西”,而不用特別指明每一個你想要傳遞(capture)的局部變量。其語法是使用這種形式的 lambda 導引符 [=] (默認傳遞(capture-default ) =  應該可以讓你想起賦值或者拷貝初始化 Foo foo = bar; 雖然這里的拷貝實際上是直接初始化(通過初始化列表進行賦值),就像上面的 m_a(a))。

       

      C:/Temp>type defaultcapturekittybyvalue.cpp

      #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);

          }

       

          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;

      }

       

      C:/Temp>cl /EHsc /nologo /W4 defaultcapturekittybyvalue.cpp > NUL && defaultcapturekittybyvalue

      Input: 4 7

      0 1 2 3 4 7 8 9

       

      當編譯器看到 lambda 中的 x 和 y, 就會從 main() 中按值傳遞(capture)。

       

      情形(a)要修改通過傳遞(capture)獲得拷貝該怎樣呢?默認情況下,一個 lambda 函數調用操作符是 const 屬性的,但是可以通過使用 mutable 把它變成 non-const 。

      C:/Temp>type capturekittybymutablevalue.cpp

      #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);

          }

       

          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;

      }

       

      C:/Temp>cl /EHsc /nologo /W4 capturekittybymutablevalue.cpp > NUL && capturekittybymutablevalue

      0 0 0 6 24 60 120 210 336 504

      1, 1

      這里是依次將 v 中前兩個元素相乘。(我得承認真的很難想出一個不用 partial_sum() 或 adjacent_difference() 表示的例子,partial_sum() 是與前面所有的元素相乘,adjacent_difference()是與前一個元素相乘)。注意到情形(d),對通過傳遞獲得的拷貝的更新操作并沒有影響局部變量(再一次,原始值語義)。

       

      如果你想處理情形(b),(c)和(d):避免拷貝,在 lambda 中觀察局部變量的更新,以及在 lambda 中修改局部變量又該怎么做呢?在這種情況下,你會想通過引用傳遞(capture by reference)。其語法是這種形式的 lambda 導引符 [&x, &y]  (你可以把它想象成  X& x, Y& y  ; 那是“引用”而不是“取址”)。

      C:/Temp>type capturekittybyreference.cpp

      #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);

          }

       

          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;

      }

       

      C:/Temp>cl /EHsc /nologo /W4 capturekittybyreference.cpp > NUL && capturekittybyreference

      0 0 0 6 24 60 120 210 336 504

      8, 9

      注意與 capturekittybymutablevalue.cpp 的區別:(1),lambda 導引符是 [&x, &y]  ,(2)沒有 mutable ,(3),局部變量 x 和 y 最后的值是 8 和 9,反應了在 lambda 中對他們的修改。

      上面的代碼在內部被翻譯成:

      C:/Temp>type capturekittybyreference98.cpp

      #include <algorithm>

      #include <iostream>

      #include <iterator>

      #include <ostream>

      #include <vector>

      using namespace std;

       

      #pragma warning(push)

      #pragma warning(disable: 4512) // assignment operator could not be generated

       

      class LambdaFunctor {

      public:

          LambdaFunctor(int& a, int& b) : m_a(a), m_b(b) { }

       

          void operator()(int& r) const {

              const int old = r;

       

              r *= m_a * m_b;

       

              m_a = m_b;

              m_b = old;

          }

       

      private:

          int& m_a;

          int& m_b;

      };

       

      #pragma warning(pop)

       

      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(), LambdaFunctor(x, y) );

       

          copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));

          cout << endl;

       

          cout << x << ", " << y << endl;

      }

       

      C:/Temp>cl /EHsc /nologo /W4 capturekittybyreference98.cpp > NUL && capturekittybyreference98

      0 0 0 6 24 60 120 210 336 504

      8, 9

      當你通過引用傳遞(capture)局部變量時,函數對象存儲局部變量的引用。這樣避免了拷貝,能夠讓函數對象觀測對局部變量的更新,以及能夠讓函數對象通過引用修改局部變量。(注意函數調用操作符是 const 屬性的,因為我們沒有把它聲明成 mutable ,但這只阻止我們修改函數對象的數據成員。在這里數據成員是引用,我們無法修改它,但是我們可以修改它所指向的東西。函數調用操作符的常量性是,且一直都是,表面的)

       

      當然,如果函數對象比用于引用傳遞的局部變量的生命期更長的話,程序會毀滅性地崩潰。(譯注:就是說引用所指向的東西已經銷毀了,但你可能還在使用這個引用)

       

      同樣,你可以使用默認的按引用傳遞語法;這種形式 lambder 導引符 [&] 表明“按引用傳遞”。

       

      如果你想混合使用按值傳遞和按引用傳遞該怎么做呢?你可以像這樣聲明  [a, b, c, &d, e, &f, g] ,但你也可以指定默認按值傳遞,再為特定的(需要按引用傳遞的)局部變量而重載它。下面是一個修改capturekittybymutablevalue.cpp 而來的例子:

      C:/Temp>type overridekitty.cpp

      #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);

          }

       

          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;

      }

       

      C:/Temp>cl /EHsc /nologo /W4 overridekitty.cpp && overridekitty

      overridekitty.cpp

      0 0 0 6 24 60 120 210 336 504

      sum: 45, product: 362880

      x: 1, y: 1

       

      在這里,我們想通過按值傳遞 x 和 y (因為我們只想在 lambda 內部修改它們,而影響外部),同時我們想按傳引用捕獲 sum 和 product (因為我們確實想讓對它們的修改在外部也生效)。像這樣的 lambda 導入符組合 [&, x, y]  可以起到同樣的效果(按應用傳遞所有參數,除了 x 和 y 是按值傳遞之外)

       

      嗯,如果你想這么做又該如何?

      C:/Temp>type memberkitty.cpp

      #include <algorithm>

      #include <iostream>

      #include <ostream>

      #include <vector>

      using namespace std;

       

      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);

      }

       

      C:/Temp>cl /EHsc /nologo /W4 memberkitty.cpp

      memberkitty.cpp

      memberkitty.cpp(12) : error C3480: 'Kitty::m_toys': a lambda capture variable must be from an enclosing function scope

       

      lambda 表達式語法允許你傳遞局部變量,但是數據成員不是局部變量。通過特別的方法,你也可以傳遞數據成員:

      C:/Temp>type workingmemberkitty.cpp

      #include <algorithm>

      #include <iostream>

      #include <ostream>

      #include <vector>

      using namespace std;

       

      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);

      }

       

      C:/Temp>cl /EHsc /nologo /W4 workingmemberkitty.cpp > NUL && workingmemberkitty

      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 ,你可以使用 m_toys ,它隱含意味著 this->m_toys ,就如平常一樣(譯注:作為類自身成員變量)。你也可以顯式使用 this->m_toys 。(在一個 lambda 表達式內,只有當你傳遞了 this ,你才能使用它;你永不可能取得 lambda 對象它自身的 this 指針)。

       

      你也可以隱式地傳遞 this 

      C:/Temp>type implicitmemberkitty.cpp

      #include <algorithm>

      #include <iostream>

      #include <ostream>

      #include <vector>

      using namespace std;

       

      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);

      }

       

      C:/Temp>cl /EHsc /nologo /W4 implicitmemberkitty.cpp > NUL && implicitmemberkitty

      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] 。

       

      如果你想使用一個空無的 lambda (不帶參數),你可以省略整個 lambda參數聲明:

      C:/Temp>type nullarykitty.cpp

      #include <algorithm>

      #include <iostream>

      #include <iterator>

      #include <ostream>

      #include <vector>

      using namespace std;

       

      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;

      }

       

      C:/Temp>cl /EHsc /nologo /W4 nullarykitty.cpp > NUL && nullarykitty

      0 1 2 3 4 5 6 7 8 9

      i: 10

      這比 [&]() { return i++; } 少兩個字符。省略 lambda 參數聲明是否是良好的風格是由你來決定的。

      僅博一笑,這意味著下面的代碼在 C++0x 中是合法的。

      C:/Temp>type nokitty.cpp

      int main() {

          [](){} ();

          []{} ();

      }

       

      上面構建了兩個什么也不做的 lambda (一個有 lambda 參數聲明,一個沒有)并立即調用它們(通過最后一個空括號組合)。

       

      注意可選的 lambda 參數聲明語法上包括:

      lambda-parameter-declaration-listopt ) mutable opt exception-specificationopt lambda-return-type-clauseopt

       

      因此,如果你想使用 mutable 或  -> ReturnType ,你需要在 lambda 導引符和它們之間插入空括號。

      最后,因為 lambda 產生普通的函數對象,你可以在 tr1::function 中存儲它們。

      C:/Temp>type tr1kitty.cpp

      #include <algorithm>

      #include <functional>

      #include <iostream>

      #include <ostream>

      #include <vector>

      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);

      }

       

      C:/Temp>cl /EHsc /nologo /W4 tr1kitty.cpp > NUL && tr1kitty

      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 ,意味著“讓它和初始化它的事物具有相同的類型”。你看:

       

      C:/Temp>type autocat.cpp

      #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;

          }

      }

       

      C:/Temp>cl /EHsc /nologo /W4 autocat.cpp > NUL && autocat

      cute kittens

      ugly puppies

      evil goblins

      ^Z

      kittens are cute

      goblins are evil

      puppies are ugly

       

      map<string, string>::iterator ,你近10年的恐怖統治終于到頭了。

       

      (注意:m.begin()返回 iterator ,而不是 cosnt_iterator ,因為 map 不是 const 屬性的。C++ 0x cbegin() 允許你從一個 non-cosnt 容器中獲得一個 const_iterator 。)

       

      lambdas and auto

       

      先前我提到過在 tr1::functions 中存儲 lambda 函數。但是如非必要請別這么做,因為 tr1::function 會增加一些開銷。如果你想重用 lambda 函數,或只想給它命名的話,你可以使用 auto 。這兒有一個簡潔的例子:

       

      C:/Temp>type autolambdakitty.cpp

      #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);

      }

       

      C:/Temp>cl /EHsc /nologo /W4 autolambdakitty.cpp

      autolambdakitty.cpp

       

      C:/Temp>autolambdakitty

      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 <functional> 中的 not1() 函數,因為那要求你的謂詞函數繼承自 unary_function ,而 lambda 函數并不滿足這個條件。

       

      static_assert

       

      static_assert 讓你能夠在觸發編譯器錯誤時使用定制的錯誤信息:

       

      C:/Temp>type staticfluffykitten.cpp

      template <int N> struct Kitten {

          static_assert(N < 2, "Kitten<N> requires N < 2.");

      };

       

      int main() {

          Kitten<1> peppermint;

       

          Kitten<3> jazz;

      }

       

      C:/Temp>cl /EHsc /nologo /W4 staticfluffykitten.cpp

      staticfluffykitten.cpp

      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

              ]

       

      如果你有任何疑問,我很樂意在評論中回答它們。

       

      Stephan T. Lavavej

      Visual C++ Libraries Developer

      Published Tuesday, October 28, 2008 9:31 AM by vcblog


      posted @ 2009-05-28 12:11  飄飄白云  閱讀(581)  評論(0)    收藏  舉報
      本博客遵循 Creative Commons License “署名-非商業用途-保持一致”創作共用協議。 與我聯系
      主站蜘蛛池模板: 岑巩县| 人妻精品动漫H无码中字| 92国产精品午夜福利免费 | 热久在线免费观看视频 | 久久96热在精品国产高清| 狠狠婷婷色五月中文字幕| 国产九九视频一区二区三区| 九九九国产| 国产日产亚洲系列av| 国产一区二区三四区| 九九热精品在线观看| 欧美综合天天夜夜久久| 亚洲国产一区二区三区久| 99国精品午夜福利视频不卡99| 亚洲色大成网站WWW永久网站| 日本不卡码一区二区三区| 一本色道婷婷久久欧美| 免费观看日本污污ww网站69| 洛川县| 丁香五月亚洲综合在线国内自拍| 精品人妻二区中文字幕| 久久久久成人精品无码中文字幕 | 久久se精品一区精品二区国产| 日韩一区二区三区女优丝袜| 无码AV中文字幕久久专区| 亚洲午夜久久久影院伊人| 精品一区二区三区日韩版| 通许县| 亚洲人成色99999在线观看| 国产揄拍国产精品| 亚洲www永久成人网站| 无码人妻一区二区三区AV| 中文字幕成熟丰满人妻| 平顶山市| 孕妇特级毛片ww无码内射| 亚洲国产精品日韩AV专区| 丁香五月激情图片| 九九热精彩视频在线免费| 蜜桃av色偷偷av老熟女| 亚洲国产精品成人av网| 国产网友愉拍精品视频手机|