Visual Studio 2010中C++の4つの大きな変化

26857 ワード

From:http://news.csdn.net/a/20100402/217713.html
マイクロソフトのVisual Studio 2010の正式版では、C++言語の修正を行いました.
ランバー表現
多くのプログラミング言語は匿名関数をサポートしています.匿名関数とは、この関数は関数体だけで、関数名はありません.Lambda表式は匿名関数を実現するためのプログラミング技法であり、匿名関数を作成するための簡単な関数式の構文を提供している.同じVisual Studioで開発された言語でも、Visual BaicとVisual C胫はLambada表現に対する支持を早く実現しました.やっとVisual C++は今回も遅れを取りたくないです.Visual Studio 2010にLambada表現に対する支持を追加しました.
Lamban表現は、関数を使用する場所で定義することができ、Lamban関数ではLamber関数以外のデータを使用することができます.これは集合操作に対して大きな便宜をもたらしました.機能的にはLamda表現は関数ポインタと関数オブジェクトに似ていますが、Lamda表現は関数ポインタと関数オブジェクトの長所を兼ね備えていますが、欠点はありません.関数ポインタや関数オブジェクトの複雑な文法形式に対して、Lambada表現は非常に単純な文法を使用して同様の機能を実現し、Lambada表現の学習難易度を低減し、複雑な関数オブジェクトや関数ポインタの使用によるエラーを回避しました.実際の例を見てもいいです.

 
   
  1. #include "stdafx.h"
  2. #include <algorithm>
  3. #include <iostream>
  4. #include <ostream>
  5. #include <vector>
  6. using namespace std;
  7. int _tmain(int argc, _TCHAR* argv[])
  8. {
  9. vector<int> v;
  10. for (int i = 0; i < 10; ++i) {
  11. v.push_back(i);
  12. }
  13. for_each(v.begin(), v.end(), [] (int n) {
  14. cout << n;
  15. if (n % 2 == 0) {
  16. cout << " even ";
  17. } else {
  18. cout << " odd ";
  19. }
  20. });
  21. cout << endl;
  22. return 0;
  23. }
  24. #include "stdafx.h"
  25. #include <algorithm>
  26. #include <iostream>
  27. #include <ostream>
  28. #include <vector>
  29. using namespace std;
  30. int _tmain(int argc, _TCHAR* argv[])
  31. {
  32. vector<int> v;
  33. for (int i = 0; i < 10; ++i) {
  34. v.push_back(i);
  35. }
  36. for_each(v.begin(), v.end(), [] (int n) {
  37. cout << n;
  38. if (n % 2 == 0) {
  39. cout << " even ";
  40. } else {
  41. cout << " odd ";
  42. }
  43. });
  44. cout << endl;
  45. return 0;
  46. }
このコードは出力vectorの各数を巡回し、この数が奇数か偶数かを判断する.Lambda表現を随時修正して、この匿名関数の実装を変更して、セットの動作を修正することができます.このコードでは、C+++はペアの中かっこ「[]」を使用してLamban表現の開始を表し、その後の"(int n)"はLamband表現のパラメータを表します.これらのパラメータはLamda式で使用されます.Lamda表現の簡潔さを理解するために、同じ機能を見てみます.

 
   
  1. #include "stdafx.h"
  2. #include <algorithm>
  3. #include <iostream>
  4. #include <ostream>
  5. #include <vector>
  6. using namespace std;
  7. struct LambdaFunctor {
  8. void operator()(int n) const {
  9. cout << n << " ";
  10. if (n % 2 == 0) {
  11. cout << " even ";
  12. } else {
  13. cout << " odd ";
  14. }
  15. }
  16. };
  17. int _tmain(int argc, _TCHAR* argv[])
  18. {
  19. vector<int> v;
  20. for (int i = 0; i < 10; ++i) {
  21. v.push_back(i);
  22. }
  23. for_each(v.begin(), v.end(), LambdaFunctor());
  24. cout << endl;
  25. return 0;
  26. }
  27. #include "stdafx.h"
  28. #include <algorithm>
  29. #include <iostream>
  30. #include <ostream>
  31. #include <vector>
  32. using namespace std;
  33. struct LambdaFunctor {
  34. void operator()(int n) const {
  35. cout << n << " ";
  36. if (n % 2 == 0) {
  37. cout << " even ";
  38. } else {
  39. cout << " odd ";
  40. }
  41. }
  42. };
  43. int _tmain(int argc, _TCHAR* argv[])
  44. {
  45. vector<int> v;
  46. for (int i = 0; i < 10; ++i) {
  47. v.push_back(i);
  48. }
  49. for_each(v.begin(), v.end(), LambdaFunctor());
  50. cout << endl;
  51. return 0;
  52. }
 
