C++11
C11(C標準リビジョン)
と混同しないでください
C ++ 11には、のバージョンであるISO / IECのための14882標準C ++プログラミング言語。C ++ 11と呼ばれるC ++標準の以前のバージョン、置換C ++ 03、を、後に置換したC ++ 14。この名前は、仕様の発行年までに言語バージョンに名前を付けるという伝統に従いますが、2010年より前に発行される予定だったため、以前はC ++ 0xと呼ばれていました。
設計目標の1つは、コア言語への変更よりもライブラリへの変更を優先することでしたが、 C ++ 11はコア言語にいくつかの追加を行います。大幅に改善されたコア言語の領域には、マルチスレッドのサポート、ジェネリックプログラミングのサポート、均一な初期化、およびパフォーマンスが含まれます。数学的な特殊関数のライブラリを除く、ほとんどのC ++テクニカルレポート1(TR1)ライブラリを組み込んだ、C ++標準ライブラリにも大幅な変更が加えられました。
C ++ 11は、2011年9月にISO / IEC 14882:2011 として公開され、有料で入手できます。公開されているC ++ 11標準に最も類似した作業ドラフトは、2012年1月16日付けのN3337です。 C ++ 11標準からの編集上の修正のみが
コンテンツ
1 設計目標
2 C ++コア言語の拡張
2.1 コア言語のランタイムパフォーマンスの強化
2.1.1 参照の再評価とコンストラクターの移動
2.1.2 constexpr –一般化された定数式
2.1.3 プレーンな古いデータの定義の変更
2.2 コア言語のビルド時のパフォーマンスの強化
2.2.1 外部テンプレート
2.3 コア言語のユーザビリティの強化
2.3.1 イニシャライザリスト
2.3.2 均一な初期化
2.3.3 型推論
2.3.4 範囲ベースのforループ
2.3.5 ラムダ関数と式
2.3.6 代替関数の構文
2.3.7 オブジェクト構造の改善
2.3.8 明示的なオーバーライドと最終
2.3.9 ヌルポインタ定数
2.3.10 強く型付けされた列挙型
2.3.11 直角ブラケット
2.3.12 明示的な変換演算子
2.3.13 テンプレートエイリアス
2.3.14 無制限の組合
2.4 コア言語機能の改善
2.4.1 可変個引数テンプレート
2.4.2 新しい文字列リテラル
2.4.3 ユーザー定義リテラル
2.4.4 マルチスレッドメモリモデル
2.4.5 スレッドローカルストレージ
2.4.6 明示的にデフォルト設定および削除された特殊メンバー関数
2.4.7 long longintと入力します
2.4.8 静的アサーション
2.4.9 sizeofが明示的なオブジェクトなしでクラスのメンバーで機能することを許可する
2.4.10 オブジェクトの配置を制御および照会する
2.4.11 ガベージコレクションの実装を許可する
2.4.12 属性
3 C ++標準ライブラリの変更
3.1 標準ライブラリコンポーネントへのアップグレード 3.2 糸脱毛設備 3.3 タプルタイプ 3.43.4 ハッシュテーブル 3.5 正規表現 3.6 汎用スマートポインター 3.7 拡張可能な乱数機能 3.8 ラッパーリファレンス 3.9 関数オブジェクトのポリモーフィックラッパー 3.10 メタプログラミングの型特性 3.11 関数オブジェクトの戻り型を計算するための統一された方法
4 C互換性の向上
5 当初計画されていたが削除されたか含まれていない機能
6 削除または廃止された機能
7 も参照してください
8 参考文献
9 外部リンク
設計目標
助けてください、このセクションを改善することにより、信頼性の高い情報源に引用を追加します。調達されていない資料は、異議を申し立てられ、削除される可能性が
設計委員会は、C ++ 11の設計においていくつかの目標に固執しようとしました。
C ++ 98および場合によってはCとの安定性と互換性を維持します
コア言語を拡張するのではなく、標準ライブラリを介して新機能を導入することをお勧めします
プログラミング技術を進化させることができる変更を好む
特定のアプリケーションにのみ役立つ新機能を導入するのではなく、C ++を改善してシステムとライブラリの設計を容易にします
以前の安全でない技術に代わるより安全な方法を提供することにより、型安全性を向上させます
パフォーマンスとハードウェアを直接操作する機能を向上させる
現実の問題に適切な解決策を提供する
ゼロオーバーヘッドの原則を実装します(一部のユーティリティで必要な追加のサポートは、ユーティリティを使用する場合にのみ使用する必要があります)
エキスパートプログラマーが必要とするユーティリティを削除することなく、C ++の指導と学習を容易にします。
ほとんどのコンピュータープログラマーは常にそのようであり、多くの初心者は知識を広げることはなく、専門とする言語の側面での作業に限定されるため、初心者への注意は重要であると考えられています。
C ++コア言語の拡張
C ++委員会の機能の1つは、言語コアの開発です。大幅に改善されたコア言語の領域には、マルチスレッドのサポート、ジェネリックプログラミングのサポート、均一な初期化、およびパフォーマンスが含まれます。
コア言語のランタイムパフォーマンスの強化
これらの言語機能は、主に、メモリまたは計算速度のいずれかで、ある種のパフォーマンス上の利点を提供するために存在します。
参照の再評価とコンストラクターの移動
C ++ 03(およびそれ以前)では、一時(「右辺値」と呼ばれ、割り当ての右側にあることが多いため)は、Cの場合と同様に、決して変更できないように意図されており、const T&型と区別できないと見なされていました。それにもかかわらず、場合によっては、一時的なものが変更された可能性があり、その動作は有用な抜け穴であるとさえ考えられていました。 C ++ 11は、によって識別される右辺値参照T&&。これは、「移動セマンティクス」を許可する目的で、初期化後に変更が許可されている一時的なものを指します。
C ++ 03の慢性的なパフォーマンスの問題は、オブジェクトが値で渡されるときに暗黙的に発生する可能性のある、コストがかかり不要なディープコピーです。この問題を説明するためにstd::vector
C ++ 11では、
ムーブコンストラクタのstd::vector
右辺値参照は、標準ライブラリの外部で変更を加えることなく、既存のコードにパフォーマンス上の利点を提供できます。一時的なものは自動的に右辺値と見なされるため、std::vector
安全上の理由から、いくつかの制限が課せられます。名前付き変数は、そのように宣言されていても、右辺値とは見なされません。右辺値を取得するには、関数テンプレートstd::move()を使用する必要が右辺値参照は、主に移動コンストラクターで使用することを目的として、特定の状況でのみ変更することもできます。
右辺値参照の言い回しの性質、および左辺値参照(通常の参照)の言い回しの変更により、右辺値参照を使用すると、開発者は完全な関数転送を提供できます。可変個引数テンプレートと組み合わせると、この機能により、特定の引数を取る別の関数に引数を完全に転送できる関数テンプレートが可能になります。これは、コンストラクターパラメーターを転送して、それらの特定の引数に対して正しいコンストラクターを自動的に呼び出すファクトリ関数を作成する場合に最も役立ちます。これは、C ++標準ライブラリメソッドのemplace_backセットに見られます。
constexpr –一般化された定数式
C ++には、常に定数式の概念がこれらは3+4、コンパイル時と実行時に常に同じ結果をもたらすような式です。定数式はコンパイラーにとって最適化の機会であり、コンパイラーはコンパイル時に定数式を頻繁に実行し、結果をプログラムにハードコーディングします。また、いくつかの場所で、C ++仕様では定数式を使用する必要が配列を定義するには定数式が必要であり、列挙子の値は定数式である必要が
ただし、定数式に関数呼び出しまたはオブジェクトコンストラクターを含めることは許可されしたがって、これと同じくらい単純なコードは無効です。
int get_five (){ return 5 ;} int some_value [ get_five ()+ 7 ]; // 12個の整数の配列を作成します。不正な形式のC ++
get_five() + 7は定数式ではないため、これはC ++ 03では無効でした。C ++ 03コンパイラget_five()には、実行時に実際に定数であるかどうかを知る方法がありません。理論的には、この関数はグローバル変数に影響を与えたり、他の非実行時定数関数を呼び出したりする可能性が
C ++ 11ではキーワードが導入されましたconstexpr。これにより、ユーザーは関数またはオブジェクトのコンストラクターがコンパイル時定数であることを保証できます。上記の例は次のように書き直すことができます。
constexpr int get_five (){ return 5 ;} int some_value [ get_five ()+ 7 ]; // 12個の整数の配列を作成します。有効なC ++ 11
これにより、コンパイラget_five()はコンパイル時定数を理解して検証できます。
constexpr関数で使用すると、その関数で実行できる操作にいくつかの制限が課せられます。まず、関数は非voidの戻り型を持っている必要が次に、関数本体は変数を宣言したり、新しい型を定義したりすることはできません。第3に、本文には、宣言、nullステートメント、および単一のreturnステートメントのみを含めることができます。引数の置換後、returnステートメントの式が定数式を生成するような引数値が存在する必要が
C ++ 11より前では、変数の値は、変数がconstとして宣言され、定数式であるイニシャライザーがあり、整数型または列挙型である場合にのみ、定数式で使用できました。C ++ 11は、変数がconstexprキーワードで定義されている場合、変数が整数型または列挙型でなければならないという制限を取り除きます。
constexpr double earth_gravitational_acceleration = 9.8 ; constexpr double moon_gravitational_acceleration = earth_gravitational_acceleration / 6.0 ;
このようなデータ変数は暗黙的にconstであり、定数式である必要がある初期化子を持っている必要が
ユーザー定義型から定数式のデータ値を作成するために、コンストラクターをで宣言することもできますconstexpr。constexprコンストラクタの関数本体は宣言のみとヌル文を含めることができ、および変数を宣言するかのタイプを定義することはできません、と同様constexprの機能。引数の置換後、定数式でクラスのメンバーを初期化するような引数値が存在する必要がこのようなタイプのデストラクタは些細なものでなければなりません。
型のコピーコンストラクターは、constexpr通常、constexprコンストラクターとして定義する必要がこれにより、型のオブジェクトをconstexpr関数から値で返すことができます。コピーコンストラクター、演算子のオーバーロードなど、クラスのすべてのメンバー関数は、constexprconstexpr関数の要件を満たしている限り、として宣言できます。これにより、コンパイラはコンパイル時にオブジェクトをコピーしたり、オブジェクトに対して操作を実行したりできます。
constexpr関数またはコンストラクターが定数式ではない引数を使用して呼び出された場合、呼び出しは関数がconstexprでないかのように動作し、結果の値は定数式ではありません。同様に、constexpr関数のreturnステートメントの式が、特定の呼び出しに対して定数式に評価されない場合、結果は定数式ではありません。
constexprC ++ 20constevalで導入されたとは異なり、後者は常にコンパイル時定数を生成する必要がありますが、この制限はありません。constexpr
プレーンな古いデータの定義の変更
C ++ 03では、クラスまたは構造体がプレーンオールドデータ(POD)型と見なされるためには、いくつかの規則に従う必要がこの定義に適合するタイプは、Cと互換性のあるオブジェクトレイアウトを生成し、静的に初期化することもできます。C ++ 03標準には、Cと互換性のあるタイプ、またはコンパイラがプログラムを受け入れることができなかった技術的な理由がないにもかかわらず静的に初期化できるタイプに制限が誰かがC ++ 03 PODタイプを作成し、非仮想メンバー関数を追加した場合、このタイプはPODタイプではなくなり、静的に初期化できず、メモリレイアウトに変更がないにもかかわらず、Cと互換性がなくなります。 。
C ++ 11は、PODの概念を2つの別個の概念(トリビアルと標準レイアウト)に分割することにより、PODルールのいくつかを緩和しました。
些細なタイプは静的に初期化できます。またmemcpy、コピーコンストラクターを使用するのではなく、を介してデータをコピーすることが有効であることも意味します。トリビアル型の存続期間は、コンストラクターが完了したときではなく、ストレージが定義されたときに始まります。
些細なクラスまたは構造体は、次のようなものとして定義されます。
些細なデフォルトコンストラクタがこれは、デフォルトのコンストラクタ構文(SomeConstructor() = default;)を使用する場合が
簡単なコピーおよび移動コンストラクターがあり、デフォルトの構文を使用できます。
簡単なコピーおよびムーブ代入演算子があり、デフォルトの構文を使用できます。
些細なデストラクタがありますが、仮想であってはなりません。
クラスの仮想メンバー関数と仮想基本クラスがない場合にのみ、コンストラクターは簡単です。コピー/移動操作では、すべての非静的データメンバーが簡単である必要も
標準レイアウトであるタイプは、Cと互換性のある方法でメンバーを注文およびパックすることを意味します。クラスまたは構造体は、定義上、次の条件で標準レイアウトです。
仮想機能はありません
仮想基本クラスはありません
そのすべての非静的データメンバーは、同じアクセス制御(パブリック、プライベート、保護)を持っています
基本クラスのメンバーを含むすべての非静的データメンバーは、階層内の同じ1つのクラスにあります
上記のルールは、すべての基本クラスと、クラス階層内のすべての非静的データメンバーにも適用されます。
最初に定義された非静的データメンバーと同じタイプの基本クラスはありません
クラス/構造体/共用体は、それが些細な標準レイアウトであり、その非静的データメンバーと基本クラスがすべてPODである場合、PODと見なされます。
これらの概念を分離することにより、一方を失うことなく、もう一方を放棄することが可能になります。複雑なmoveおよびcopyコンストラクターを持つクラスは簡単ではないかもしれませんが、標準レイアウトである可能性があり、したがってCと相互運用できます。同様に、パブリックおよびプライベートの非静的データメンバーを持つクラスは標準レイアウトではありませんが、memcpy取るに足らない、したがって-可能。
コア言語のビルド時のパフォーマンスの強化編集
外部テンプレート
C ++ 03では、完全に指定されたテンプレートが変換ユニットで検出されるたびに、コンパイラーはテンプレートをインスタンス化する必要がテンプレートが多くの変換ユニットで同じタイプでインスタンス化される場合、これによりコンパイル時間が大幅に増加する可能性がC ++ 03ではこれを防ぐ方法がないため、C ++ 11では、externデータ宣言に類似したexternテンプレート宣言が導入されました。
C ++ 03には、コンパイラにテンプレートのインスタンス化を義務付ける次の構文が
テンプレートクラスstd :: vector < MyClass > ;
C ++ 11は、次の構文を提供するようになりました。
extern template class std :: vector < MyClass > ;
これは、この変換ユニットでテンプレートをインスタンス化しないようにコンパイラーに指示します。
コア言語のユーザビリティの強化
これらの機能は、言語を使いやすくすることを主な目的として存在します。これらにより、型の安全性が向上し、コードの繰り返しが最小限に抑えられ、誤ったコードが発生しにくくなります。
イニシャライザリスト
C ++ 03は、Cから初期化リスト機能を継承しました。構造体または配列には、構造体内のメンバーの定義順に、引数のリストが中括弧で囲まれて指定されます。これらの初期化子リストは再帰的であるため、構造体の配列または他の構造体を含む構造体がそれらを使用できます。
構造体 オブジェクト{{ 最初にフロート; int秒; };オブジェクトスカラー= { 0.43f 、10 }; // 1つのオブジェクト、first = 0.43fおよびsecond = 10のオブジェクトanArray [] = {{ 13.4f 、3 }、{ 43.28f 、29 }、{ 5.934f 、17 }}; // 3つのオブジェクトの配列
これは、静的リスト、または構造体をある値に初期化する場合に非常に役立ちます。C ++には、オブジェクトを初期化するためのコンストラクターも用意されていますが、初期化子リストほど便利ではないことがよくただし、C ++ 03では、Plain Old Data(POD)定義に準拠する構造体とクラスの初期化子リストのみが許可されます。C ++ 11は初期化子リストを拡張するため、のような標準コンテナーを含むすべてのクラスで使用できますstd::vector。
C ++ 11は、概念をと呼ばれるテンプレートにバインドしstd::initializer_listます。これにより、コンストラクターやその他の関数が初期化子リストをパラメーターとして受け取ることができます。例えば:
クラス SequenceClass{{パブリック: SequenceClass (std :: initializer_list < int > list ); };
これによりSequenceClass、次のような整数のシーケンスから構築できます。
SequenceClass some_var = { 1 、4 、5 、6 }。
このコンストラクターは、initializer-list-constructorと呼ばれる特別な種類のコンストラクターです。このようなコンストラクターを持つクラスは、均一な初期化中に特別に扱われます(以下を参照)。クラスstd::initializer_list<>は、ファーストクラスのC ++ 11標準ライブラリタイプです。これらは、C ++ 11コンパイラ{}によって、そのような中括弧がに推論されるコンテキストで型名なしの構文を使用するstd::initializer_listか、またはのような型を明示的に指定することによって静的に構築できますstd::initializer_list
リストは一度作成するとコピーできます。これは安価で、参照によるコピーとして機能します(クラスは通常、開始/終了ポインターのペアとして実装されます)。Anstd::initializer_listは定数です。メンバーは、作成後に変更することはできません。また、それらのメンバーのデータを変更することもできません(メンバーからの移動、クラスメンバーへのコピーの必要性など)。
その構造はコンパイラによって特別に扱われますが、anstd::initializer_listは実数型であるため、クラスコンストラクタ以外の場所でも使用できます。通常の関数は、型付きstd::initializer_listのsを引数として取ることができます。例えば:
void function_name (std :: initializer_list < float > list ); //コピーは安価です。上記を参照 function_name ({ 1.0f 、-3.45f 、-0.4f });
標準ライブラリでのこの例には、数値型のsをとるテンプレートstd::min()とstd::max()テンプレートが含まれstd::initializer_listます。
標準コンテナは、次の方法で初期化することもできます。
std :: vector < std :: string > v = { “xyzzy” 、”plugh” 、”abracadabra” };
std :: vector < std :: string > v ({ “xyzzy” 、”plugh” 、”abracadabra” }); std :: vector < std :: string > v { “xyzzy” 、”plugh” 、”abracadabra” }; //以下の「均一な初期化」を参照してください
均一な初期化
C ++ 03には、型の初期化に関して多くの問題がこれを行うにはいくつかの方法があり、交換すると異なる結果が得られる方法もたとえば、従来のコンストラクタ構文は関数宣言のように見える可能性があり、コンパイラの最も厄介な解析ルールがそれをそのように誤解しないようにするための手順を実行する必要がアグリゲート初期化子(を使用SomeType var = {/*stuff*/};)で初期化できるのは、アグリゲートとPODタイプのみです。
C ++ 11は、任意のオブジェクトで機能する完全に均一な型の初期化を可能にする構文を提供します。イニシャライザリストの構文を拡張します。
struct BasicStruct{{ int x ; ダブルy ; };構造体 AltStruct{{ AltStruct (int x 、double y )
:x_ { x }
、y_ { y } {}プライベート: int x_ ; ダブルy_ ; };BasicStruct VAR1 { 5 、3.2 }。 AltStruct VAR2 { 2 、4.3 }。
の初期化は、var1集計初期化とまったく同じように動作します。つまり、オブジェクトの各データメンバーは、イニシャライザリストの対応する値でコピー初期化されます。暗黙の型変換は、必要に応じて使用されます。変換が存在しない場合、または絞り込み変換のみが存在する場合、プログラムの形式は正しくありません。の初期化によりvar2、コンストラクターが呼び出されます。
これを行うこともできます:
struct IdString{{ std ::文字列名; int識別子; };IdString get_string () {{ return { “foo” 、42 }; //明示的な型がないことに注意して}
均一な初期化は、コンストラクター構文を置き換えるものではありません。コンストラクター構文は、依然として必要になる場合がクラスに初期化子リストコンストラクター(TypeName(initializer_list
std :: vector < int > the_vec { 4 };
イニシャライザリストコンストラクタを呼び出します。そのコンストラクタはstd::vector単一のサイズパラメータを取り、そのサイズでベクトルを作成しません。後者のコンストラクターにアクセスするには、ユーザーは標準のコンストラクター構文を直接使用する必要が
型推論
C ++ 03(およびC)では、変数を使用するには、その型を明示的に指定する必要がただし、テンプレートタイプとテンプレートメタプログラミング手法の出現により、何かのタイプ、特に関数の明確に定義された戻り値を簡単に表現できない場合がしたがって、中間体を変数に格納することは困難であり、特定のメタプログラミングライブラリの内部に関する知識が必要になる可能性が
C ++ 11では、これを2つの方法で軽減できます。まず、明示的な初期化を使用した変数の定義では、autoキーワードを使用できます。 これにより、イニシャライザーの特定のタイプの変数が作成されます。
auto some_strange_callable_type = std :: bind (&some_function 、_2 、_1 、some_object );
auto other_variable = 5 ;
のタイプはsome_strange_callable_type、特定のテンプレート関数がstd::bindそれらの特定の引数に対して返すものを単純にオーバーライドします。このタイプは、セマンティック分析業務の一部としてコンパイラーによって手続き的に簡単に判別されますが、ユーザーが検査時に判別するのは簡単ではありません。のタイプother_variableも明確に定義されていますが、ユーザーが判断しやすくなっています。それはint整数リテラルと同じタイプです。
キーワードのこの使用autoC ++再目的で本来タイプなし先行言語で使用されたこのキーワードの意味論B型なし表すの関連役割に自動変数の定義。
さらに、このキーワードdecltypeを使用して、コンパイル時に式のタイプを判別できます。例えば:
int some_int ; decltype (some_int )other_integer_variable = 5 ;
auto自動変数のタイプはコンパイラーだけが知っているので、これは、と組み合わせて使用するとさらに便利です。ただし、演算子のオーバーロードや特殊な型decltypeを多用するコード内の式にも非常に役立ちます。
autoコードの冗長性を減らすのにも役立ちます。たとえば、書く代わりに
以下のため(のstd ::ベクトル<整数> :: const_iteratorのITR = myvec 。cbegin (); ITR != myvec 。CEND (); ++ ITR )
プログラマーはより短いものを使用できます
用(オートITR = myvec 。cbegin (); ITR != myvec 。CEND (); ++ ITRは)
「myvec」は開始/終了イテレータを実装しているため、これをさらに圧縮できます。
for (const auto &x :myvec )
この違いは、プログラマーがコンテナーをネストし始めるにつれて大きくなりますが、そのような場合typedefは、コードの量を減らすための良い方法です。
で示されるタイプは、でdecltype推定されるタイプとは異なる場合がありますauto。
#include
自動a = v ; // aの型はintdecltype (v )b = 1 ; // bの型はconstint &で、戻り型は// std :: vector
範囲ベースのforループ
C ++ 11は、forステートメントの構文を拡張して、要素の範囲で簡単に反復できるようにします。
INTのmy_arrayで = { 1 、2 、3 、4 、5 }。
// my_arrayの各要素の値を2倍にします:for (int &x :my_array )
x * = 2 ; //似ていますが、(auto &x :my_array )の配列要素の型推論も使用します
x * = 2 ;
for「範囲ベースの」と呼ばれるこの形式は、リスト内の各要素を反復処理します。これは、Cスタイルの配列、リスト初期化、および持っている任意のタイプのために働くだろうbegin()とend()そのリターンイテレータそれのために定義された関数。開始/終了ペアを持つすべての標準ライブラリコンテナは、範囲ベースのforステートメントで機能します。
ラムダ関数と式
無名関数§C++(C ++ 11以降)
C ++ 11は、ラムダ関数と呼ばれる無名関数を作成する機能を提供します。これらは次のように定義されています。
[](int x 、int y )-> int { return x + y ; }-> intすべてのreturn式が同じ型を返す限り、戻り型(この例では)は省略できます。ラムダはオプションでクロージャにすることができます。
代替関数の構文
標準のC関数宣言構文は、C言語の機能セットには完全に適切でした。C ++がCから進化するにつれて、基本的な構文を維持し、必要に応じて拡張しました。ただし、C ++がより複雑になるにつれて、特にテンプレート関数の宣言に関して、いくつかの制限が発生しました。たとえば、C ++ 03では、これは許可され<クラス Lhs 、クラスRhs > Ret add_func (const Lhs &lhs 、const Rhs &rhs ){ return lhs + rhs ;} // Retはlhs + rhsのタイプである必要があります
タイプRetは、タイプLhsを追加したものであり、Rhs生成されます。前述ののC ++ 11機能を使用してもdecltype、これは不可能です。<クラス Lhs 、クラスRhs > decltype (lhs + rhs )adding_func (const Lhs &lhs 、const Rhs &rhs ){ return lhs + rhs ;} //無効C ++ 11
lhsとrhsはまだ定義されていないため、これは有効なC ++ではありません。パーサーが関数プロトタイプの残りの部分を解析するまで、これらは有効な識別子にはなりません。
これを回避するために、C ++ 11では、末尾にreturn-typeを使用した新しい関数宣言構文が導入されました。<クラス Lhs 、クラスRhs > 自動adding_func (const Lhs &lhs 、const Rhs &rhs )-> decltype (lhs + rhs ){ return lhs + rhs ;}
この構文は、よりありふれた関数の宣言と定義に使用できます。
struct SomeStruct{{ auto func_name (int x 、int y )-> int ;
};auto SomeStruct :: func_name (int x 、int y )-> int
{{ x + yを返す; }
この場合の「auto」キーワードの使用は構文の一部にすぎず、C ++ 11では自動型推定を実行しません。ただし、C ++ 14以降では、末尾の戻り型を完全に削除でき、コンパイラーは戻り型を自動的に推測します。
オブジェクト構造の改善
C ++ 03では、クラスのコンストラクターは、そのクラスの初期化子リスト内の他のコンストラクターを呼び出すことはできません。各コンストラクターは、次のように、すべてのクラスメンバー自体を構築するか、共通のメンバー関数を呼び出す必要が
クラス SomeType{{パブリック: SomeType (int new_number ) {{
構築(new_number ); } SomeType () {{
構築(42 ); }プライベート: void構文(int new_number ) {{ 番号= new_number ;
} int番号; };
基本クラスのコンストラクターは、派生クラスに直接公開することはできません。基本クラスのコンストラクターが適切な場合でも、各派生クラスはコンストラクターを実装する必要がクラスの非定数データメンバーは、それらのメンバーの宣言のサイトで初期化できません。これらはコンストラクターでのみ初期化できます。
C ++ 11は、これらすべての問題の解決策を提供します。
C ++ 11では、コンストラクターが他のピアコンストラクター(委任と呼ばれる)を呼び出すことができます。これにより、コンストラクターは、最小限の追加コードで別のコンストラクターの動作を利用できます。委任は、JavaやObjective-Cなどの他の言語で使用されています。
この構文は次のとおりです。
クラス SomeType{{ int番号; パブリック: SomeType (int new_number ):number (new_number ){}
SomeType ():SomeType (42 ){} };
この場合、new_numberデフォルトのパラメータを作成することで同じ効果が得られる可能性があることに注意してただし、新しい構文では、インターフェイスではなく実装でデフォルト値(42)を表現できます。コンストラクターの委任では、関数パラメーターのデフォルト値がサイトの呼び出しに「組み込まれる」ため、ライブラリコードのメンテナーにとってメリットがライブラリを使用してコードを再コンパイルせずに変更される値。
これは、警告が付属しています:C ++ 03には、そのコンストラクタが終了すると実行時に構築されるオブジェクトと見なしますが、C ++ 11には、一度構築されたオブジェクトと考える任意のコンストラクタの終了の実行を。複数のコンストラクターの実行が許可されるため、これは、各委任コンストラクターが独自のタイプの完全に構築されたオブジェクトで実行されることを意味します。派生クラスコンストラクターは、基本クラスのすべての委任が完了した後に実行されます。
基本クラスのコンストラクターの場合、C ++ 11では、基本クラスのコンストラクターを継承するようにクラスで指定できます。したがって、C ++ 11コンパイラは、派生クラスの継承と基本クラスへの転送を実行するコードを生成します。これはオールオアナッシング機能です。その基本クラスのコンストラクターがすべて転送されるか、転送されないかのどちらかです。また、継承されたコンストラクターは、派生クラスのコンストラクターの署名と一致する場合はシャドウされ、複数の継承には制限がクラスコンストラクターは、同じ署名を持つコンストラクターを使用する2つのクラスから継承できません。
構文は次のとおりです。
クラス BaseClass{{パブリック: BaseClass (int value ); };class DerivedClass :public BaseClass {{パブリック: BaseClassを使用する:: BaseClass ; };
メンバーの初期化の場合、C ++ 11では次の構文が許可されます。
クラス SomeClass{{パブリック: SomeClass (){} 明示的なSomeClass (int new_value ):value (new_value ){} プライベート: int値= 5 ; };
クラスvalueのコンストラクターは、コンストラクターが独自の初期化をオーバーライドしない場合、5で初期化されます。したがって、上記の空のコンストラクターはvalueクラス定義の状態に従って初期化されますが、intを受け取るコンストラクターは、指定されたパラメーターに初期化されます。
上記の代入初期化の代わりに、コンストラクターまたは均一初期化を使用することもできます。
明示的なオーバーライドと最終
C ++ 03では、基本クラス関数をオーバーライドしようとしたときに、誤って新しい仮想関数を作成する可能性が例えば:
構造体 ベース{{ virtual void some_func (float ); };構造体 派生:ベース {{ virtual void some_func (int ); };
Derived::some_funcが基本クラスバージョンを置き換えることを目的としているとします。ただし、代わりに、署名が異なるため、2番目の仮想関数が作成されます。これは、特にユーザーが基本クラスを変更しようとする場合によくある問題です。
C ++ 11は、この問題を解決するための構文を提供します。
構造体 ベース{{ virtual void some_func (float ); };構造体 派生:ベース {{ virtual void some_func (int )override ; //不正な形式-基本クラスのメソッドをオーバーライドしません};
overrideコンパイラは、この正確なシグネチャを持つ仮想関数が存在するかどうかを確認するためにベース・クラス(複数可)をチェックする特別な識別子手段。存在しない場合、コンパイラはエラーを示します。
C ++ 11には、クラスからの継承を防止したり、派生クラスのメソッドのオーバーライドを防止したりする機能も追加されています。これは、特別な識別子を使用して行われますfinal。例えば:
struct Base1 final { }; struct Derived1 :Base1 { }; //クラスBase1がfinalとマークされているため、形式が正しくありません
struct Base2{{ 仮想ボイドf ()最終; };struct Derived2 :Base2 {{ void f (); //仮想関数Base2 :: fがfinalとマークされているため、形式が正しくありません};
この例では、virtual void f() final;ステートメントは新しい仮想関数を宣言しますが、派生クラスがそれをオーバーライドすることも防ぎます。また、派生クラスがその特定の関数名とパラメーターの組み合わせを使用するのを防ぐ効果も
言語キーワードでもないoverrideことに注意してくださいfinal。これらは、技術的には宣言者属性の識別子です。
これらは、特定の末尾のコンテキスト(すべての型指定子、アクセス指定子、メンバー宣言(struct、class、およびenum型の場合)、および宣言子指定子の後、ただし、各宣言子の初期化またはコード実装の前にコンマで使用される場合にのみ、属性として特別な意味を持ちます。 -宣言者の個別のリスト);
宣言された型シグネチャを変更したり、スコープ内の新しい識別子を宣言またはオーバーライドしたりすることはありません。
認識および受け入れられた宣言子属性は、C ++の将来のバージョンで拡張される可能性があります(一部のコンパイラ固有の拡張機能は、追加された宣言子属性をすでに認識しており、コンパイラにコード生成オプションまたは最適化ヒントを提供したり、コンパイルされたコードに追加データを生成したりします。コンパイラ、リンカ、およびコンパイルされたコードの展開、追加のシステム固有のセキュリティ属性の提供、実行時のリフレクション機能の強化、または他のプログラミング言語やランタイムシステムとの相互運用性のための追加のバインディング情報の提供。これらの拡張機能はパラメータを取る場合が宣言子属性識別子の後の括弧の間。ANSI準拠の場合、これらのコンパイラ固有の拡張機能では、二重下線プレフィックス規則を使用する必要があります)。
他の場所では、それらは新しい宣言の有効な識別子になる可能性があります(後でアクセス可能な場合に使用されます)。
ヌルポインタ定数
このセクションおよびこのセクションのみの目的のために、「0」のすべての出現は、「0int型であると評価される定数式」を意味します。実際には、定数式は任意の整数型にすることができます。
1972年のCの夜明け以来、定数0は定数整数とnullポインタ定数の2つの役割を果たしてきました。の二重の意味に固有のあいまいさ0は、プリプロセッサマクロを使用してCで処理されました。NULLこれは、通常、((void*)0)またはのいずれかに展開されます0。C ++は、void *から他のポインタ型への暗黙の変換を禁止しているため、にキャスト0する利点がなくなりvoid *ます。結果0として、nullポインタ定数としてのみ許可されます。これは、関数のオーバーロードとの相互作用が不十分です。
void foo (char * ); void foo (int );
場合NULLのように定義される0(通常はC ++での場合である)、ステートメントがfoo(NULL);呼び出されますfoo(int)、コードの表面的な読み取りが示唆何プログラマが意図したものをほぼ確実にされていない、とではありません。
C ++ 11は、識別されたnullポインタ定数として機能する新しいキーワードを導入することでこれを修正しますnullptr。これはタイプnullptr_tであり、暗黙的に変換可能であり、任意のポインター型またはポインターからメンバーへの型に匹敵します。を除いて、暗黙的に変換可能または整数型に匹敵するものではありませんbool。元の提案では、型の右辺値をnullptr_tに変換できないように指定されていましたがbool、コア言語ワーキンググループは、通常のポインター型との一貫性を保つために、そのような変換が望ましいと判断しました。提案された文言の変更は、2008年6月に全会一致でワーキングペーパーに投票されました。同様の提案がC標準ワーキンググループにも持ち込まれています。
下位互換性の理由から、0は有効なnullポインタ定数のままです。
char * pc = nullptr ; // OK int * pi = nullptr ; // OK bool b = nullptr ; // わかった。bは偽です。int i = nullptr ; // エラー
foo (nullptr ); // foo(int);ではなくfoo(nullptr_t)を呼び出します。/ * foo(nullptr_t)は 、スコープ内の互換性のあるポインター型でオーバーロードしている他の関数がない場合にのみ、暗黙の変換を使用して上記の例で実際にfoo(char *)を呼び出すことに注意して 複数のオーバーロードが存在する場合 、foo(nullptr_t)の明示的な宣言がない限り、解決はあいまいであるため失敗します。
C ++ 11の標準型ヘッダーでは、nullptr_t型は次のように宣言する必要がありtypedefdecltype(nullptr)nullptr_t; ただし、次のようにはなりません:
typedef int nullptr_t; // NULLを0として定義する必要がある以前のバージョンのC ++
typedef void * nullptr_t; // NULLを((void *)0)として定義するANSI C * /
強く型付けされた列挙型
C ++ 03では、列挙はタイプセーフではありません。列挙型が異なる場合でも、これらは事実上整数です。これにより、異なる列挙型の2つの列挙値を比較できます。C ++ 03が提供する唯一の安全性は、ある列挙型の整数または値が暗黙的に別の列挙型に変換されないことです。さらに、基礎となる整数型は実装定義です。したがって、列挙型のサイズに依存するコードは移植性がありません。最後に、列挙値はそれを囲むスコープにスコープされます。したがって、同じスコープ内の2つの別々の列挙型が一致するメンバー名を持つことはできません。
C ++ 11では、これらの問題がない特別な列挙の分類が可能です。これは、enum class(enum struct同義語としても受け入れられる)宣言を使用して表されます。
列挙型 クラス列挙 {{ Val1 、 Val2 、 Val3 = 100 、
Val4 // = 101 };
この列挙はタイプセーフです。列挙型クラスの値は、暗黙的に整数に変換されません。したがって、整数と比較することもできません(式Enumeration::Val4 == 101でコンパイルエラーが発生します)。
列挙型クラスの基になるタイプは常にわかっています。デフォルトのタイプはint;です。この例に見られるように、これは別の整数型にオーバーライドできます。
列挙型 クラスEnum2 :unsigned int { Val1 、Val2 };
古いスタイルの列挙では、値は外部スコープに配置されます。新しいスタイルの列挙では、それらはenumクラス名のスコープ内に配置されます。したがって、上記の例でVal1は、は未定義ですがEnum2::Val1、定義されています。
古いスタイルの列挙型が明示的なスコープを提供できるようにする移行構文と、基になる型の定義も
enum Enum3 :unsigned long { Val1 = 1 、Val2 };
この場合、列挙子名は列挙型のスコープ(Enum3::Val1)で定義されますが、下位互換性のために、それらは囲んでいるスコープにも配置されます。
前方宣言列挙型はC ++ 11でも可能です。以前は、列挙型のサイズはそのメンバーの定義に依存するため、列挙型を前方宣言することはできませんでした。列挙型のサイズが暗黙的または明示的に指定されている限り、前方宣言することができます。
列挙型 Enum1 ; // C ++ 03およびC ++ 11では無効です。基になるタイプを判別できません。enum Enum2 :unsigned int ; // C ++ 11で有効で、基になるタイプは明示的に指定されます。列挙型クラスEnum3 ; // C ++ 11で有効で、基になる型はintです。列挙型クラスEnum4 :unsigned int ; // C ++ 11で有効です。列挙型Enum2 :unsigned short ; // Enum2は以前は別の基になる型で宣言されていたため、C ++ 11では無効です。
直角ブラケット
C ++ 03のパーサーは>>、すべての場合に「」を右シフト演算子またはストリーム抽出演算子として定義します。ただし、ネストされたテンプレート宣言では、プログラマーが2つの直角括弧の間にスペースを入れることを怠る傾向があるため、コンパイラーの構文エラーが発生します。
C ++ 11はパーサーの仕様を改善し、複数の右山括弧が妥当な場所でテンプレート引数リストを閉じると解釈されるようにします。これは、「>」、「>=」、または「>>」の二項演算子を使用してパラメーター式を括弧で囲むことでオーバーライドできます。<ブールテスト>クラスSomeType 。 std :: vector < SomeType < 1 > 2 >> x1 ; // SomeType
明示的な変換演算子
C ++ 98は、explicit単一引数のコンストラクターが暗黙の型変換演算子として使用されないようにするために、コンストラクターの修飾子としてキーワードを追加しました。ただし、これは実際の変換演算子には何もしません。たとえば、スマートポインタークラスにはoperator bool()、プリミティブポインターのように動作できるようにするためのがこの変換が含まれている場合は、でテストできますif (smart_ptr_variable)(ポインターがnull以外の場合はtrue、そうでない場合はfalse)。ただし、これにより、他の意図しない変換も可能になります。C ++boolは算術型として定義されているため、整数型または浮動小数点型に暗黙的に変換できます。これにより、ユーザーが意図しない数学演算が可能になります。
C ++ 11では、explicitキーワードを変換演算子に適用できるようになりました。コンストラクターと同様に、暗黙の変換でこれらの変換関数を使用することを防ぎます。ただし、ブール値(ifステートメントとループの条件、および論理演算子のオペランド)を特に必要とする言語コンテキストは、明示的な変換としてカウントされるため、ブール変換演算子を使用できます。
たとえば、この機能は安全なブール問題をきれいに解決します。エイリアス
C ++ 03では、typedefを別のタイプのシノニムとしてのみ定義できます。これには、すべての実際のテンプレート引数が指定されたテンプレート特殊化のシノニムが含まれます。typedefテンプレートを作成することはできません。例えば:< typenameにまず、型名第二に、int型サード>
クラス SomeType ;テンプレート< typenameにセカンド> typedef SomeType < OtherType 、Second 、5 > TypedefName ; // C ++ 03では無効
これはコンパイルされません。
C ++ 11は、次の構文でこの機能を追加します。
テンプレート< typenameにまず、型名第二に、int型サード>
クラス SomeType ;テンプレート< typenameにセカンド> 使用TypedefName = SomeType < OtherType 、第二に、5 > 。
このusing構文は、C ++ 11の型エイリアシングとしても使用できます。
typedef void (* FunctionType )(double ); // FunctionTypeを使用した古いスタイル= void (* )(double ); //新しく導入された構文
無制限の組合
C ++ 03では、どのタイプのオブジェクトがのメンバーになることができるかについての制限がありますunion。たとえば、ユニオンには、重要なコンストラクタまたはデストラクタを定義するオブジェクトを含めることはできません。C ++ 11は、これらの制限の一部を解除します。
場合はunionメンバーが非自明持つ特殊なメンバ関数を、コンパイラがための同等のメンバ関数を生成しませんunion、それは手動で定義する必要が
これは、C ++ 11で許可されているユニオンの簡単な例です。
#include
};ユニオン U{{ int z ; ダブルw ; ポイントp ; // C ++ 03では無効です; C ++ 11で有効です。U (){} // Pointメンバーのため、コンストラクター定義が必要になりました。U (const Point &pt ):p (pt ){} //初期化子リストを使用してPointオブジェクトを作成します。U &operator = (const Point &pt ){ new (&p )Point (pt ); return * this ; } //配置 ‘new’を使用してPointオブジェクトを割り当てます。};
変更は現在のルールを緩和するだけなので、既存のコードを壊すことはありません。
コア言語機能の改善
これらの機能により、言語は、以前は不可能であった、非常に冗長な、または移植性のないライブラリを必要としていたことを実行できます。
可変個引数テンプレート
可変個引数テンプレート
C ++ 11では、テンプレートは可変数のテンプレートパラメーターを取ることができます。これにより、タイプセーフな可変個引数関数の定義も可能になります。
新しい文字列リテラル
C ++ 03は、2種類の文字列リテラルを提供します。二重引用符で囲まれた第1の種類は、タイプがnullで終了する配列を生成しますconst char。として定義された2番目の種類は、L””タイプがnullで終了する配列を生成しますconst wchar_t。ここwchar_tで、は未定義のサイズとセマンティクスのワイド文字です。どちらのリテラル型も、UTF-8、UTF-16、またはその他の種類のUnicode エンコーディングを使用した文字列リテラルのサポートを提供し
型の定義は、char少なくともUTF-8の8ビットコーディングを格納するために必要なサイズであり、コンパイラの基本的な実行文字セットのメンバーを含むのに十分な大きさであることを明示的に表すように変更されました。以前はC ++標準自体で後者としてのみ定義されていましたが、少なくとも8ビットを保証するためにC標準に依存していました。
C ++ 11は、UTF- 8、UTF-16、およびUTF-32の3つのUnicodeエンコーディングをサポートしています。の定義に対する以前に指摘された変更に加えてchar、C ++ 11は2つの新しい文字タイプを追加します:char16_tとchar32_t。これらは、それぞれUTF-16とUTF-32を格納するように設計されています。
これらのエンコーディングごとに文字列リテラルを作成するには、次のようにします。
u8 「私はUTF-8文字列です。」u 「これはUTF-16文字列です。」U 「これはUTF-32文字列です。」
最初の文字列のタイプは通常const char[]です。2番目の文字列のタイプはconst char16_t[](小文字の「u」プレフィックスに注意)です。3番目の文字列のタイプはconst char32_t[](大文字の「U」プレフィックス)です。
Unicode文字列リテラルを作成する場合、Unicodeコードポイントを文字列に直接挿入すると便利なことがよくこれを行うために、C ++ 11では次の構文を使用できます。
u8 「これはUnicode文字です: u2018 。」u 「これはより大きなUnicode文字です: u2018 。」U 「これはUnicode文字です: U00002018 。」
後の数字uは16進数です。通常の0xプレフィックスは必要ありません。識別子uは16ビットのUnicodeコードポイントを表します。32ビットのコードポイントを入力するには、と32Uビットの16進数を使用します。有効なUnicodeコードポイントのみを入力できます。たとえば、U + D800–U + DFFFの範囲のコードポイントは、UTF-16エンコーディングのサロゲートペア用に予約されているため、禁止されています。
また、特にXMLファイルのリテラル、スクリプト言語、または正規表現を使用する場合は、文字列を手動でエスケープしないようにすることも役立つ場合がC ++ 11は、生の文字列リテラルを提供します。
R “(文字列データスタッフ”) “R “delimiter(The String Data Stuff”)delimiter “
最初のケースでは、”(との間のすべてが)”文字列の一部です。”そして文字はエスケープする必要はありません。2番目のケースでは、”delimiter(は文字列を開始し、に)delimiter”達したときにのみ終了します。文字列delimiterは、空の文字列を含め、最大16文字の任意の文字列にすることができます。この文字列には、スペース、制御文字、含めることはできません(、)または文字を。この区切り文字列を使用すると、ユーザーは)生の文字列リテラル内に文字を含めることができます。たとえば、R”delimiter((a-z))delimiter”はと同等”(a-z)”です。
生の文字列リテラルは、ワイドリテラルまたは任意のUnicodeリテラルプレフィックスと組み合わせることができます。
u8R “XXX(私は”生のUTF-8 “文字列です。)XXX”uR “*(これは”生のUTF-16 “文字列です。)*”UR」(これは「生のUTF-32」文字列です。)」
ユーザー定義リテラル
C ++ 03は、いくつかのリテラルを提供します。文字12.5はdouble、値が12.5の型としてコンパイラーによって解決されるリテラルです。ただし、のfように接尾辞を追加すると、値12.5を含む12.5f型の値が作成されfloatます。リテラルの接尾辞修飾子はC ++仕様によって修正されており、C ++ 03コードは新しいリテラル修飾子を作成できません。
対照的に、C ++ 11を使用すると、ユーザーは、リテラルが変更する文字列に基づいてオブジェクトを構築する新しい種類のリテラル修飾子を定義できます。
リテラルの変換は、生と調理済みの2つの異なるフェーズに再定義されます。生のリテラルは特定のタイプの文字のシーケンスですが、クックされたリテラルは別のタイプです。C ++リテラルは1234、生のリテラルとして、この文字列です’1’、’2’、’3’、’4’。調理されたリテラルとしては、C ++整数リテラル1234である0xA生の形式であり’0’、’x’、’A’、調理された形態でそれが整数10です。
リテラルは、未加工の形式と調理済みの形式の両方で拡張できます。ただし、文字列リテラルは、調理済みの形式でのみ処理できます。この例外は、文字列に問題の文字の特定の意味とタイプに影響を与えるプレフィックスがあるためです。
すべてのユーザー定義リテラルはサフィックスです。プレフィックスリテラルを定義することはできません。アンダースコア(_)を除く任意の文字で始まるすべてのサフィックスは、標準で予約されています。したがって、すべてのユーザー定義リテラルには、アンダースコア(_)で始まるサフィックスが必要です。
リテラルの生の形式を処理するユーザー定義リテラルは、リテラル演算子を介して定義されoperator “”ます。リテラル演算子は、として記述されます。次に例を示します。
OutputType演算子”” _mysuffix (const char * literal_string )
{{ // OutputTypeにconstchar * OutputType ret (literal_string );を受け取るコンストラクターがあることを前提としています。
retを返す; }OutputType some_variable = 1234 _mysuffix ; // OUTPUTTYPEに戻る二重ことGET_VALUE()メソッドを持っていることを前提とアサート(some_variable 。GET_VALUE ()== 1234.0 )
代入ステートメントOutputType some_variable = 1234_mysuffix;は、ユーザー定義のリテラル関数によって定義されたコードを実行します。この関数は”1234″Cスタイルの文字列として渡されるため、ターミネータがnullになります。
整数および浮動小数点の生のリテラルを処理するための代替メカニズムは、可変個引数テンプレートを使用することです。
template < char ... > OutputType演算子”” _tuffix (); OutputType some_variable = 1234 _tuffix ; OutputType another_variable = 2.17 _tuffix ;
これにより、リテラル処理関数がとしてインスタンス化されoperator “” _tuffix<'1', '2', '3', '4'>()ます。この形式では、文字列を終了するヌル文字はありません。これを行う主な目的は、C ++ 11のconstexprキーワードを使用して、コンパイラがコンパイル時にリテラルを完全に変換することを保証することです。これOutputTypeは、constexprで構成可能でコピー可能な型であり、リテラル処理関数が関数であると想定していconstexprます。
数値リテラルの場合、クックされたリテラルのタイプは、unsigned long long整数リテラルまたはlong double浮動小数点リテラルのいずれかです。(注:符号付き整数型は、符号付きリテラルが単項接頭演算子としての符号と符号なし数値を含む式として解析されるため、必要ありません。)代替のテンプレート形式はありません。
OutputType演算子”” _suffix (unsigned long long ); OutputType演算子”” _suffix (long double ); OutputType some_variable = 1234 _suffix ; // ‘unsigned longlong’オーバーロードを使用します。OutputType another_variable = 3.1416 _suffix ; // ‘longdouble’オーバーロードを使用します。
前述の新しい文字列プレフィックスに従って、文字列リテラルの場合、これらが使用されます。
OutputType演算子”” _ssuffix (const char * string_values 、size_t num_chars );
OutputType演算子”” _ssuffix (const wchar_t * string_values 、size_t num_chars );
OutputType演算子”” _ssuffix (const char16_t * string_values 、size_t num_chars );
OutputType演算子”” _ssuffix (const char32_t * string_values 、size_t num_chars );
OutputType some_variable = “1234” _ssuffix ; // ‘const char *’オーバーロードを使用します。OutputType some_variable = u8 “1234” _ssuffix ; // ‘const char *’オーバーロードを使用します。OutputType some_variable = L “1234” _ssuffix ; // ‘const wchar_t *’オーバーロードを使用します。OutputType some_variable = u “1234” _ssuffix ; // ‘const char16_t *’オーバーロードを使用します。OutputType some_variable = U “1234” _ssuffix ; // ‘const char32_t *’オーバーロードを使用します。
代替のテンプレートフォームはありません。文字リテラルも同様に定義されます。
マルチスレッドメモリモデル
参照:
メモリモデル(コンピューティング)
C ++ 11は、マルチスレッドプログラミングのサポートを標準化します。
関係する2つの部分があります:複数のスレッドがプログラム内で共存できるようにするメモリモデルと、スレッド間の相互作用のためのライブラリサポートです。(スレッド機能に関するのセクションを参照して)
メモリモデルは、複数のスレッドが同じメモリ位置にアクセスできるタイミングを定義し、1つのスレッドによる更新が他のスレッドに表示されるタイミングを指定します。
スレッドローカルストレージ
マルチスレッド環境では、すべてのスレッドがいくつかの一意の変数を持つのが一般的です。これは、関数のローカル変数ではすでに発生していますが、グローバル変数と静的変数では発生しません。(既存の静的、動的、および自動に加えて)新しいスレッドローカルストレージ期間は、ストレージ指定子によって示されます。thread_local
静的ストレージ期間(つまり、プログラムの実行全体にまたがる存続期間)を持つ可能性のあるオブジェクトには、代わりにスレッドローカル期間を指定できます。その目的は、他のstatic-duration変数と同様に、スレッドローカルオブジェクトをコンストラクターを使用して初期化し、デストラクタを使用して破棄できるようにすることです。
明示的にデフォルト設定および削除された特殊メンバー関数
C ++ 03では、コンパイラーは、それらを提供しないクラスに対して、デフォルトコンストラクター、コピーコンストラクター、コピー代入演算子(operator=)、およびデストラクタを提供します。プログラマーは、カスタムバージョンを定義することにより、これらのデフォルトをオーバーライドできます。C ++はoperator new、プログラマーがオーバーライドできるすべてのクラスで機能するいくつかのグローバル演算子(など)も定義します。
ただし、これらのデフォルトの作成を制御することはほとんどできません。たとえば、クラスを本質的にコピー不可にするには、プライベートコピーコンストラクターとコピー代入演算子を宣言し、それらを定義しない必要がこれらの関数を使用しようとすると、単一定義規則(ODR)に違反します。診断メッセージは必要ありませんが、違反するとリンカーエラーが発生する可能性が
クラスがで定義されている場合、デフォルトコンストラクタの場合は、コンパイラがデフォルトコンストラクタを生成しません任意のコンストラクタ。これは多くの場合に役立ちますが、特殊なコンストラクターとコンパイラーによって生成されたデフォルトの両方を使用できることも役立ちます。
C ++ 11では、これらの特別なメンバー関数の明示的なデフォルト設定と削除が可能です。たとえば、このタイプは、デフォルトのコンストラクターを使用していることを明示的に宣言します。
struct SomeType{{ SomeType ()=デフォルト; //デフォルトのコンストラクタは明示的に指定されています。SomeType (OtherType value ); }; または、特定の機能を明示的に無効にすることもできます。たとえば、このタイプはコピーできません。
構造体の コピー不可{{ NonCopyable ()=デフォルト;
NonCopyable (const NonCopyable &)=削除;
NonCopyable &operator = (const NonCopyable &)= delete ; };= delete指定子は、特定のパラメータを持つメンバ関数を呼び出す禁止するために使用することができる任意の関数を呼び出すことを禁止するために使用することができます。例えば:
struct NoInt{{ void f (double i );
void f (int )=削除; };
呼び出そうとf()しては、intその代わりにサイレント変換を行う、コンパイラによって拒否されますdouble。これを一般化してdouble、次以外のタイプで関数を呼び出さないようにすることができます。
struct OnlyDouble{{ void f (double d );
テンプレート<クラス T > void f (T )=削除; };
タイプ long long int
C ++ 03では、最大の整数型はlong intです。少なくとも。と同じ数の使用可能なビットがあることが保証されていintます。これにより、long int一部の一般的な実装では64ビット、その他の実装では32ビットのサイズになりました。C ++ 11は、long long intこの問題に対処するために新しい整数型を追加します。少なくともlong int、と同じ大きさで、64ビット以上であることが保証されています。この型は元々C99によって標準Cに導入され、ほとんどのC ++コンパイラーはすでに拡張機能としてサポートしていました。
静的アサーション
C ++ 03は、アサーションをテストするための2つのメソッドを提供します。マクロassertとプリプロセッサディレクティブ#errorです。ただし、どちらもテンプレートでの使用には適しマクロは実行時にアサーションをテストし、プリプロセッサディレクティブはテンプレートのインスタンス化の前に行われる前処理中にアサーションをテストします。テンプレートパラメータに依存するプロパティのテストにはどちらも適切ではありません。
新しいユーティリティは、新しいキーワードを使用して、コンパイル時にアサーションをテストする新しい方法を導入しますstatic_assert。宣言は次の形式を想定しています。
static_assert(定数式、エラーメッセージ);
static_assert使用方法の例を次に示します。
static_assert ((GREEKPI > 3.14 )&& (GREEKPI < 3.15 )、"GREEKPIは不正確です!" );
テンプレート<クラス T >構造体 チェック{{ static_assert (sizeof (int )<= sizeof (T )、"Tは十分な大きさではありません!" ); };<クラス インテグラル>積分foo (積分x 、積分y ) {{ static_assert (std :: is_integral < Integral > :: value 、”foo()パラメーターは整数型でなければなりません。” ); }
定数式がの場合、falseコンパイラはエラーメッセージを生成します。最初の例はプリプロセッサディレクティブに似てい#errorますが、プリプロセッサは整数型のみをサポートしています。対照的に、2番目の例では、テンプレートクラスのインスタンス化のたびにアサーションがチェックされますCheck。
静的アサーションは、テンプレートの外部でも役立ちます。たとえば、アルゴリズムの特定の実装は、のサイズが、long longよりも大きいことに依存する場合がありintます。これは、標準では保証されこのような仮定は、ほとんどのシステムとコンパイラで有効ですが、すべてではありません。
sizeof明示的なオブジェクトなしでクラスのメンバーで作業できるようにする
C ++ 03では、sizeof演算子は型とオブジェクトで使用できます。ただし、これを行うために使用することはできません。
struct SomeType { OtherTypeメンバー; }; sizeof (SomeType :: member ); // C ++ 03では機能しません。C ++ 11で大丈夫
これにより、のサイズが返されOtherTypeます。C ++ 03はこれを許可しないため、コンパイルエラーです。C ++ 11はそれを可能にします。alignofC ++ 11で導入された演算子でも使用できます。
オブジェクトの配置を制御および照会する
C ++ 11は、可変整合が照会とによって制御されることを可能にするalignofとalignas。
alignofオペレータは、タイプを取り、(AS型のインスタンスが割り当てられなければならない上に2バイト境界のパワーを返しますstd::size_t)。参照型alignofが指定されると、参照型の配置が返されます。配列の場合、要素タイプの配置を返します。
alignas指定子は、変数のメモリアライメントを制御します。指定子は定数または型を取ります。提供される場合、タイプalignas(T)はの省略形ですalignas(alignof(T))。たとえば、char配列を適切に配置してfloatを保持するように指定するには、次のようにします。
alignas (float )unsigned char c [ sizeof (float )]
ガベージコレクションの実装を許可する
以前のC ++標準は、を介してプログラマー主導のガベージコレクションを提供してset_new_handlerいましたが、自動ガベージコレクションを目的としたオブジェクトの到達可能性の定義はありませんでした。C ++ 11は、ポインタ値が他の値から「安全に派生」する条件を定義します。実装は、厳密なポインターの安全性の下で動作するように指定する場合がその場合、これらのルールに従って派生されていないポインターは無効になる可能性が
属性
C ++ 11は、言語のコンパイラ/ツール拡張用の標準化された構文を提供します。このような拡張機能は、従来、#pragmaディレクティブまたはベンダー固有のキーワード(__attribute__GNUや__declspecMicrosoftなど)を使用して指定されていました。新しい構文では、追加情報を二重角かっこで囲まれた属性の形式で指定できます。属性は、ソースコードのさまざまな要素に適用できます。
int [] i [[ attr2 、attr3 ]]; [[ attr4 (arg1 、arg2 )]] if (cond ) {{ [[ベンダー:: attr5 ]] return i ; }
上記の例では、属性はattr1変数の型に適用されi、attr2そしてattr3変数自体には適用され、attr4に適用されるifの文とvendor::attr5return文に適用されます。一般に(ただし、一部の例外を除いて)、名前付きエンティティに指定された属性は名前の後に配置され、エンティティの前に配置されます。それ以外の場合は、上記のように、いくつかの属性が1組の二重角括弧内にリストされ、追加の引数が提供される場合が属性の場合、属性はベンダー固有の属性名前空間によってスコープされる場合が
属性には言語の意味を持たず、無視してもプログラムの意味を変えないことをお勧めします。属性は、たとえば、コンパイラーがより適切な診断を発行したり、生成されたコードを最適化したりするのに役立つ情報を提供するのに役立ちます。
C ++ 11は、それ自体に2つの標準属性を提供noreturnします。関数が返されないことを指定することと、carries_dependency関数の引数または戻り値に依存関係があることを示すことによってマルチスレッドコードの最適化を支援することです。
C ++標準ライブラリの変更
多くの新機能がC ++ 11標準ライブラリに導入されました。これらの多くは古い標準の下で実装できた可能性がありますが、一部は(多かれ少なかれ)新しいC ++ 11コア機能に依存しています。
新しいライブラリの大部分は、2005年に発行されたドキュメントC ++標準委員会のライブラリテクニカルレポート(TR1と呼ばれる)で定義されました。現在、名前空間を使用して、TR1のさまざまな完全および部分的な実装を利用できますstd::tr1。C ++ 11の場合、それらは名前空間に移動されましたstd。ただし、TR1機能がC ++ 11標準ライブラリに組み込まれたため、初期のTR1バージョンでは使用できなかったC ++ 11言語機能で適切にアップグレードされました。また、C ++ 03で可能であったが、元のTR1仕様の一部ではなかった機能で拡張されている可能性が
標準ライブラリコンポーネントへのアップグレード
C ++ 11は、現在存在する標準ライブラリコンポーネントが恩恵を受けることができる多くの新しい言語機能を提供します。たとえば、ほとんどの標準ライブラリコンテナは、重いコンテナをすばやく移動したり、それらのコンテナの内容を新しいメモリ位置に移動したりするために、右辺値参照ベースの移動コンストラクタサポートの恩恵を受けることができます。標準ライブラリコンポーネントは、必要に応じて新しいC ++ 11言語機能でアップグレードされました。これらには以下が含まれますが、必ずしもこれらに限定されません。
値の参照と関連する移動のサポート
UTF-16エンコーディングユニット、およびUTF-32エンコーディングユニットのUnicode文字タイプのサポート
可変個引数テンプレート(完全な転送を可能にするために右辺値参照と組み合わせて)
コンパイル時定数式 decltype explicit 変換演算子
デフォルトまたは削除されたと宣言された関数
さらに、以前のC ++標準からかなりの時間が経過しました。標準ライブラリを使用した多くのコードが書かれています。これにより、いくつかの改善を使用できる標準ライブラリの一部が明らかになりました。検討された多くの改善領域の中には、標準ライブラリアロケータがありました。以前のモデルを補足するために、アロケータの新しいスコープベースのモデルがC ++ 11に含まれていました。
糸脱毛設備
C ++ 03言語はスレッド化をサポートするメモリモデルを提供しますが、実際にスレッド化を使用するための主要なサポートはC ++ 11標準ライブラリに付属しています。
スレッドクラス(std::thread)が提供されます。このクラスは、関数オブジェクト(およびそれに渡すオプションの一連の引数)を受け取り、新しいスレッドで実行します。別の実行中のスレッドが完了するまでスレッドを停止させ、std::thread::join()メンバー関数を介してスレッド結合サポートを提供することができます。可能な場合は、メンバー関数によるプラットフォーム固有の操作のために、基盤となるネイティブスレッドオブジェクトへのアクセスが提供されstd::thread::native_handle()ます。
スレッド間の同期のために、適切なミューテックス(std::mutex、std::recursive_mutexなど)と条件変数(std::condition_variableおよびstd::condition_variable_any)がライブラリに追加されます。これらは、簡単に使用できるように、Resource Acquisition Is Initialization(RAII)ロック(std::lock_guardおよびstd::unique_lock)およびロックアルゴリズムを介してアクセスできます。
高性能で低レベルの作業では、ミューテックスのオーバーヘッドなしでスレッド間の通信が必要になる場合がこれは、メモリ位置に対するアトミック操作を使用して行われます。これらは、オプションで、操作に必要な最小メモリ可視性制約を指定できます。この目的のために、明示的なメモリバリアを使用することもできます。
C ++ 11スレッドライブラリには、スレッド間で非同期結果を渡すための、およびそのような非同期結果を生成できる関数呼び出しをまとめるためのfuturesとpromiseも含まstd::packaged_taskれています。先物の提案は、先物を組み合わせて、一連の約束の中で1つの約束の完了を確認する方法がないため、批判されました。
スレッドプールなどのさらに高レベルのスレッド機能は、将来のC ++テクニカルレポートに差し戻されました。これらはC ++ 11の一部ではありませんが、最終的な実装は完全にスレッドライブラリ機能の上に構築されることが期待されています。
新しいstd::async機能は、タスクを実行し、それらをに結び付ける便利な方法を提供しますstd::future。ユーザーは、タスクを別のスレッドで非同期的に実行するか、値を待機するスレッドで同期的に実行するかを選択できます。デフォルトでは、実装は選択できます。これは、オーバーサブスクリプションなしでハードウェアの同時実行性を利用する簡単な方法を提供し、単純な使用法のためのスレッドプールの利点のいくつかを提供します。
タプルタイプ
タプルは、事前に配置された次元の異種オブジェクトで構成されるコレクションです。タプルは、構造体のメンバー変数の一般化と見なすことができます。
TR1タプルタイプのC ++ 11バージョンは、可変個引数テンプレートなどのC ++ 11機能の恩恵を受けました。合理的に実装するために、TR1バージョンには、実装で定義された最大数の含まれる型と、かなりのマクロトリックが必要でした。対照的に、C ++ 11バージョンの実装では、明示的な実装定義の最大数の型は必要ありません。コンパイラーにはテンプレートのインスタンス化のための内部最大再帰深度がありますが(これは正常です)、C ++ 11バージョンのタプルはこの値をユーザーに公開しません。
可変個引数テンプレートを使用すると、タプルクラスの宣言は次のようになります。<クラス...タイプ>クラスのタプル。
タプルタイプの定義と使用例:
typedef std :: tuple < int 、double 、long &、const char *> test_tuple ;
長い長い= 12 ; test_tupleの証明(18 、6.5 、長い、”チャオ!” ); longy = std :: get < 0 > (証明); // ‘lengthy’に値18を割り当てます。std :: get < 3 > (proof )= “Beautiful!” ; //タプルの4番目の要素を変更します。
proof内容を定義せずにタプルを作成することは可能ですが、タプル要素の型がデフォルトのコンストラクターを持っている場合に限ります。さらに、タプルを別のタプルに割り当てることができます。2つのタプルのタイプが同じである場合、各要素タイプはコピーコンストラクターを所有している必要がそれ以外の場合、右側のタプルの各要素タイプは、左側のタプルの対応する要素タイプの要素タイプに変換可能であるか、左側のタプルの対応する要素タイプに適切なコンストラクターがある必要が
typedef std :: tuple < int 、double 、string > tuple_1 t1 ; typedef std :: tuple < char 、short 、const char * > tuple_2 t2 (’X’ 、2 、”Hola!” );
t1 = t2 ; // OK、最初の2つの要素を変換できます。//3番目の要素は’const char *’から作成できます。
の場合と同様std::make_pairにstd::pair、型推論を使用しstd::make_tupleてstd::tuplesを自動的に作成し、そのようなautoタプルを宣言するのに役立ちます。std::tieタプルの解凍に役立つ左辺値参照のタプルを作成します。std::ignoreここでも役立ちます。例を参照して
auto record = std :: make_tuple (”Hari Ram” 、”New Delhi” 、3.5 、’A’ );
std ::文字列名; フロートGPA ; charグレード;
std :: tie (name 、std :: ignore 、gpa 、grade )= record ; // std :: ignoreは地名を削除するのに役立ちますstd :: cout << name << '' << gpa << '' << grade << std :: endl ;
関係演算子(同じ数の要素を持つタプル間)が使用可能であり、タプルの特性をチェックするために2つの式が使用可能です(コンパイル中のみ)。
std::tuple_size
std::tuple_element::typeIタプルのオブジェクト番号のタイプを返しますT。
ハッシュテーブル
C ++標準ライブラリにハッシュテーブル(順序付けされていない連想コンテナ)を含めることは、最も頻繁に発生する要求の1つです。時間の制約があるため、C ++ 03では採用されませんでした。ハッシュテーブルは、最悪の場合(多くの衝突が存在する場合)の平衡ツリーよりも効率が低くなりますが、多くの実際のアプリケーションでパフォーマンスが向上します。
委員会は、非常に多くの本質的な問題をもたらすオープンアドレス法のソリューションを標準化することが適切であるとは考えていなかったため、衝突は線形連鎖によってのみ管理されます(とりわけ要素の消去が認められた場合)。独自のハッシュテーブル実装を開発した非標準ライブラリとの名前の衝突を避けるために、「ハッシュ」の代わりにプレフィックス「unordered」が使用されました。
新しいライブラリには4種類のハッシュテーブルがあり、同じキー(一意のキーまたは同等のキー)を持つ要素を受け入れるかどうか、および各キーを関連する値にマップするかどうかによって区別されます。これらは、unordered_プレフィックスが付いた、4つの既存のバイナリ検索ツリーベースの連想コンテナに対応します。
ハッシュテーブルの種類
関連する値
同等のキー
std::unordered_set 番号 番号
std::unordered_multiset 番号 はい
std::unordered_map はい 番号
std::unordered_multimap はい はい
新しいクラスは、すべての要件を満たすコンテナクラスを、アクセス要素に必要なすべてのメソッドを持っています:insert、erase、begin、end。
この新機能は、任意のC ++言語のコアの拡張(実装は、さまざまなC ++ 11個の言語機能を利用しますが)、ヘッダのみの小さな延長必要はありませんでした
正規表現
新しいヘッダーで定義された新しいライブラリ
正規表現は、テンプレートクラスのインスタンスで表されますstd::regex。
オカレンスは、テンプレートクラスのインスタンスによって表されますstd::match_results。
この関数std::regex_searchは検索に使用され、「検索と置換」にはstd::regex_replace新しい文字列を返す関数が使用されます。アルゴリズムstd::regex_searchとstd::regex_replaceは正規表現と文字列を取り、構造体で見つかったオカレンスを書き込みstd::match_resultsます。
使用例を次に示しますstd::match_results。
const char * reg_esp = “[、。\ t \ n ; :]” ; //区切り文字のリスト。 //これは生の文字列リテラルを使用して実行できます:// const char * reg_esp = R “([、。 t n ;:])”;std :: regex rgx (reg_esp ); // ‘regex’は、型 ‘char’の引数を持つテンプレートクラス// ‘basic_regex’のインスタンスです。std :: cmatch match ; // ‘cmatch’はテンプレートクラスのインスタンスです// ‘match_results’型の引数 ‘const char *’。const char * target = “Unseen University-Ankh-Morpork” ;
//「reg_esp」の文字で区切られた「target」のすべての単語を識別します。if (std :: regex_search (target 、match 、rgx )) {{ //指定された文字で区切られた単語が存在する場合。 const size_t n = match 。サイズ();
for (size_t a = 0 ; a < n ; a ++ ) {{ std ::文字列strの(一致まず、一致。第二)
std :: cout << str << " n " ; }} C ++はエスケープ文字としてバックスラッシュを使用するため、ダブルバックスラッシュの使用に注意してこの問題を回避するには、C ++ 11の生の文字列機能を使用できます。
ライブラリ
汎用スマートポインター
C ++スマートポインター
C ++ 11はstd::unique_ptr、TR1std::shared_ptrとの間で、および改善を提供しますstd::weak_ptr。std::auto_ptr非推奨です。
拡張可能な乱数機能
C標準ライブラリは、関数を介して疑似乱数を生成する機能を提供しますrand。ただし、アルゴリズムは完全にライブラリベンダーに委任されています。C ++はこの機能を変更せずに継承しましたが、C ++ 11は疑似乱数を生成するための新しい方法を提供します。
C ++ 11の乱数機能は、2つの部分に分かれています。乱数ジェネレーターの状態を含み、疑似乱数を生成するジェネレーターエンジン。結果の範囲と数学的分布を決定する分布。これら2つを組み合わせて、乱数ジェネレータオブジェクトを形成します。
C標準とは異なり、C rand++ 11メカニズムには3つの基本ジェネレータエンジンアルゴリズムが付属しています。 linear_congruential_engine、 subtract_with_carry_engine、 と mersenne_twister_engine。 C ++ 11は、いくつかの標準ディストリビューションも提供します。niform_int_distribution、 uniform_real_distribution、 bernoulli_distribution、 binomial_distribution、 geometric_distribution、 negative_binomial_distribution、 poisson_distribution、 exponential_distribution、 gamma_distribution、 niform_int_distribution、0 niform_int_distribution、1 niform_int_distribution、2 niform_int_distribution、3chi_squared_distribution、 cauchy_distribution、 fisher_f_distribution、 student_t_distribution、 discrete_distribution、
piecewise_constant_distribution と piecewise_linear_distribution。 ジェネレーターとディストリビューションは、次の例のように組み合わされます。
#include <ランダム> #include <機能> std :: uniform_int_distribution <整数>分布(0 、99 ); std :: mt19937エンジン; //メルセンヌツイスターMT19937自動ジェネレーター= std :: bind (distribution 、engine );
int random = generator (); // 0と99との間に均一な積分変量生成INT random2 =分布(エンジン)。//ディストリビューションとエンジンオブジェクトを使用して、別のサンプルを直接生成します。
ラッパーリファレンス
ラッパー参照は、テンプレートクラスのインスタンスから得られますreference_wrapper。ラッパー参照は&、C ++言語の通常の参照( ‘ ‘)に似ています。任意のオブジェクトからラッパー参照を取得するにrefは、関数テンプレートを使用します(定数参照のcref場合)。
ラッパー参照は、コピーではなくパラメーターへの参照が必要な関数テンプレートで特に役立ちます。
//この関数は、パラメータ ‘r’への参照を取得し、それをインクリメントします。void func (int &r ){ r ++ ; }
//テンプレート関数。テンプレート<クラス F 、クラスP > void g (F f 、P t ){ f (t ); }
int main () {{ int i = 0 ;
g (func 、i ); // ‘g
g (func 、std :: ref (i )); // ‘g
この新しいユーティリティは既存の
関数オブジェクトのポリモーフィックラッパー
関数オブジェクトのポリモーフィックラッパーは、セマンティクスと構文の関数ポインターに似ていますが、バインドが緩く、ラッパーの引数と互換性のある引数を持つ呼び出し可能なもの(関数ポインター、メンバー関数ポインター、または関数)を無差別に参照できます。 。
例でその特性を明確にすることができます。
std :: function < int (int 、int )> func ; //テンプレートクラス ‘function’を使用したラッパーの作成//。std :: plus < int > add ; // ‘plus’は ‘template
INT A = FUNC (1 、2 )。//注:ラッパー「func」がどの関数も参照していない場合、//例外「std :: bad_function_call」がスローされます。
std :: function < bool (short 、short )> func2 ; if (!func2 ) {{ // ‘func2’にはまだ関数が割り当てられていないため、Trueです。 隣接するブール値(long x 、long y );
func2 = &隣接; // OK-パラメータとリターンタイプは変換可能です。
構造体 テスト {{
ブール演算子()(short x 、short y );
}; テストカー; func = std :: ref (car ); // ‘std :: ref’は、struct’car ‘のメンバー関数’ operator() ‘のラッパーを//返すテンプレート関数です。}
func = func2 ; // OK-パラメータとリターンタイプは変換可能です。クラスfunctionは
メタプログラミングの型特性
メタプログラミングは、別のプログラム(またはそれ自体)を作成または変更するプログラムの作成で構成されます。これは、コンパイル中または実行中に発生する可能性がC ++標準化委員会は、テンプレートを経由して、コンパイル時にメタプログラミングを可能にするライブラリーを導入することを決定しました。
C ++ 03標準を使用したメタプログラムの例を次に示します。整数指数を計算するためのテンプレートインスタンスの再帰:< int型B 、int型N > struct Pow{{ //再帰的な呼び出しと再結合。enum { value = B * Pow < B 、N -1 > :: value };
};テンプレート< int型B > struct Pow < B 、0 > {{ // ” N == 0 ”終了条件。列挙型{値= 1 };
};INT quartic_of_three =パウ< 3 、4 > ::値。
多くのアルゴリズムは、さまざまなタイプのデータを操作できます。C ++のテンプレートはジェネリックプログラミングをサポートし、コードをよりコンパクトで便利なものにします。それにもかかわらず、アルゴリズムでは、使用されているデータ型に関する情報が必要になるのが一般的です。この情報は、タイプ特性を使用してテンプレートクラスのインスタンス化中に抽出できます。
タイプ特性は、オブジェクトのカテゴリとクラス(または構造体)のすべての特性を識別できます。それらは新しいヘッダーで定義され
次の例には、指定されたデータ型に応じて、提案された2つのアルゴリズム(algorithm.do_it)のいずれかをインスタンス化するテンプレート関数「elaborate」が
//最初の操作方法。テンプレート<ブールB >ストラクトアルゴリズムを {{ テンプレート<クラス T1 、クラスT2 >静的INT do_it (T1 &、T2 &){ /*…*/ }
};// 2番目の操作方法。テンプレート<>構造体アルゴリズム< true > {{ テンプレート<クラス T1 、クラスT2 >静的INT do_it (T1 、T2 ){ /*…*/ }
};// ‘elaborate’をインスタンス化すると、正しい操作方法が自動的にインスタンス化されます。テンプレート<クラス T1 、クラスT2 > int精巧な(T1 A 、T2 B ) {{ // 2番目の方法は、「T1」が整数で、「T2」が//浮動小数点の場合にのみ使用します。それ以外の場合は、最初の方法を使用します。return Algorithm < std :: is_integral < T1 > :: value && std :: is_floating_point < T2 > :: value > :: do_it (A 、B ); } ヘッダーで定義されている型特性を介して、
このタイプのプログラミングは、エレガントで簡潔なコードを生成します。ただし、これらの手法の弱点はデバッグです。コンパイル中は不快で、プログラム実行中は非常に困難です。
関数オブジェクトの戻り型を計算するための統一された方法
コンパイル時にテンプレート関数オブジェクトの戻り型を判別することは、特に戻り値が関数のパラメーターに依存する場合、直感的ではありません。例として:
構造体 クリア{{ int演算子()(int )const ; //パラメータタイプはdouble演算子()(double )const ; //リターンタイプと同じです。};<クラスObj > クラス 微積分{{パブリック: テンプレート<クラス Arg > Arg演算子()(Arg &a )const {{ メンバーを返す(a ); }プライベート: Objメンバー; };
クラステンプレートをインスタンス化するとCalculus
構造体 混乱{{ 二重演算子()(int )const ; //パラメータタイプはint演算子ではありません()(double )const ; //リターンタイプと同じです。};
インスタンス化しようとするCalculus
TR1は、std::result_ofすべての宣言に対して関数オブジェクトの戻り型を決定して使用できるようにするテンプレートクラスを導入し、C ++ 11で採用しています。オブジェクトCalculusVer2はオブジェクトを使用してstd::result_of、関数オブジェクトの戻り型を導出します。<クラスObj > クラス CalculusVer2{{パブリック: テンプレート<クラス Arg > typename std :: result_of < Obj (Arg )> :: type operator ()(Arg &a )const {{ メンバーを返す(a ); }プライベート: Objメンバー; };
このように、関数オブジェクトのインスタンスでCalculusVer2
のTR1バージョンからの唯一の変更点は、TR1バージョンでstd::result_ofは、実装が関数呼び出しの結果タイプを判別できないことを許可したことです。サポートのためのC ++への変更によりdecltype、C ++ 11バージョンはstd::result_ofこれらの特別なケースを必要としなくなりました。すべての場合に型を計算するには、実装が必要です。
C互換性の向上
Cとの互換性のために、C99からこれらが追加されました:
プリプロセッサ:
可変個引数マクロ、
隣接するナロー/ワイド文字列リテラルの連結、
_Pragma()–に相当し#pragmaます。
long long –少なくとも64ビット長の整数型。
__func__ –マクロが含まれている関数の名前を評価します。
ヘッダー:
cstdbool(stdbool.h)、
cstdint(stdint.h)、
cinttypes(inttypes.h)。
当初計画されていたが削除されたか含まれていない機能
別のTRに向かう:
モジュール
10進タイプ
数学の特殊関数
遅らせた:
コンセプト
より完全または必要なガベージコレクションのサポート
反射
マクロスコープ
削除または廃止された機能
シーケンスポイントという用語は削除され、1つの操作が別の操作の前にシーケンスされるか、2つの操作がシーケンスされないことを指定することで置き換えられました。
以前のキーワードの使用exportは削除されました。キーワード自体は残り、将来の使用のために予約されています。
動的例外仕様は非推奨になりました。例外をスローしない関数のコンパイル時の指定はnoexcept、最適化に役立つキーワードで使用できます。
std::auto_ptrに置き換えられたため、廃止されましたstd::unique_ptr。
関数オブジェクトの基本クラス(std::unary_function、std::binary_function)、関数へのポインターへのアダプター、メンバーへのポインターへのアダプター、およびバインダー・クラスはすべて非推奨です。
も参照してください
C11
参考文献
^ 「私達は国際標準を持っています:C ++ 0xは満場一致で承認されます」。
^ Stroustrup、Bjarne。「C ++ 11FAQ」。stroustrup.com。
^ 「C ++ 11の概要:委員会を導いた具体的な設計目標は何ですか?」。標準C ++。
^ 「BjarneStroustrup:C ++ 0xの概要」(PDF)。
^ 「ISO / IEC14882:2011」。ISO。
^ 「ワーキングドラフト、プログラミング言語C ++の標準」(PDF)。
^ 「標準」。
^ Sutter、Alexandrescu「C ++コーディング標準」#15
^ ガブリエルドスレイス; Bjarne Stroustrup
「システムプログラミング言語の一般的な定数式、Proceedings SAC ’10」(PDF)。
^ JaakkoJärvi; ビャーネ・ストロヴルプ; ダグラスグレゴール; ジェレミー・シーク
「Decltypeandauto、プログラミング言語C ++、文書番号:N1478 = 03-0061」(PDF)。
^ Roger Orr。「「自動車–必要悪?」過負荷ジャーナル#115」。
^ 「ドキュメント番号:N1968 = 06-0038-C ++のラムダ式とクロージャー」(PDF)。オープンスタンダード。
^ 「自動指定子(C ++ 11以降)-cppreference.com」。en.cppreference.com。
^ Gustedt、イェンス(2019-07-09)。「nullptr定数を導入します-v1」(PDF)。ISO JTC1 / SC22 / WG14ドキュメントレジスタ。標準化のための国際機関–open-std.org経由。
^ これにより、整数リテラルなどの数値リテラルでの数字のグループ化に提案されたアンダースコアの使用(他の言語で一般的)との競合が発生したため、 C ++ 14では代わりにアポストロフィ(上部のコンマとして)をグループ化に使用します。
Daveed Vandevoorde(2012-09-21)。「N3448:痛みのない数字の分離」(PDF)。 、 ローレンスクラウル(2012-12-19)。「N3499:数字セパレーター」。
^ ISO / IEC(2003)。ISO / IEC 14882:2003(E):プログラミング言語– C ++§3.21つの定義規則[basic.def.odr]パラ。3
^ 「デフォルトおよび削除された関数– ISO / IEC JTC1 SC22 WG21 N2210 = 07-0070 –2007-03-11」。
^ 「GNUコンパイラコレクション(GCC)の使用:LongLong」。gcc.gnu.org。
^ データ型の範囲(C ++)
^ Samuel P. Harbison III、Guy L. Steele Jr。:「C–リファレンスマニュアル」、第5版、p.251
^ Milewski、Bartosz
「破られた約束–C ++ 0x先物」。
^ 「Clang-C ++ 98、C ++ 11、およびC ++ 14ステータス」。Clang.llvm.org。2013-05-12 。
^ 「C99プリプロセッサ同期のドラフト変更の作業」。www.open-std.org。
^ 洞窟、ジョナサン
「C ++-0x言語標準の更新」。
^ サッター、ハーブ
「トリップレポート:2010年3月のISO C ++標準会議」。
外部リンク
このセクションでの外部リンクの
C ++標準委員会
C ++ 0X:標準C ++の新顔
ハーブサッターのC ++ 11に関するブログ記事
AnthonyWilliamsによるC ++ 11のブログ報道
ウォータールー大学のBjarneStroustrupによるC ++ 0xに関する講演
言語の状態:Bjarne Stroustrupへのインタビュー(2008年8月15日)
C ++ 0xコア言語機能とコンパイラでのそれらの可用性を追跡するのに役立つWikiページ
オンラインC ++ 11標準ライブラリリファレンス
オンラインC ++ 11コンパイラ
BjarneStroustrupのC ++ 11 FAQ
C ++ 11の機能の詳細:範囲ベースのforループ、auto_ptrが非推奨になる理由など。