C ++ 11に切り替える方法は?


35

私はしばらくの間C ++でプログラミングを行ってきましたが、ほとんどはC ++の低レベルの機能に集中していました。それによって、私は主にポインターと生の配列で作業することを意味します。この動作は、クラスでCとしてC ++を使用することで知られていると思います。それにもかかわらず、私は最近初めてCを試しました。C#やJavaなどの言語が、ディクショナリやリストなどの便利な標準ライブラリクラスでこれらの詳細を隠していることに驚きました。

C ++標準ライブラリにはベクター、マップ、文字列などの多くのコンテナがあり、C ++ 11はstd ::配列と範囲ループを使用することでこれに追加するだけであることを認識しています。

これらの最新の言語機能をどのように活用し、どの場面がどの瞬間に適しているかを最もよく学ぶにはどうすればよいですか?最近のC ++でのソフトウェアエンジニアリングは、ほとんど手動のメモリ管理から解放されているのですか?

最後に、新しい標準を最大限に活用するためにどのコンパイラを使用する必要がありますか?Visual Studioには優れたデバッグツールがありますが、VS2012でさえひどいC ++ 11サポートがあるようです。


2
VS2012のC ++ 11サポートを「ひどい」と呼ぶのは少し誇張されていると思いますが、それよりも確かに優れている可能性があります(初期化子リストがないと、テスト/玩具コードにとって特に面倒です)。しかし、彼らは、私たちは2013年の過程でVS2012でかなりの数のC ++のための11個の機能を望むことができると思いますので、彼らは、独立してVSの残りのコンパイラのアップデートを出荷すると発表なお
マーティンBaの

3
最初はC ++ 11を学習するためにそれを提案するのは奇妙だと思ったが、あなたがまだC-With-Classesの土地で立ち往生しているのを見ると... 10年前にKoenig / MooのAccelerated C ++を読んだ。実際には既にテンプレートメタプログラミングを行っていました(レビューのために読んだだけでした)が、それでも啓示のように感じた。(それ以来、C ++を教えるためのベースとして使用しました。)C with Classesから、この本はあなたが自由に使えるとは知らなかった全く新しい言語を示すことができます。250ページしかないため、C ++ 11固有のものにすぐに進むことができますが、IMOは価値のあるステップです。
-sbi

4
g++ -std=c++11
fredoverflow

回答:


50

まず、いくつかの経験則:

  • std::unique_ptrオーバーヘッドなしのスマートポインターとして使用します。あまり頻繁に生のポインタを気にする必要はありません。std::shared_ptrほとんどの場合、同様に不要です。所有権を共有したいという願望は、多くの場合、そもそも所有権についての思考不足に裏打ちされます。

  • std::array静的長配列およびstd::vector動的配列に使用します。

  • 特に、一般的なアルゴリズムを広範囲に使用します。

    • <algorithm>
    • <numeric>
    • <iterator>
    • <functional>
  • 読みやすい場所で使用autodecltype()ます。特に、イテレータや複雑なテンプレート型など、気にしない型のものを宣言する場合は、を使用しますauto。別の物の型に関して物を宣言したい場合、を使用しますdecltype()

  • 可能な場合は、タイプセーフにします。特定の種類の事物に不変条件を強制するアサーションがある場合、そのロジックは型に集中させることができます。そして、これは必ずしも実行時のオーバーヘッドにはなりません。また、Cスタイルキャスト((T)x)を避けて、より明示的(かつ検索可能)なC ++スタイルキャスト(例:)を優先することも言うまでもありませんstatic_cast

  • 最後に、次の3つのルールを理解します。

    • デストラクタ
    • コンストラクタをコピー
    • 代入演算子

    移動コンストラクターと移動代入演算子が追加された5つのルールになっています。また、右辺値参照全般とコピーを回避する方法を理解します。

C ++は複雑な言語であるため、C ++のすべてを最適に使用する方法を特徴付けることは困難です。しかし、優れたC ++開発のプラクティスは、C ++ 11で根本的に変更されていません。手動のメモリ管理よりもメモリ管理コンテナを優先する必要があります。スマートポインタを使用すると、効率的にこれを簡単に実行できます。