比較によって,Lamban表現の文法はより簡潔で,より簡単で効率的に使用できることが分かった.
静的にスタティックと言い切るクラスメイト
前のC++標準C+03では、2つの断言が使えます.
 
◆前処理中の条件コンパイルと↉error命令を使用して、前処理段階でいくつかのコンパイル条件を確認できます.
◆マクロクラスを使って実行時のチェックを行い、プログラムロジックの正確性を確保します.
しかし、龛を使用する方法は非常に煩雑であり、テンプレートの実用化はコンパイル時に行われるので、前処理段階において行われる.クラスメイトマクロは運行時に検査を行います.簡単に見つけられます.コンパイル時に検査できるツールが足りません.そして、静的に言い放つことが生まれる.
新しいC++標準C++0 xに静的断言へのサポートが加わり、新たなキーワードstatic_が導入されました.astertは静的に断言することを表します.静的断言を使用して,プログラムのコンパイルの時期に,いくつかの条件が成立するかどうかを検出することができます.この特性はテンプレート関数のテンプレートパラメータをデバッグする時に特に有用です.コンパイルする時、テンプレート関数が実用化されている場合、テンプレート関数のパラメータが私達の設計によって適切な値を持つかどうかを静的に判定してテストすることができます.例えば、以下のコード:

 
   
  1. template <int N> struct Kitten {
  2. static_assert(N < 2, "Kitten<N> requires N < 2.");
  3. };
  4. int main() {
  5. Kitten<1> peppermint;
  6. Kitten<3> jazz;
  7. return 0;
  8. }
  9. template <int N> struct Kitten {
  10. static_assert(N < 2, "Kitten<N> requires N < 2.");
  11. };
  12. int main() {
  13. Kitten<1> peppermint;
  14. Kitten<3> jazz;
  15. return 0;
  16. }
 
メイン関数で「1」を使って、Kittenという構造体を具体化すると、コンパイルするときに、スタティックにstatic_を断言します.astertはパラメータNの値をテストします.Nの値が2より小さいと、エラーと言い切ることができます.それに対応するデバッグヘルプ情報を「Err List」ウィンドウに出力します.そうすると、プログラマは問題の迅速な位置決めができ、問題を解決するのにもっと便利です.
また、静的断言は他にも多くのメリットをもたらします.例えば、静的には、コンパイル時に処理を行うと断言されており、実行時刻空間および時間的なオーバヘッドは一切発生しないので、これは、astertマクロよりも効率的である.また重要な特性の一つは、失敗と断言すれば、意味があり、十分な診断情報が生まれ、プログラマが問題を迅速に解決するのを助けることです.
autキーワード
C++において、autキーワードの意味が変わった.Visual Studio 2010から、autキーワードは、コンパイラが変数の初期値に基づいて変数のデータタイプを決定するように導くために使用されます.言い換えれば、autを新しいタイプのデータとして扱うことができます.これは「初期化器(initialize)から代表される変数の真のタイプを導出することができます.」このようなautキーワードの使い方は、現在の代替方式によって引き起こされる冗長性とエラー性のあるコードを大幅に除去することができる.実際の例を見ます.

 
   
  1. #include <iostream>
  2. #include <map>
  3. #include <ostream>
  4. #include <regex>
  5. #include <string>
  6. using namespace std;
  7. using namespace std::tr1;
  8. int main() {
  9. map<string, string> m;
  10. const regex r("(\\w+) (\\w+)");
  11. for (string s; getline(cin, s); ) {
  12. smatch results;
  13. if (regex_match(s, results, r)) {
  14. m[results[1]] = results[2];
  15. }
  16. }
  17. for (auto i = m.begin(); i != m.end(); ++i) {
  18. cout << i->second << " are " << i->first << endl;
  19. }
  20. return 0;
  21. }
  22. #include <iostream>
  23. #include <map>
  24. #include <ostream>
  25. #include <regex>
  26. #include <string>
  27. using namespace std;
  28. using namespace std::tr1;
  29. int main() {
  30. map<string, string> m;
  31. const regex r("(\\w+) (\\w+)");
  32. for (string s; getline(cin, s); ) {
  33. smatch results;
  34. if (regex_match(s, results, r)) {
  35. m[results[1]] = results[2];
  36. }
  37. }
  38. for (auto i = m.begin(); i != m.end(); ++i) {
  39. cout << i->second << " are " << i->first << endl;
  40. }
  41. return 0;
  42. }
 
