新しい標準では、物事を行うための新しい方法があり、多くは古い方法よりも優れていますが、古い方法でも問題ありません。また、下位互換性の理由から、新しい標準が公式にそれほど非推奨になっていないことも明らかです。残る質問は次のとおりです。
C++ 11スタイルよりも明らかに劣っている古いコーディング方法は何ですか?代わりに何ができるでしょうか?
これに答える際に、「自動変数を使用する」などの明白なことをスキップできます。
final
指定子を提供しますstd::auto_ptr
_が機能する魔法の方法は不要になりました。shrink_to_fit()
メンバー関数を提供します。これにより、一時的なものと交換する必要がなくなります。= delete
_構文は、特定の機能が明示的に拒否されていることを示すより直接的な方法です。これは、ヒープ割り当ての防止(つまり、メンバー_=delete
_の_operator new
_)、コピー、割り当てなどの防止に適用できます。result_of
_ :クラステンプレート_result_of
_の使用は、decltype
に置き換える必要があります。 _result_of
_が利用可能であればdecltype
を使用すると思います。NULL
をnullptr
として再定義する必要がありますが、 STLの話 を参照して、それに対して決定した理由を確認してください。私はそこでやめると思います!
ある時点で、値だけでなく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
NULL
を優先して_0
_とnullptr
を放棄できるようになり次第、そうしてください!
非汎用コードでは、_0
_またはNULL
の使用はそれほど重要ではありません。しかし、ジェネリックコードでNULLポインター定数を渡し始めるとすぐに、状況はすぐに変わります。 _0
_をtemplate<class T> func(T)
に渡すと、T
はNULLポインター定数としてではなく、int
として推定されます。また、その後、ヌルポインター定数に戻すことはできません。これは、ユニバースがnullptr
のみを使用した場合に単に存在しない問題の泥沼にカスケードします。
C++ 11は、_0
_およびNULL
をNULLポインター定数として非推奨にしません。しかし、それがあったかのようにコーディングする必要があります。
セーフブールイディオム →explicit operator bool()
。
プライベートコピーコンストラクター(boost :: noncopyable)→X(const X&) = delete
プライベートデストラクタと仮想継承を使用した最終クラスのシミュレーション →class X final
C++ 11で基本的なアルゴリズムを書くことを避けさせるものの1つは、標準ライブラリが提供するアルゴリズムと組み合わせてラムダを使用できることです。
私は現在それらを使用していますが、いまいましいループを再度書く代わりに、count_if()、for_each()、または他のアルゴリズムを使用して、やりたいことをどれだけ頻繁に伝えるかは信じられません。
完全なC++ 11標準ライブラリを備えたC++ 11コンパイラを使用したら、標準アルゴリズムを使用して自分のビルドを作成しないという言い訳はもうありません。ラムダはただそれを殺します。
どうして?
実際に(この方法でアルゴリズムを記述した後)、意味を理解するために暗号化を解除する必要のあるループを使用するよりも、簡単な言葉で構築されたものを読む方がはるかに簡単です。ただし、ラムダ引数を自動的に推測すると、構文を生のループに簡単に匹敵させることができます。
基本的に、標準アルゴリズムで作成されたアルゴリズムの読み取りは、ループの実装の詳細を隠す単語としてはるかに簡単です。
下位レベルのアルゴリズムを構築できるようになったので、上位レベルのアルゴリズムのみを考慮する必要があります。
swap
のカスタムバージョンを実装する必要が少なくなります。 C++ 03では、コストのかかるコピーをスローしないために、効率的な非スローswap
が必要になることがよくあります。また、_std::swap
_は2つのコピーを使用するため、swap
をカスタマイズする必要があります。 C++では、_std::swap
_はmove
を使用するため、効率的で非スローの移動コンストラクターと移動代入演算子の実装に焦点が移ります。これらの場合、多くの場合、デフォルトで十分であるため、C++ 03よりもはるかに少ない作業になります。
一般的に、どのイディオムが使用されるのかを予測するのは困難です。それらは経験を通じて作成されるためです。来年は「効果的なC++ 11」、そして必要な経験がまだないため、「C++ 11 Coding Standards」はわずか3年で期待できます。
名前はわかりませんが、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
と組み合わされたコピー省略によるコピーが回避されました。
値渡しはもはや問題ではありません。移動セマンティクスや戻り値の最適化(コンパイラー依存)を使用すると、オーバーヘッドやコストのない(ほとんどの場合)コーディング関数がより自然になります。
C++ 11標準を使用するコンパイラが次のコードに違反しないことに気づいたとき:
std::vector<std::vector<int>> a;
おそらく演算子>>を含むため、私は踊り始めました。以前のバージョンでは、やらなければなりませんでした
std::vector<std::vector<int> > a;
さらに悪いことに、これをデバッグしなければならなかった場合、これから出てくるエラーメッセージがどれほど恐ろしいものであるかを知っています。
しかし、これがあなたにとって「明白」であったかどうかはわかりません。