実際、現代のC ++にはほとんど手動のメモリ管理がありません。C++のメモリモデルの利点は、手動ではなく決定論的であることです。予測可能な割り当て解除により、予測可能なパフォーマンスが向上します。

コンパイラーに関しては、G ++とClangはどちらもC ++ 11機能の点で競争力があり、それらの欠陥を急速に追いついています。私はVisual Studioを使用していないので、賛成も反対もできません。

最後に、std::for_each一般的なことは避けてください。

transformaccumulate、及びerase- remove_if機能古き良きありmapfoldfilter。しかしfor_each、より一般的であるため、意味がありません。ループ以外の意図はありません。それに加えて、範囲ベースと同じ状況で使用され、forポイントフリーで使用された場合でも、構文的に重いです。考慮してください:

for (const auto i : container)
    std::cout << i << '\n';

std::for_each(container.begin(), container.end(), [](int i) {
    std::cout << i << '\n';
});

for (const auto i : container)
    frobnicate(i);

std::for_each(container.begin(), container.end(), frobnicate);

6
これらの経験則に拘束力のある原則はありますか?良い提案のリストのように思えますが、... Googleからこの質問に到着した部外者として、あなたの答えはどのように私が原則的にC ++ 11を拾い上げ、C ++の軸に巻き込まずにそれを使用するのに役立ちますか?
ロバートハーベイ

3
リストに対して+1ですが、ちょっとした注意点があります:(正しい)警告に対してstd::for_each、範囲ベースのforループがplainよりも優れた代替として期待されていたときfor
ファビオフラカッシ

@FabioFracassi:おっと。私が書いた平野と対比してstd::for_eachいないと、範囲ベース。混乱を避けるために削除しました。
ジョンパーディ

1
そうでない場合は更新しstd::for_each()ます。ラムダがある場合、従来のforループよりも確かに優れています。範囲ベースのforループはそうではないかもしれませんが、「範囲ベースのforループ」を書いていません。
sbi

@sbi:私の考えでは、「forループ」という用語には「範囲ベースのforループ」が含まれます。私は、より多くの説明と例を明確にするために例を編集しました、ありがとう。
ジョンパーディ

12