このコードでは、autキーワードを使って、本当のデータタイプmap<string、string>の代わりに使用します.また、他のデータタイプと同様に、autキーワードを修飾することもできます.例えば、const、ポインタ(*)、左値参照(&)、右値参照(&&&)などを追加して、これらの修飾の具体的な意味を決定します.いくつかの従来のC++コードに対応するために、このコンパイラオプションを使って、コンパイラがautキーワードを採用しているかそれとも新しい標準C++に定義されているかを教えます.
右参照
最も重要な言語特性として、右の値参照がC++に導入されます.操作符の「&&&」を通じて、右の値の引用を宣言できます.もともとはC++の中で「&」オペレータ宣言の引用を使っていましたが、現在は左の値参照と呼ばれています.

 
   
  1. int a;
  2. int& aa_lvref = a;//
  3. int b;
  4. int&& bb_rvref = b;//
左の値参照と右の値参照の表現は基本的に一致していますが、その唯一の違いは右の値参照は一時的なオブジェクト(右の値)に結び付けられます.左の値は参照できません.たとえば:

 
   
  1. int& a_lvref = int();// error C2440: 'initializing' : cannot convert from 'int' to 'int &'
  2. int&& b_rvref = int();// OK!
最初の行コードでは、一時的なオブジェクトint()を左の値参照に結び付けてコンパイルエラーを発生します.第二行では、一時的なオブジェクトを右の値に結び付けて参照すれば、簡単にコンパイルすることができます.右の値は名前がないデータで、例えば関数の戻り値は一般に右の値です.右の値を操作すると、右の値自体は保持する必要がありませんので、場合によっては直接「移動」することができます.右の値を参照すると、プログラムは、入力されたパラメータが右の値かどうかを明確に区別し、不要なコピーを回避することができ、プログラムの効率も向上します.簡単なデータ交換のための手続きを考えて、右の引用による効率の向上を実感します.関数swapを書いて、二つの変数値の交換を実現できます.

 
   
  1. template <class T> swap(T& a, T& b)
  2. {
  3. T tmp(a); // tmp , a
  4. a = b;// b
  5. b = tmp;// a
  6. }
このコードの中では、簡単なデータ交換のためだけに、複数のオブジェクトのコピーを実行しています.これらのオブジェクトのコピー操作は、特にこれらのオブジェクトが大きい場合、プログラムの効率に影響を与えるに違いない.右値参照を使うとどうなりますか?

 
   
  1. #include "stdafx.h"
  2. template <class T>
  3. T&& move(T&& a)
  4. {
  5. return a;
  6. }
  7. template <class T> void swap(T& a, T& b)
  8. {
  9. T tmp(move(a)); // a tmp,a
  10. a = move(b);// b a,b
  11. b = move(tmp);// tmp b
  12. }
  13. int _tmain(int argc, _TCHAR* argv[])
  14. {
  15. int a = 1;
  16. int b = 2;
  17. swap(a, b);
  18. return 0;
  19. }
  20. #include "stdafx.h"
  21. template <class T>
  22. T&& move(T&& a)
  23. {
  24. return a;
  25. }
  26. template <class T> void swap(T& a, T& b)
  27. {
  28. T tmp(move(a)); // a tmp,a
  29. a = move(b);// b a,b
  30. b = move(tmp);// tmp b
  31. }
  32. int _tmain(int argc, _TCHAR* argv[])
  33. {
  34. int a = 1;
  35. int b = 2;
  36. swap(a, b);
  37. return 0;
  38. }
 
この再実現されたコードでは、オブジェクトの割当演算子「=」の代わりに、move()関数を使用して、右または左の値の参照を単純に受け入れてパラメータとして参照し、直接に該当するオブジェクトの右値参照を返します.このプロセスはコピー(Copy)操作を生成せず、ソースオブジェクトだけをターゲットオブジェクトに移動します.
コピー(Copy)とモバイル(Move)の違いこそ、右の引用はC+0 xの中で最も人の心を奮い立たせる新しい特性の一つとなります.実践の角度から言えば、完璧にC++の中で長い間人に非難されてきた一時的な対象の効率的な問題を解決することができます.言語そのものから言えば、C++の中の引用の種類は左の値の右の面での欠陥を健全にしています.ライブラリの設計者の立場から言えば、ライブラリの設計者にもう一つの利器を持ってきました.多くのライブラリの利用者にとっては、不動の一兵卒で「無料」の効率が向上し、ビジュアルスタジオ2010では、これらのC++の新しい特性に対する支持があったため、プログラマーたちのC++への情熱が新たに火をつけました.