「C++の変更点」の版間の差分

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
ナビゲーションに移動 検索に移動
(ページの作成:「== 概要 == ここでは、C++11以降の変更点を記載する。<br> <br><br> == C++11の変更点 == <br><br> == C++14の変更点 == C++14とは、C++11のマ…」)
 
34行目: 34行目:
  </source>
  </source>
<br>
<br>
C言語とは、sizeofで値が取得できない等、細かい部分で互換性がない。
C言語とは、sizeofで値が取得できない等、細かい部分で互換性がない。<br>
また、クラス内で使用できない場合がある。
また、クラス内で使用できない場合がある。<br>
構造体内の動的配列は、Variable Length Array In Structure(VLAIS)と呼ばれる。
構造体内の動的配列は、Variable Length Array In Structure(VLAIS)と呼ばれる。<br>
C++14の実行時サイズ配列は、VLAISをサポートしない。
C++14の実行時サイズ配列は、VLAISをサポートしない。<br>
  <source lang="c++">
  <source lang="c++">
  void f(std::size_t size)
  void f(std::size_t size)
48行目: 48行目:
  </source>
  </source>
<br>
<br>
===== 通常の関数の戻り値型の推論 =====
===== 通常の関数の戻り値型の推論 =====
ラムダ式と同様に、通常の関数でもreturn文から戻り値の型を推論できる。<br>
ラムダ式と同様に、通常の関数でもreturn文から戻り値の型を推論できる。<br>

2020年4月11日 (土) 09:28時点における版

概要

ここでは、C++11以降の変更点を記載する。


C++11の変更点



C++14の変更点

C++14とは、C++11のマイナーバージョンアップとラムダ式などの機能追加を行われたC++である。
この機能を使用するためには、C++14に対応したコンパイラ(g++、clang++等)が必要である。

  • 2進数リテラル
  • 実行時サイズの配列
  • 通常の関数の戻り値型の推論
  • ジェネリックラムダ
  • 一般化されたラムダキャプチャ
  • constexpr関数の制限の緩和
  • 変数テンプレート
  • 軽量コンセプト


2進数リテラル

0bもしくは0Bのプレフィックスをつけて、数値の2進数リテラルを記述できる。

 int i = 0b1100;  // i = 12


実行時サイズの配列

配列のサイズ(要素数)を実行時の値で指定できるようになる。

 void f(std::size_t size)
 {
    int a[size];  // 実行時サイズの配列
 }


C言語とは、sizeofで値が取得できない等、細かい部分で互換性がない。
また、クラス内で使用できない場合がある。
構造体内の動的配列は、Variable Length Array In Structure(VLAIS)と呼ばれる。
C++14の実行時サイズ配列は、VLAISをサポートしない。

 void f(std::size_t size)
 {
    struct
    {
       int a[size]; // GCC VLAIS, C++14 ではエラーになる
    } valis;
 }


通常の関数の戻り値型の推論

ラムダ式と同様に、通常の関数でもreturn文から戻り値の型を推論できる。
return文のオペランドの式から推定される。

 auto f();               // 関数宣言では、戻り値の型は不明
 auto f(){return 123;};  // 関数f()の定義で、戻り値の型はintとなる。
 int x = f();            // x = 123


decltype(auto)

decltype(auto)は、戻り値型の推定に追加された機能である。
decltype(変数)で、変数の型と同じ型を指定できる。

 auto a = 10;                // int a = 10; と同義
 decltype(a) b;	             // int b; と同義
 std::vector<decltype<a> v;  // std::vector<int> v; と同義


ジェネリックラムダ

ラムダ式のパラメータがジェネリックにできる。

 [](const auto& a, const auto& b){return a > b;};


また、Varadic template parameter(パラメーターパック)も使用できる。

 auto f = [](auto ... args) {};
 f();
 f(0);
 f(0,1);
 f(0,1,2,3,4,5);


一般化されたラムダキャプチャ

非staticデータメンバーにおいて、コピーキャプチャできる。

 int x = 1;
 auto f = [y=x, &z=x] { ... };        // xをコピーしたy, xの参照をキャプチャしたz
 auto g = [y = x + 1] { return y; };  // 2を返す


ムーブキャプチャも同様にできる。

 std::unique_ptr<int> p(new int(3));
 auto f = [q = std::move(p)]{/* 何か処理 */;};


constexpr関数の制限の緩和
  • if, switch による条件分岐を許可
  • for, while, do-while のループの許可
  • void 戻り値型の許可
    パラメータの参照で書き換えを行う
  • 初期化をともなう変数宣言の許可
    static, thread_local は除く
  • 変数書き換えの許可
 constexpr int abs(int i)
 {
    if (i < 0)
    {
       i = -i;
    }
 
    return i;
 }


変数テンプレート

変数定義にテンプレートを使用できる。
詳細については、変数テンプレート(Variable Templates)を参照すること。

 template <class T> constexpr T pi = T(3.1415);
 
 template <class T>
 T menseki(T hankei)
 {
    return pi<T> * hankei * hankei;
 }


軽量コンセプト
  • コンセプトの軽量版
  • テンプレートの型制約機能


数値区切り

数値区切りとは、数値リテラルを単一引用符で区切る機能である。
区切りの桁は任意であり、大きな数字は、区切りを入れたほうが「人に解りやすい」というメリットがある。

 int a = 1'000;	                   // 千
 long int b = 1'000'000;           // 100万
 long long int c = 1'000'000'000;  // 10億


2進数や16進数も区切ると見やすくなる。

 uint16_t a = 0b11110000'00001111;  // 1[byte]ずつ区切る
 uint32_t b = 0xff'00'ff'ff;        // 1[byte]ずつ区切る


小数点を区切ることもできる。

 double pi = 3.14159'26535;


非推奨をマークする (deprecated)

deprecated属性は、エンティティを非推奨扱いする属性である。
「非推奨扱いの名前」が使用される場合、「警告メッセージ」を出力させることができる。

 // 非推奨の関数
 [[deprecated]] char * gets(char *str);
 
 // コメント
 [[deprecated("gets is deprecated. Use gets_s instead.")]]


例えば、「非推奨の関数」はいきなり削除はできない。
現実的な解として、「非推奨の関数」の実装を置き換えることが可能かもしれないが、必ずしも置き換え可能ではなく、完全な形の置き換えができるかは不明である。
なぜなら、実装を変更することにより、互換性の問題が発生する等、サイドエフェクトが考えられるからである。
「非推奨な関数」を利用しているかどうか気付くのは難しく、C++コンパイラで警告を出し、プログラマに解決して貰う方が良い。