出発点として:

  • char*文字列の使用を停止します。使用std::stringまたはstd::wstringちょうどあなたのコードが短くなる見て、読みやすく、そしてより安全な
  • Cスタイルの配列(で宣言されたもの[ ])の使用を停止しstd::vector、その他の適切なコンテナクラスを使用します。良い点std::vectorは、独自の長さを知っていること、スコープ外になったときに内容をクリーンアップすること、反復が容易であること、さらに項目を追加すると大きくなることです。しかし、あなたの状況によりよく機能する他のコレクションがあります。
  • 使用std::unique_ptr-とstd::moveほぼすぐに学びます。これは、いくつかのコピー不可のオブジェクトになることがありますので、怠惰は時折あなたに向けて送信することstd::shared_ptr-あなたは、いくつかのための本物のユースケースがありstd::shared_ptr、同様に
  • auto以前の宣言に依存するイテレータおよび型を宣言するときに使用します(たとえば、以前に何かのベクトルを宣言したのに、今は何かを宣言しているので、使用しますauto
  • アルゴリズムを使用for_eachし、可能な限り「raw for」を使用してください。他の人がループを注意深く読んでからコレクション全体を実際に反復していると結論付けることができますfor_each。以下のような些細なアルゴリズムの呼び出しを学びiotagenerateaccumulatefind_ifなどを。
  • ラムダを使用します-アルゴリズムを活用する簡単な方法です。彼らはまた、はるかに多くへの扉を開きます。

どのコンパイラーを使用するかについて、あまり詳しくなりすぎないでください。VS2012でのC ++ 11のサポートの「ひどい、ひどい」欠如は、可変個のテンプレートがないことです(そうですね、ちょうどあなたは可変個のテンプレートを使用うとしていた)、{}初期化子が存在しないことです。私もそれが欲しいのですが、その上で有用な開発ツールを使うのをやめるつもりはほとんどありません。

2番目に行うことは、を受け入れた後std::、RAIIについて考え始めることです。いつでも

  • 開始アクション
  • アクションを開始して得たものを含む一連のアクション
  • 例外の場合でも発生する必要があるクリーンアップアクション

次に、コンストラクタ、多数のメンバー関数、およびデストラクタがあります。あなたのためにそれを大事にするクラスを書いてください。あなたは俳優とdtorを書く必要さえないかもしれません。をshared_ptrクラスのメンバー変数として設定することはRAIIの例です。メモリ管理コードを記述しませんが、インスタンスがスコープから外れると、正しいことが起こります。その考え方を拡張して、ファイルを閉じる、ハンドル、ロックなど、コードを解放するなどのことを、目の前で単純に(リークを排除しながら)小さくしていきます。

あなたが本当に自信を持っているならprintf、賛成してパージしcout、マクロ(#defineもの)を取り除き、PIMPLのような「高度なイディオム」を学び始めてください。私が持っているこの上のコース全体は、おそらく彼らの無料試用版を使用して見ることができますPluralsightのを。


2
すぐに可変長テンプレートを使用しないという彼の皮肉が好きですが、均一な初期化の欠落は、日常のプログラミングにとって本当に重要なものを見逃していると思います。
sbi

我々はそれらを買ってあげる時に見つけるために待っている...リスト初期化子を待つことができない...
ケイトグレゴリー

VS2012のもう1つの重要な欠如は、「右辺値参照v3」、つまり、自動生成された移動コンストラクターと移動割り当てです。
Mr.C64

3

これらの最新の言語機能をどのように活用し、どの場面がどの瞬間に適しているかを最もよく学ぶにはどうすればよいですか?

プログラミングによって。経験は学ぶための最良の方法です。

C ++ 11には多くの新機能(自動、右辺値、新しいスマートポインター-ほんの数例を挙げると)があります。最良の出発点は、それらの使用を開始し、可能な限り、また興味深い記事を見つけたときにはいつでもそれらについて読むことです。

最近のC ++でのソフトウェアエンジニアリングは、ほとんど手動のメモリ管理から解放されているのですか?

それはあなたが何をする必要があるかによります。ほとんどのアプリケーションは、スマートポインターで逃げることができ、メモリ管理を忘れることがあります。それほど簡単に逃げられないアプリケーションがまだあります(たとえば、新しい配置や、何らかの理由でカスタムメモリアロケータが必要な場合)。

Qtを使用する必要がある場合は、メモリ管理にそれらのルールを使用する必要があります。

新しいコンパイラを最大限に活用するにはどのコンパイラを使用すればよいですか?

最新の標準をサポートしているものは何でも:

ただし、すべての機能をサポートするコンパイラはありません。


-7

私の大学はまだ教育にC ++を使用しています。私は5年間C ++でプログラミングをしてきましたが、現在は大学院生です。もちろん、今では多くのJava、Rubyなどを使用しています。Javaなどの言語のこれらの機能についてあまり急いでいないことをお勧めします。私の経験と意見では、C ++の低レベル機能の後。テンプレートクラス、テンプレート関数、演算子の上書き、仮想メソッド、スマートポインターの作成など、C / C ++を使用した汎用プログラミングなどのトピックを検討する必要があります。オブジェクト指向設計パートには、多重継承のように、C ++にはあるがJavaにはない多くの機能があります。継承は強力ですが危険です。C ++でのオブジェクト指向設計の実装レベルも良いトピックです。プロセス間通信、スレッド化は、C ++でも重要です。

コンパイラおよびデバッガ用。私はビジュアルスタジオが素晴らしいことを知っています。しかし、GDB、Valgrind、Make Stillを学び、これらのツールに精通することをお勧めします。マイクロソフトは素晴らしいですが、あなたにとってあまりにも多くのことをしました。学生として、あなたもマイクロソフトがあなたにしたことを本当に学ぶ必要があります。コンパイラーにとっては、G ++はGNUから優れています。

結局のところ、私は本当に何年も経て、最も重要なことは生の配列のような低レベルの機能だと感じています。ベクトルは実際には単なる動的配列です。これらは私の推奨事項であり、主観的すぎる可能性があります。あなたが正しいと思うものを選んでください。


6
これは質問にどのように答えますか?問題は、C ++全般を学ぶことではなく、C ++ 11に切り替えることです。
ロックマルティ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.