C++11

C11(C標準リビジョン)
と混同しないでください }} C ++ 11は、プログラミング言語C ++の標準のバージョンです。これは2011年8月12日に国際標準化機構(ISO)によって承認され、C ++ 03に取って代わり、2014年8月18日にC ++ 14に取って代わられ、その後C ++ 17に置き換えられました。この名前は、仕様の発行年までに言語バージョンに名前を付けるという伝統に従いますが、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 Externテンプレート
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スタイルの配列のラッパーであると考えてstd::vector一時関数が作成された場合、または関数から返された場合は、新しいものを作成し、std::vectorすべての右辺値のデータを関数にコピーすることによってのみ保存できます。次に、一時的なメモリとそのすべてのメモリが破棄されます。(簡単にするために、この説明では戻り値の最適化を無視しています。)
++ 11 Cにおいて、ムーブコンストラクタのstd::vectorに右辺値参照かかるstd::vector新たに右辺のうち内部Cスタイルの配列へのポインタをコピーすることができstd::vector、その後、nullに右辺値内部ポインタを設定します。一時オブジェクトが再び使用されることはないため、nullポインタにアクセスしようとするコードはありません。また、ポインタがnullであるため、スコープ外になってもメモリは削除されません。したがって、操作はディープコピーの費用を省くだけでなく、安全で目に見えません。
右辺値参照は、標準ライブラリの外部で変更を加えることなく、既存のコードにパフォーマンス上の利点を提供できます。一時的なものは自動的に右辺値と見なされるため、std::vector一時的なものを返す関数の戻り値のタイプを明示的に変更しstd::vector &&て、moveコンストラクターを呼び出す必要はありません。(ただし、std::vectorがmoveコンストラクターのないC ++ 03バージョンの場合、copyコンストラクターはで呼び出されconst 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です。
コア言語のビルド時のパフォーマンスの強化
Externテンプレート
C ++ 03では、コンパイラは、完全に指定されたテンプレートが変換ユニットで検出されるたびに、テンプレートをインスタンス化する必要がテンプレートが多くの変換ユニットで同じタイプでインスタンス化される場合、これによりコンパイル時間が劇的に増加する可能性がC ++ 03ではこれを防ぐ方法がないため、C ++ 11では、externデータ宣言に類似したexternテンプレート宣言が導入されました。
C ++ 03には、コンパイラにテンプレートのインスタンス化を義務付ける次の構文が
テンプレート クラス std :: vector < MyClass > ;
C ++ 11は、次の構文を提供するようになりました。
extern テンプレート クラス std :: vector < MyClass > ;
これは、この変換ユニットでテンプレートをインスタンス化しないようにコンパイラーに指示します。
コア言語のユーザビリティの強化
これらの機能は、言語を使いやすくすることを主な目的として存在します。これらにより、型の安全性が向上し、コードの繰り返しが最小限に抑えられ、誤ったコードが発生しにくくなります。
イニシャライザリスト
C ++ 03は、Cから初期化子リスト機能を継承しました。構造体または配列には、構造体内のメンバーの定義順に、引数のリストが中括弧で囲まれて指定されます。これらの初期化子リストは再帰的であるため、構造体の配列または他の構造体を含む構造体がそれらを使用できます。
struct Object { 最初にフロート ; 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ます。これにより、コンストラクターやその他の関数が初期化子リストをパラメーターとして受け取ることができます。例えば:
class SequenceClass { public : 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{args}(他の種類の構築構文など)。
リストは一度作成するとコピーできます。これは安価で、参照によるコピーとして機能します(クラスは通常、開始/終了ポインターのペアとして実装されます)。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には、型の初期化に関して多くの問題がこれを行うにはいくつかの方法があり、交換すると異なる結果が得られる方法もたとえば、従来のコンストラクタ構文は関数宣言のように見える可能性があり、コンパイラの最も厄介な解析ルールがそれをそのように誤解しないようにするための手順を実行する必要がアグリゲートとPODタイプのみがアグリゲート初期化子で初期化できます(を使用SomeType var = {/*stuff*/};)。
C ++ 11は、任意のオブジェクトで機能する完全に均一な型の初期化を可能にする構文を提供します。イニシャライザリストの構文を拡張します。
struct BasicStruct { int x ; ダブル y ; };struct 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);)がある場合、初期化子リストがシーケンスコンストラクターの型に準拠していれば、他の形式の構築よりも優先されます。のC ++ 11バージョンにstd::vectorは、テンプレートタイプのイニシャライザリストコンストラクタがしたがって、このコード:
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 ); 自動 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 (auto & x : myvec )
この違いは、プログラマーがコンテナーをネストし始めるにつれて大きくなりますが、そのような場合typedefは、コードの量を減らすための良い方法です。
で示されるタイプは、でdecltype推定されるタイプとは異なる場合がありますauto。
#include int main (){ const std :: vector < int > v (1 ); 自動 a = v ;
// aの型は intdecltype (v ) b = 1 ; // bの型は
constint &で、戻り値の型は// std :: vector :: operator [](size_type)const auto c = 0 ;
// C持つ型int型の 自動 D = C ;
// dの型は intdecltype (c ) e ;
// eの型はintで、c decltype ((c )) f = c ;で 指定されたエンティティの型です。//(c)は左辺値 decltype (0 ) gであるため、fの型はint&です。
// 0は右辺値であるため、gの型はintです}
範囲ベースのforループ
C ++ 11は、forステートメントの構文を拡張して、要素の範囲で簡単に反復できるようにします。
INTの my_arrayで = { 1 、 2 、 3 、 4 、 5 }。// my_arrayの各要素の値を2倍にします:for (int & x : my_array ) x * = 2 ;//似ていますが、配列要素の型推論も使用していますfor (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の adding_func (CONST LHS &LHS 、 CONST RHS &RHS ) {戻り LHS + RHS ;} //のRetはLHS + RHSの型でなければなりません
タイプRetは、タイプLhsを追加したものであり、Rhs生成されます。前述ののC ++ 11機能を使用してもdecltype、これは不可能です。<クラス LHS 、 クラス RHS > decltype (LHS + RHS ) adding_func (CONST LHS &LHS 、 CONST RHS &RHS ) {戻り LHS + RHS ;} //ていない有効なC ++ 11
lhsとrhsはまだ定義されていないため、これは有効なC ++ではありません。パーサーが関数プロトタイプの残りの部分を解析するまで、これらは有効な識別子にはなりません。
これを回避するために、C ++ 11では、末尾に戻り値の型を使用した新しい関数宣言構文が導入されました。<クラス 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 { return x + y ; }
この場合のキーワード「auto」の使用は構文の一部にすぎず、自動型推定は実行されません。
オブジェクト構造の改善
C ++ 03では、クラスのコンストラクターは、そのクラスの初期化子リスト内の他のコンストラクターを呼び出すことはできません。各コンストラクターは、次のように、すべてのクラスメンバー自体を構築するか、共通のメンバー関数を呼び出す必要が
class SomeType { public : SomeType (int new_number ) {
構成(new_number ); } SomeType () {
構成(42 ); }private : void Construct (int new_number ) {
number = new_number ; } int 番号; };
基本クラスのコンストラクターは、派生クラスに直接公開することはできません。基本クラスのコンストラクターが適切な場合でも、各派生クラスはコンストラクターを実装する必要がクラスの非定数データメンバーは、それらのメンバーの宣言のサイトで初期化できません。それらはコンストラクターでのみ初期化できます。
C ++ 11は、これらすべての問題の解決策を提供します。
C ++ 11では、コンストラクターが他のピアコンストラクター(委任と呼ばれる)を呼び出すことができます。これにより、コンストラクターは、最小限の追加コードで別のコンストラクターの動作を利用できます。委任は、JavaやObjective-Cなどの他の言語で使用されています。
この構文は次のとおりです。
クラス SomeType { int 番号;public : SomeType (int new_number ) : number (new_number ) {} SomeType () : SomeType (42 ) {} };
この場合、new_numberデフォルトのパラメータを作成することで同じ効果が得られる可能性があることに注意してただし、新しい構文では、インターフェイスではなく実装でデフォルト値(42)を表現できます。コンストラクターの委任では、関数パラメーターのデフォルト値がサイトを呼び出すために「ベイクイン」されるため、ライブラリコードのメンテナーにとってメリットがライブラリを使用してコードを再コンパイルせずに変更される値。
これは、警告が付属しています:C ++ 03には、そのコンストラクタが終了すると実行時に構築されるオブジェクトと見なしますが、C ++ 11には、一度構築されたオブジェクトと考える任意のコンストラクタの終了の実行を。複数のコンストラクターの実行が許可されるため、これは、各委任コンストラクターが独自のタイプの完全に構築されたオブジェクトで実行されることを意味します。派生クラスコンストラクターは、基本クラスのすべての委任が完了した後に実行されます。
基本クラスコンストラクターの場合、C ++ 11では、基本クラスコンストラクターを継承するようにクラスで指定できます。したがって、C ++ 11コンパイラは、派生クラスの継承と基本クラスへの転送を実行するコードを生成します。これはオールオアナッシング機能です。その基本クラスのコンストラクターがすべて転送されるか、転送されないかのどちらかです。また、継承されたコンストラクターは、派生クラスのコンストラクターの署名と一致する場合にシャドウされ、複数の継承には制限がクラスコンストラクターは、同じ署名を持つコンストラクターを使用する2つのクラスから継承できません。
構文は次のとおりです。
class BaseClass { public : BaseClass (int value ); };class DerivedClass : public BaseClass { public : using BaseClass :: BaseClass ; };
メンバーの初期化の場合、C ++ 11では次の構文が許可されます。
class SomeClass { public : SomeClass () {} 明示的な SomeClass (int new_value ) : value (new_value ) {}プライベート: int 値 = 5 ; };
クラスvalueのコンストラクターは、コンストラクターが独自の初期化をオーバーライドしない場合、5で初期化されます。したがって、上記の空のコンストラクターはvalueクラス定義の状態に従って初期化されますが、intを受け取るコンストラクターは、指定されたパラメーターに初期化します。
上記の割り当ての初期化の代わりに、コンストラクターまたは均一な初期化を使用することもできます。
明示的なオーバーライドと最終
C ++ 03では、基本クラス関数をオーバーライドしようとしたときに、誤って新しい仮想関数を作成する可能性が例えば:
struct Base { virtual void some_func (float ); };struct Derived : Base { virtual void some_func (int ); };
Derived::some_funcが基本クラスのバージョンを置き換えることを目的としているとします。ただし、代わりに、署名が異なるため、2番目の仮想関数が作成されます。これは、特にユーザーが基本クラスを変更しようとする場合によくある問題です。
C ++ 11は、この問題を解決するための構文を提供します。
struct Base { virtual void some_func (float ); };struct Derived : Base { virtual void some_func (int ) override ; //不正な形式-基本クラスのメソッドをオーバーライドしません};
overrideコンパイラは、この正確なシグネチャを持つ仮想関数が存在するかどうかを確認するためにベース・クラス(複数可)をチェックする特別な識別子手段。存在しない場合、コンパイラはエラーを示します。
C ++ 11には、クラスからの継承を防止したり、派生クラスのメソッドのオーバーライドを防止したりする機能も追加されています。これは、特別な識別子を使用して行われますfinal。例えば:
struct Base1 final { };struct Derived1 : Base1 { }; //クラスBase1がfinalとマークされているため、形式が正しくありません
struct Base2 { virtual void f () final ; };struct Derived2 : Base2 { void f (); //仮想関数Base2 :: fがfinalとマークされているため、形式が正しくありません};
この例では、virtual void f() final;ステートメントは新しい仮想関数を宣言しますが、派生クラスがそれをオーバーライドするのも防ぎます。また、派生クラスがその特定の関数名とパラメーターの組み合わせを使用するのを防ぐ効果も
言語キーワードでもないoverrideことに注意してくださいfinal。これらは、技術的には宣言子属性の識別子です。
これらは、特定の末尾のコンテキスト(すべての型指定子、アクセス指定子、メンバー宣言(構造体、クラス、列挙型の場合)、および宣言型指定子の後)で使用される場合にのみ、属性として特別な意味を持ちますが、各宣言子の初期化またはコード実装の前にコンマで-宣言子の個別のリスト);
宣言された型シグネチャを変更したり、スコープ内の新しい識別子を宣言またはオーバーライドしたりすることはありません。
認識および承認された宣言子属性は、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 ;
// OK。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 };
古いスタイルの列挙では、値は外側のスコープに配置されます。新しいスタイルの列挙では、それらは列挙クラス名のスコープ内に配置されます。したがって、上記の例でVal1は、は未定義ですがEnum2::Val1、定義されています。
古いスタイルの列挙が明示的なスコープを提供できるようにする移行構文と、基になる型の定義も
列挙型 Enum3 : unsigned long { Val1 = 1 、 Val2 };
この場合、列挙子名は列挙型のスコープ(Enum3::Val1)で定義されますが、下位互換性のために、それらは囲んでいるスコープにも配置されます。
前方宣言列挙型はC ++ 11でも可能です。以前は、列挙型のサイズはそのメンバーの定義に依存するため、列挙型を前方宣言できませんでした。列挙型のサイズが暗黙的または明示的に指定されている限り、前方宣言することができます。
列挙型 Enum1 ;
// C ++ 03およびC ++ 11では無効です。基になるタイプを判別できません。列挙型 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はパーサーの仕様を改善し、複数の直角括弧が妥当な場所でテンプレート引数リストを閉じるものとして解釈されるようにします。これは、「>」、「>=」、または「>>」の二項演算子を使用してパラメーター式を括弧で囲むことでオーバーライドできます。< bool テスト> クラス SomeType ; std :: vector < SomeType < 1 > 2 >> x1 ; // SomeType のstd :: vectorとして解釈され、 //その後に「2 >> x1」が続きます。これは宣言子の有効な構文ではありません。1は真です。std :: vector < SomeType < (1 > 2 )>> x1 ; // SomeType のstd :: vectorとして解釈され、 //有効なC ++ 11構文である宣言子 “x1″が続きます。(1> 2)は偽です。
明示的な変換演算子
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 、 第二に、 5 > TypedefName 。 // C ++ 03では無効
これはコンパイルされません。
C ++ 11は、次の構文でこの機能を追加します。
テンプレート < typenameに まず、 型名 第二に、 int型 サード>クラス SomeType 。テンプレート <型名 第>使用 TypedefName = SomeType < OtherType 、 第二に、 5 > 。
このusing構文は、C ++ 11の型エイリアスとしても使用できます。
typedef void (* FunctionType )(double );
// FunctionTypeを使用した 古いスタイル= void (* )(double ); //新しく導入された構文
無制限の組合
C ++ 03では、どのタイプのオブジェクトがのメンバーになることができるかについての制限がありますunion。たとえば、ユニオンには、重要なコンストラクタまたはデストラクタを定義するオブジェクトを含めることはできません。C ++ 11は、これらの制限のいくつかを解除します。
場合はunionメンバーが非自明持つ特殊なメンバ関数を、コンパイラがための同等のメンバ関数を生成しませんunion、それは手動で定義する必要が
これは、C ++ 11で許可されている結合の簡単な例です。
#include //配置に必要 ‘new’。struct Point { Point () {} Point (int x 、 int y ): x_ (x )、 y_ (y ) {}
int x_ 、 y_ ; };ユニオン U { int z ; ダブル w ; ポイント p ; // C ++ 03では無効です; C ++ 11で有効です。 U () {} // Pointメンバーのため、コンストラクター定義が必要になりました。 U (const Point & pt ) : p (pt ) {} //初期化子リストを使用してPointオブジェクトを作成します。 U & 演算子= (const Point & pt ) { new (&p ) Point (pt ); return * this ; } //配置 ‘new’を使用してPointオブジェクトを割り当てます。};
変更は現在のルールを緩和するだけなので、既存のコードを壊すことはありません。
コア言語機能の改善
これらの機能により、言語は、以前は不可能であった、非常に冗長な、または移植性のないライブラリを必要としていたことを実行できます。
可変個引数テンプレート
可変個引数テンプレート
C ++ 11では、テンプレートは可変数のテンプレートパラメータを取ることができます。これにより、タイプセーフな可変個引数関数の定義も可能になります。
新しい文字列リテラル
C ++ 03は、2種類の文字列リテラルを提供します。二重引用符で囲まれた最初の種類は、タイプが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 文字 * literal_string ){ //はOUTPUTTYPEはCONST文字*取るコンストラクタがあることを前提とし 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になります。
整数および浮動小数点の生リテラルを処理するための代替メカニズムは、可変個引数テンプレートを使用することです。< 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 () = default ; //デフォルトのコンストラクタは明示的に記述されています。 SomeType (OtherType 値); };
または、特定の機能を明示的に無効にすることもできます。たとえば、このタイプはコピーできません。
struct NonCopyable { NonCopyable () = デフォルト; NonCopyable (const NonCopyable &) = 削除; NonCopyable & operator = (const NonCopyable &) = delete ; };
= delete指定子は、特定のパラメータを持つメンバ関数を呼び出す禁止するために使用することができる任意の関数を呼び出すことを禁止するために使用することができます。例えば:
struct NoInt { void f (double i ); void f (int ) = delete ; };
呼び出そうと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 <積分> ::値、 “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 > (証明); // ‘longy’に値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ここでも役立ちます。例を参照して
自動 レコード = std :: make_tuple (”Hari Ram” 、 “New Delhi” 、 3.5 、 ‘A’ ); std ::文字列 名 ; フロート GPA ; チャー グレード ; std :: tie (name 、 std :: ignore 、 gpa 、 grade ) = record ; // std :: ignoreは、地名を削除するのに役立ちますstd :: cout << name << '' << gpa << '' << grade << std :: endl ;
関係演算子(同じ数の要素を持つタプル間)が使用可能であり、タプルの特性をチェックするために2つの式が使用可能です(コンパイル中のみ)。
std::tuple_size::valueタプル内の要素の数を返しますT、
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’はテンプレートクラスのインスタンスです
// ‘basic_regex’型の引数を持つ ‘char’。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 。サイズ(); 用 (サイズ_t = 0 ; < N ; ++ ){のstd ::文字列strの(一致まず、一致。第二)std :: cout << str << " n " ; } }
C ++はエスケープ文字として円記号を使用するため、二重円記号の使用に注意してこの問題を回避するには、C ++ 11の生の文字列機能を使用できます。
ライブラリは、既存のヘッダーの変更(必要に応じてそれらを使用しますが)もコア言語の拡張も必要としません。ではPOSIX C、正規表現も利用できますC POSIXライブラリ#1 regex.h。
汎用スマートポインター
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は、いくつかの標準ディストリビューションも提供します。
uniform_int_distribution、 uniform_real_distribution、 bernoulli_distribution、 binomial_distribution、 geometric_distribution、 negative_binomial_distribution、 poisson_distribution、 exponential_distribution、 gamma_distribution、 weibull_distribution、 extreme_value_distribution、 normal_distribution、 lognormal_distribution、 chi_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 ランダム = ジェネレーター(); // 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 ‘がインスタンス化されます
//その後、 ‘i’は変更されません。 std :: cout << i << std :: endl ; //出力-> 0 g (func 、 std :: ref (i )); // ‘g >’がインスタンス化されます
//その後 ‘i’が変更されます。 std :: cout << i << std :: endl ; //出力-> 1 }
この新しいユーティリティは既存のヘッダーに追加され、C ++言語をさらに拡張する必要はありませんでした。
関数オブジェクトのポリモーフィックラッパー
関数オブジェクトのポリモーフィックラッパーは、セマンティクスと構文の点で関数ポインターに似ていますが、バインドが緩く、ラッパーの引数と互換性のある引数を持つ呼び出し可能なもの(関数ポインター、メンバー関数ポインター、または関数)を無差別に参照できます。 。
例でその特性を明確にすることができます。
std :: function < int (int 、 int )> func ; //
テンプレートクラス ‘function’を使用した//ラッパーの作成。std :: plus < int > add ; // ‘plus’は ‘template T plus(T、T);’として宣言されます
//次に、「add」はタイプ「int add(int x、int y)」です。func = add ; // OK-パラメータと戻り値の型は同じです。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-パラメータと戻り値の型は変換可能です。 struct Test {
bool operator ()(short x 、 short y ); }; テスト カー; func = std :: ref (car ); // ‘std :: ref’は、
構造体 ‘car’のメンバー関数 ‘operator()’のラッパーを//返すテンプレート関数です。} func = func2 ; // OK-パラメータと戻り値の型は変換可能です。クラスfunctionは、C ++言語を変更することなく、ヘッダー内で定義されました。
メタプログラミングの型特性
メタプログラミングは、別のプログラム(またはそれ自体)を作成または変更するプログラムの作成で構成されます。これは、コンパイル中または実行中に発生する可能性がC ++標準化委員会は、テンプレートを経由して、コンパイル時にメタプログラミングを可能にするライブラリーを導入することを決定しました。
C ++ 03標準を使用したメタプログラムの例を次に示します。整数指数を計算するためのテンプレートインスタンスの再帰:
template < int B 、 int N > struct Pow { //再帰呼び出しと再結合。 列挙型{ 値 = B * Pow < B 、 N -1 > ::値 }; };template < int B > struct Pow < B 、 0 > { // ” N == 0 ”終了条件。 列挙型{ 値 = 1 }; }; INT quartic_of_three = パウ< 3 、 4 > ::値。
多くのアルゴリズムは、さまざまなタイプのデータを操作できます。C ++のテンプレートはジェネリックプログラミングをサポートし、コードをよりコンパクトで便利にします。それにもかかわらず、アルゴリズムでは、使用されているデータ型に関する情報が必要になるのが一般的です。この情報は、型特性を使用してテンプレートクラスのインスタンス化中に抽出できます。
タイプ特性は、オブジェクトのカテゴリとクラス(または構造体)のすべての特性を識別できます。それらは新しいヘッダーで定義されます。
次の例では、指定されたデータ型に応じて、提案された2つのアルゴリズムのいずれかをインスタンス化するテンプレート関数「elaborate」があります(algorithm.do_it)。
//最初の操作方法。テンプレート< ブール B > 構造体 アルゴリズム{ テンプレート<クラス T1 、 クラス T2 > 静的 INT do_it (T1 &、 T2 &) { /*…*/ } }。// 2番目の操作方法。テンプレート<> 構造体 アルゴリズム<真> { テンプレート<クラス T1 、 クラス T2 > 静的 INT do_it (T1 、 T2 ) { /*…*/ } }。// ‘elaborate’をインスタンス化すると、正しい操作方法が自動的にインスタンス化されます。template < class T1 、 class T2 > int elaborate (T1 A 、 T2 B ){ // ‘T1’が整数で、 ‘T2’が 浮動小数点の 場合にのみ// 2番目の方法を使用し、それ以外の場合は最初の方法を使用します。return Algorithm < std :: is_integral < T1 > :: value && std :: is_floating_point < T2 > :: value > :: do_it ( A 、 B ) ; }
ヘッダーで定義されている型特性を介して、型変換操作を作成することもできます(テンプレート内static_castでconst_castは不十分です)。
このタイプのプログラミングは、エレガントで簡潔なコードを生成します。ただし、これらの手法の弱点はデバッグです。コンパイル中は不快で、プログラム実行中は非常に困難です。
関数オブジェクトの戻り値の型を計算するための統一された方法
特に戻り値が関数のパラメーターに依存する場合、コンパイル時にテンプレート関数オブジェクトの戻り値の型を判別することは直感的ではありません。例として:
struct Clear { int operator ()(int ) const ; //パラメータタイプは double 演算子()(double ) const ; //戻り値の型と同じです。};template < class Obj > class Calculus { public : template < class Arg > Arg operator ()(Arg & a ) const {
return member (a ); } private : Obj メンバー; };
クラステンプレートをインスタンス化するとCalculus、の関数オブジェクトcalculusは常にの関数オブジェクトと同じ戻り値の型になりますClear。ただし、Confused以下のクラスを指定します。
struct Confused { double operator ()(int ) const ;
//パラメータタイプは int 演算子ではありません()(double ) const ; //戻り値の型と同じです。};
インスタンス化しようとするCalculusと、の戻り値の型Calculusがクラスの戻り値の型と同じになりませんConfused。コンパイラは、からintへの変換、doubleおよびその逆の変換に関する警告を生成する場合が
TR1は、std::result_ofすべての宣言に対して関数オブジェクトの戻り値の型を決定して使用できるようにするテンプレートクラスを導入し、C ++ 11で採用しています。オブジェクトCalculusVer2はオブジェクトを使用してstd::result_of、関数オブジェクトの戻り値の型を導出します。
template < class Obj > class CalculusVer2 { public : template < class Arg > typename std :: result_of < Obj (Arg )> :: type operator ()(Arg & a ) const {
return member (a ); } private : 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は満場一致で承認されます」。取得した12年8月2011。
^ サッター、ハーブ(2014年8月18日)、C ++ 14があります!、2014年8月18日取得
^ Stroustrup、Bjarne。「C ++ 11FAQ」。stroustrup.com。
^ 「C ++ 11の概要:委員会を導いた具体的な設計目標は何ですか?」。標準C ++。
^ 「BjarneStroustrup:C ++ 0xの概要」(PDF)。検索された30年6月2011。
^ 「ISO / IEC14882:2011」。ISO。2011年9月2日。取得した3年9月2011。
^ 「ワーキングドラフト、プログラミング言語C ++の標準」(PDF)。
^ 「スタンダード」。取得した2012年11月2日に。
^ Sutter、Alexandrescu「C ++コーディング標準」#15
^ Gabriel Dos Reis; ビャーネ・ストロヴルプ(2010年3月22日)。「システムプログラミング言語の一般的な定数式、Proceedings SAC ’10」(PDF)。
^ JaakkoJärvi; ビャーネ・ストロヴルプ; ダグラスグレゴール; ジェレミーシーク(2003年4月28日)。「Decltypeとauto、プログラミング言語C ++、ドキュメント番号:N1478 = 03-0061」(PDF)。
^ Roger Orr。「「自動車–必要悪?」過負荷ジャーナル#115」。
^ 「ドキュメント番号:N1968 = 06-0038-C ++のラムダ式とクロージャー」(PDF)。オープンスタンダード。
^ 「自動指定子(C ++ 11以降)-cppreference.com」。en.cppreference.com。
^ Gustedt、Jens(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 ++)
^ サミュエル・P・ハービソンIII、ガイ・L・スティール・ジュニア:「C-リファレンスマニュアル」、第5版、p.251
^ Milewski、Bartosz(2009年3月3日)。「破られた約束–C ++ 0x先物」。
^ 「Clang-C ++ 98、C ++ 11、およびC ++ 14ステータス」。Clang.llvm.org。2013-05-12 。
^ 「C99プリプロセッサ同期のための作業ドラフトの変更」。www.open-std.org。
^ 洞窟、ジョナサン(2007年6月4日)。「C ++-0x言語標準の更新」。検索された5月25 2010。
^ a b サッター、ハーブ(2010年3月3日)。「トリップレポート:2010年3月のISO C ++標準会議」。取得した3月24日に2010。
外部リンク
このセクションでの外部リンクの
C ++標準委員会
C ++ 0X:標準C ++の新顔
HerbSutterによるC ++ 11のブログ報道
AnthonyWilliamsによるC ++ 11のブログ報道
ウォータールー大学のBjarneStroustrupによるC ++ 0xに関する講演
言語の状態:ビャーネ・ストロヴルプへのインタビュー(2008年8月15日)
C ++ 0xコア言語機能とコンパイラーでのそれらの可用性を追跡するのに役立つWikiページ
オンラインC ++ 11標準ライブラリリファレンス
オンラインC ++ 11コンパイラ
BjarneStroustrupのC ++ 11 FAQ
C ++ 11の機能の詳細:範囲ベースのforループ、auto_ptrが非推奨になる理由など。

投稿日:
カテゴリー: C