web-dev-qa-db-ja.com

どのC ++イディオムがC ++ 11で非推奨になりましたか?

新しい標準では、物事を行うための新しい方法があり、多くは古い方法よりも優れていますが、古い方法でも問題ありません。また、下位互換性の理由から、新しい標準が公式にそれほど非推奨になっていないことも明らかです。残る質問は次のとおりです。

C++ 11スタイルよりも明らかに劣っている古いコーディング方法は何ですか?代わりに何ができるでしょうか?

これに答える際に、「自動変数を使用する」などの明白なことをスキップできます。

189
Alan Baljeu
  1. 最終クラス :C++ 11は、クラス派生を防ぐためにfinal指定子を提供します
  2. C++ 11ラムダは、名前付き関数オブジェクト(ファンクター)クラスの必要性を大幅に減らします。
  3. Move Constructor :右辺値参照のファーストクラスのサポートにより、_std::auto_ptr_が機能する魔法の方法は不要になりました。
  4. Safe bool :これは以前に言及されました。 C++ 11の明示的な演算子は、この非常に一般的なC++ 03イディオムを不要にします。
  5. Shrink-to-fit :多くのC++ 11 STLコンテナは、shrink_to_fit()メンバー関数を提供します。これにより、一時的なものと交換する必要がなくなります。
  6. Temporary Base Class :古いC++ライブラリの中には、このかなり複雑なイディオムを使用するものがあります。移動セマンティクスを使用すると、もう必要ありません。
  7. Type Safe Enum 列挙はC++ 11では非常に安全です。
  8. ヒープの割り当てを禁止する :_= delete_構文は、特定の機能が明示的に拒否されていることを示すより直接的な方法です。これは、ヒープ割り当ての防止(つまり、メンバー_=delete_の_operator new_)、コピー、割り当てなどの防止に適用できます。
  9. テンプレート化されたtypedefエイリアステンプレート C++ 11では、単純なテンプレート化されたtypedefの必要性を減らします。ただし、複合型ジェネレーターにはメタ関数が必要です。
  10. 一般化された定数式 を使用して、フィボナッチなどのいくつかのコンパイル時の数値計算を簡単に置き換えることができます。
  11. _result_of_ :クラステンプレート_result_of_の使用は、decltypeに置き換える必要があります。 _result_of_が利用可能であればdecltypeを使用すると思います。
  12. クラス内メンバー初期化子 デフォルト値で非静的メンバーのデフォルト初期化のための入力を保存します。
  13. 新しいC++ 11コードでは、NULLnullptrとして再定義する必要がありますが、 STLの話 を参照して、それに対して決定した理由を確認してください。
  14. 式テンプレート 狂信者は、C++ 11で 末尾の戻り値の型 関数の構文を持つことを喜んでいます。これ以上30行の長い戻り値の型はありません!

私はそこでやめると思います!

171
Sumant

ある時点で、値だけでなくconstの値で返す必要があると主張されました。

const A foo();
^^^^^

これは、C++ 98/03ではほとんど無害であり、次のようないくつかのバグをキャッチした可能性もあります。

foo() = a;

ただし、C++ 11では、constによる戻りは移動のセマンティクスを禁止するため禁忌です。

A a = foo();  // foo will copy into a instead of move into it

リラックスしてコーディングしてください:

A foo();  // return by non-const value
65
Howard Hinnant

NULLを優先して_0_とnullptrを放棄できるようになり次第、そうしてください!

非汎用コードでは、_0_またはNULLの使用はそれほど重要ではありません。しかし、ジェネリックコードでNULLポインター定数を渡し始めるとすぐに、状況はすぐに変わります。 _0_をtemplate<class T> func(T)に渡すと、TはNULLポインター定数としてではなく、intとして推定されます。また、その後、ヌルポインター定数に戻すことはできません。これは、ユニバースがnullptrのみを使用した場合に単に存在しない問題の泥沼にカスケードします。

C++ 11は、_0_およびNULLをNULLポインター定数として非推奨にしません。しかし、それがあったかのようにコーディングする必要があります。

61
Howard Hinnant

セーフブールイディオムexplicit operator bool()

プライベートコピーコンストラクター(boost :: noncopyable)→X(const X&) = delete

プライベートデストラクタと仮想継承を使用した最終クラスのシミュレーションclass X final

38
kennytm

C++ 11で基本的なアルゴリズムを書くことを避けさせるものの1つは、標準ライブラリが提供するアルゴリズムと組み合わせてラムダを使用できることです。

私は現在それらを使用していますが、いまいましいループを再度書く代わりに、count_if()、for_each()、または他のアルゴリズムを使用して、やりたいことをどれだけ頻繁に伝えるかは信じられません。

完全なC++ 11標準ライブラリを備えたC++ 11コンパイラを使用したら、標準アルゴリズムを使用して自分のビルドを作成しないという言い訳はもうありません。ラムダはただそれを殺します。

どうして?

実際に(この方法でアルゴリズムを記述した後)、意味を理解するために暗号化を解除する必要のあるループを使用するよりも、簡単な言葉で構築されたものを読む方がはるかに簡単です。ただし、ラムダ引数を自動的に推測すると、構文を生のループに簡単に匹敵させることができます。

基本的に、標準アルゴリズムで作成されたアルゴリズムの読み取りは、ループの実装の詳細を隠す単語としてはるかに簡単です。

下位レベルのアルゴリズムを構築できるようになったので、上位レベルのアルゴリズムのみを考慮する必要があります。

24
Klaim

swapのカスタムバージョンを実装する必要が少なくなります。 C++ 03では、コストのかかるコピーをスローしないために、効率的な非スローswapが必要になることがよくあります。また、_std::swap_は2つのコピーを使用するため、swapをカスタマイズする必要があります。 C++では、_std::swap_はmoveを使用するため、効率的で非スローの移動コンストラクターと移動代入演算子の実装に焦点が移ります。これらの場合、多くの場合、デフォルトで十分であるため、C++ 03よりもはるかに少ない作業になります。

一般的に、どのイディオムが使用されるのかを予測するのは困難です。それらは経験を通じて作成されるためです。来年は「効果的なC++ 11」、そして必要な経験がまだないため、「C++ 11 Coding Standards」はわずか3年で期待できます。

10
Philipp

名前はわかりませんが、C++ 03コードでは、移動割り当ての欠落の代わりに次の構成を使用することがよくありました。

std::map<Big, Bigger> createBigMap(); // returns by value

void example ()
{
  std::map<Big, Bigger> map;

  // ... some code using map

  createBigMap().swap(map);  // cheap swap
}

これにより、上記のswapと組み合わされたコピー省略によるコピーが回避されました。

2
Andrzej

値渡しはもはや問題ではありません。移動セマンティクスや戻り値の最適化(コンパイラー依存)を使用すると、オーバーヘッドやコストのない(ほとんどの場合)コーディング関数がより自然になります。

1
Martin A

C++ 11標準を使用するコンパイラが次のコードに違反しないことに気づいたとき:

std::vector<std::vector<int>> a;

おそらく演算子>>を含むため、私は踊り始めました。以前のバージョンでは、やらなければなりませんでした

std::vector<std::vector<int> > a;

さらに悪いことに、これをデバッグしなければならなかった場合、これから出てくるエラーメッセージがどれほど恐ろしいものであるかを知っています。

しかし、これがあなたにとって「明白」であったかどうかはわかりません。

1
v010dya