web-dev-qa-db-ja.com

CとC ++を知っているC ++ 11を学ぶのはなぜですか?

私はCとC++のプログラマーですが、どちらの言語にも固執せず、2つの言語を組み合わせて作成しています。場合によっては、演算子のオーバーロードやテンプレートを使用してクラスにコードを含めることもできます。優れたSTLを使用する方が明らかに良い方法です。単純なC関数ポインタを使用すると、はるかに読みやすく、明確になる場合があります。だから私は両方の言語で美しさと実用性を見つけます。 「それらを混合してC++コンパイラでコンパイルすると、もはや混合ではなく、すべてC++である」という議論には入りたくありません。 また、CとC++について話したくありません。この質問はすべてC++ 11についてです。

C++ 11は、C++の動作に対する重要な変更であると私が考えるものを紹介しますが、さまざまな状況でさまざまな機能がどのように動作するかを変える多くの特別なケース、例外、および不規則性を導入し、多重継承に制限を課し、キーワードとして機能する識別子、拡張文字列リテラル、ラムダ関数変数のキャプチャなど.

将来のある時点で、C++と言ったとき、誰もがC++ 11を想定することは知っています。最近のCと同じように、おそらくC99を意味します。そのため、C++ 11の学習を検討します。結局、C++でコードを書き続けたい場合、同僚が持っているという理由だけで、いつかこれらの機能を使い始める必要があるかもしれません。

Cを例にとります。何年も経った今でも、多くの人々がCでコードを学び、作成しています。なぜですか?言語が良いからです。良いことは、良いプログラミング言語を作成するための多くのルールに従うことです。したがって、Cは強力である(簡単であるか難しいかを問わず、ほとんどすべてのプログラミング言語がそうです)ことに加えて、Cは定期的であり、例外があっても例外はほとんどありません。しかし、C++ 11はそうは思いません。 C++ 11で導入された変更によって言語が改善されているかどうかはわかりません。

だから問題は:なぜ私はC++ 11を学ぶのですか?

28
anon

将来、就職するためにそれを知る必要があると思うなら、それを学ぶべきです。 C/C++ [そして他に知っていることなら何でも]として労働力の市場性を維持できると確信しているなら、それを学ばないでください。上司からC++ 11の使用を指示された場合は、「いいえ、私はしません」と言います。もし彼があなたを解雇したなら、どこか別の場所で仕事に行きなさい。現在知っているスキルではすぐに満足できる就職先を見つけることができなくなることが予測される場合は、C++ 11を学んでください。

私の理論的根拠を明確にしたかった:私はアンチC++ 11ではない。 OPの質問を「なぜXを学ぶべきなのか」に一般化できるとだけ言ってください。 CとC++の仕事をしているので、ML、スキーム、ハスケルを学んだことはありません。これらの言語は誰かにとって有用だと思いますが、私が今学ぶことは有益ではありません。誰かがMLでプログラミングするためにかなりのお金を提供してくれたなら、私はそれを学ぼうとするかもしれません。

24
Timmah

それは簡単です。 C++ 11を使用すると、コードが劇的に簡単になり、簡潔に記述でき、高速になります。

nullptrは、古い0をVASTで改善したものです。 0とは異なり、タイプセーフであり、変換すべきでないときに変換されません。これは、nullptrintに変換しないgoodのことです。それが起こるのは全く意味がありません。 C++委員会が#define NULL nullptrを検討しようとしたときに見つけたものを知っていますか? char c = NULL;のようなもの。それはどれほどひどいですか?ここに例外がある唯一の理由は、boolが整数型と見なされているためです。これはかなり間違っていますが、それは以前のC++とCにはありました。nullptrは、変換はgood、それはgreatであり、あなたはそれを気に入るはずです。

または、右辺値参照と可変個のテンプレートはどうですか?より速く、より一般的なコード。それはそこに完全な勝利です。

ライブラリの改善はどうですか? functionunique_ptrshared_ptrのようなものは以前のものよりもはるかに優れており、C++ 03の方が優れていると主張することは不可能です。

#define adding_func(x, y) ((x)+(y))

遠隔的に同等ではありません。マクロは60億の理由で悪いです。ここではそれらすべてを引用するつもりはありませんが、マクロは回避することができるほとんどすべての目的で回避する必要があることはよく知られています。いつになるの?

#define add_twice(x) (x + x)

ああ、あなたがxで何かを増やしていなかったといいのですが。テンプレート関数バージョンは完全に影響を受けません。また、たとえばnamespacesを評価しないようにお願いします。

次に、スコープが既に終了している外部変数を使用するための未定義の動作の世界に自分を開きます。

機能APIでは、 STLアルゴリズムの場合、参照は問題ありません。ストアドコールバックの場合は、値でキャプチャする必要があります。関数に関するどのようなドキュメントでも、どちらが必要かを明確に示す必要があります。コードがラムダで記述されているという事実は、ローカル変数を参照する問題とは無関係です。通常の関数オブジェクトを渡すと、まったく同じ問題が発生します。そして、それは問題ではありません。全然。ローカル変数を参照できるときとできないときは本質的に明白だからです。

Cを例にとります。何年も経った今でも、多くの人々がCでコードを学び、作成しています。なぜですか?

朝は歯磨きをしない人が多い。多くの殺人者、強姦者、売春婦がいます。そして政治家。自殺する人。それがこれらの活動を良いものにするか、または役立つと主張しますか?もちろん違います。誰かがそれをしたからといって、それは論理的誤りであり、それゆえ、それは良いか有用であるに違いない。

Cはまだ3つの理由で書かれています。C++は、たとえば組み込みモードやカーネルモードで実装するのが難しいからです。従来のコードベースはCで記述されており、アップグレードするにはコストがかかりすぎるためです。そしてそれを書いている人々はプログラムする方法を知らないので。それでおしまい。 Cを書く理由は他にありません。

Cまたは古いスタイルのC++を使用する場合、多くの例外は見つかりません。

単純な例として、哀れなCスタイルの配列はどうですか?配列やポインタをまっすぐに取得できない人の数は卑猥です。 C標準ライブラリが信じられないほど安全でないという事実は言うまでもありません。

あなたの中核的な議論は論理的な誤りと誤解に満ちています。

85
DeadMG

C++ 11は新しい言語ではありません。あなたがすでに知っているのは、C++の拡張/変更だけです。 C++ 11は、他のプログラミング言語と同様に、機能で構成されています。それらの多くは以前から存在しており、一部は新しいものです。しかし、あなたの質問は本当に、言語のすべての機能(この場合はC++ 11)を学ぶべきか、それとも90%だけに慣れるべきなのか、です。

IMOは、すべての言語を使用していない場合でも、少なくとも新機能が何をするかを読んでおく必要があります。それらの多くは、ライブラリ/フレームワークコード(特にテンプレート)を作成しやすくするために導入されました(たとえば、C++ 11の完全転送が不可能になる前)。しかし、これらの機能が必要になったことがない場合は、チャンスが得られます。これらの機能がC++ 11で追加されたことに気付かない。

一方、以前にいくつかのSTL/Boost機能を模倣するライブラリ/コアコードの作成に手を出していて、非常にクールでエレガントなソリューションを95%利用しているため、言語に制限されていることに気付いた場合言語が必要なものをサポートしていないことが判明したために停止しました。C++ 11の本当に素晴らしいパワーを実現します。私たちのチームがVS2010にアップグレードして以来(そしてその過程でBoostを発見しました)、私はいくつかのクレイジーな素晴らしいコードをクランクアウトすることができました。これは、r値の参照やテンプレートパラメーターの転送などの前には不可能でした。

また、ラムダのようなものは異質に見えるかもしれませんが、それらは新しい構成を導入しません。代わりに、これまで使用していたものを非常に簡単に作成できます。以前は、すべてのラムダ関数を個別のクラスにする必要がありました。今は{... code ...}です。大好きです。

重要なのは、これらの機能を見ないで、リストがどれほど難しいかを考えることです。代わりに、通常どおりにC++を使用し、これらの新しいC++ 11機能が役立つシナリオに遭遇した場合(90%以上の人がその時点まで到達しない)、拡張機能が非常に満足します。言語に行われました。とりあえず、その言語のすべてをどのように使用する必要があるかを知るだけでなく、その言語について十分に理解することをお勧めします。

29
DXM

関数を記述するのは難しいので、関数の内容をコードにインラインで記述し、名前を付けないようにする必要がありますか?

その場合は、上にスクロールするか、新しいソースファイルを開いて関数の定義をそこに追加します。次に、戻って作業を続けなければならず、ある程度気が散ります。

それ以外の場合、他の人があなたを読んでいるとき、ラムダは「ああ、この関数は何をするのか」と言うのではなく、場合によっては自己文書化することがあります。その宣言にジャンプすると、その場所で何が行われているかを確認できます。

ハーブ・サッターによるラムダについての素晴らしい話があります、多分彼はあなたをもっと説得できるでしょう:

http://channel9.msdn.com/events/PDC/PDC10/FT1

さて、ラムダ関数にする代わりに、そこでコードを書いてみませんか?

STLアルゴリズム、または関数を渡す必要がある使用中の関数を使用しているときは、それを行うことができないからです。

#define additional_func(x、y)((x)+(y))

ラムダの代わりにこの使用法を正当化する方法はありません。どこにでもコードをマクロで埋めることはできません。マクロと関数には異なる目的があり、一般に、一方は他方の代わりにはなりません。

template<class Lhs, class Rhs>
auto adding_func(const Lhs &lhs, const Rhs &rhs)
                -> decltype(lhs+rhs) {return lhs + rhs;}

私は同意します、これは醜いです。しかし、「コンパイラがこれを推測できるのに、なぜこの式の型を理解する必要があるのか​​」と私自身が言ったのを覚えています。多くの場合。これはそれらの瞬間に多くの助けになるでしょう。

要約すると:

C++ 11の新機能は構文上醜いように見えますが、すぐに慣れることができると思います。すべての新しい言語構成は、最初は学ぶのが難しいです。最初にクラス全体を書くことを学んだことを想像してください:最後に余分なセミコロンを忘れずにヘッダーファイルに宣言を置き、ソースファイルに定義を入れます。メンバー関数宣言などでスコープ解決演算子を忘れないように、複数の包含物...

しかし、いくつかのクラスを作成した後は、それに慣れ、このプロセスの複雑さについては気にしないと確信しています。クラスを使用すると、プログラマーとしての作業がはるかに簡単になること、そしてこの新しい構成要素から得られるユーティリティは、言語を学習しようとしたときのユーティリティの損失よりもはるかに大きいです。これが、C++ 11を同様の方法で学習または使用しようとする理由であると私は思います。

18
loudandclear

実際、OPには、ほとんどの回答として、いくつかのポイントがあります。しかし、彼らは「遠い」ビジョンを持っています。 C++(Cサブセットを含む)には長い歴史があり、多くの機能が時間の経過とともに追加されており、その一部は多かれ少なかれ頻繁に使用されており、また、誤用や間違いによって他の人や他の人に完全に使用されています。

新しい機能を導入した後、古い機能が必要になったり、矛盾したりすることがあります。 「クリーン」な言語は、そのままの形で一貫している必要があり、不要な機能を削除する必要はありません。

しかし、追加しても何も破壊されません。削除(または変更)すると、まだ本番環境にある既存のコードが破損します。そのため、追加する機能が何であれ、既存のコードを破損しないように注意する必要があります(特に、破損しないように注意してくださいsilently、意図したとおりに別のことを行う)。

あなたはそれすべてを学ぶ必要がありますか?はい、すべての機能が-良いか悪いか、遅かれ早かれ使用されている-ので。これが言語の「品質」にとって良いことであるかどうか(目的の測定があることを認める)は、別の話です。下位互換性はどのくらいの期間保持する必要がありますか?答えを見つけるのは難しい。誰かが3年と言って他の人が50年と言うとき。

C++をより「通常の」状態に保つための代替策は、スクラッチリスタートで、より頻繁にそれを壊すことです。しかし、もはやC++ではなくなります。

同様にそれを行う試みがあります(たとえば、Dを考えてみてください。実際にはC++(11でさえも)の方がはるかに直交的です)。彼らが勢いを保つのが難しい理由の1つは、まだ実行する必要のある多くの既存のコードとの非互換性です。

私にとって、C++ 11は明らかに、新しいニーズと下位互換性の間の妥協点です。その結果、その仕様と実装の特定の「乱雑さ」が生じました。その「乱雑さ」のコストが非互換性のコストよりも小さくなるまでは...その妥協点を残さなければなりません。

もう我慢できない場合は、...別の若い言語を検討することをお勧めします。その意味では、C++は単純化できません。この年齢ではありません。

8

C++ 11の新機能を無視することを決定した場合でも、C++標準ライブラリがそれらを使用するため、これらの機能を利用できます。たとえば、C++ 98では、vector<string>型の変数があると、ベクターが大きくなるときに作成する必要のあるコピーの数が多いため、パフォーマンスが低下する可能性がありました。 C++ 11 moveコンストラクターでは、問題はありません。実際、私はC++ 11が私たちに新しい機能、特に標準ライブラリの機能を提供することを望んでいます。

7

何年も経った今でも、多くの人々がCでコードを学習および記述しています。なぜでしょうか。言語が良いからです。

まず、最近のほとんどの学生はJavaまたは.NETであり、Cではありません。2番目に、Cは言語としての利点だけでなく、主にCを使用しています。 Cで記述された既存のソフトウェアの保守と拡張が必要な​​場合、および多くの場合(組み込みプラットフォームなど)にはCコンパイラがすべて存在するためです。ちなみに、これらはまだCOBOLを書く理由の一部です。

業界のプログラマーが既存のコードベースに関連付けられていない真新しいプロジェクトに取り組み始め、単独で作業を続けることは非常にまれです。したがって、C++ 11を学ぶ理由は、新しい機能を使用する他の人が作成したコードを処理しなければならない可能性が高いためです。また、理由により追加された機能が追加されました。それらを学び、それらを使用すると、それらを理解するようになるかもしれません。

6
Dima
  • アセンブリは、人々がマシンコードを書くのが好きではなかったために作成されました
  • Cは、Assemblyを書くことが好きではなかったために作成されました
  • C++は、人々がCを書くことを好まなかったために作成されました
  • C++ 11は、人々がC++を書くことを好まなかったために作成されました

あなたは自分のC++のキャリアの中で自分に言いたいところに来るでしょう"ファンクタがもっとシンプルであることを願っています"または"なぜNULLが整数なのか?"そして、あなたはC++ 11を理解するでしょう。

5
Pubby

追加された機能により優れたコードを作成できるため、C++ 11を学ぶ必要があります。一部の人々は、NULLポインタとラムダの型安全性について言及しましたが、これは非常に優れています。しかし、特に大規模な実稼働環境でのC++ 11の最も劇的な変更であると思うことに注意を向けたいと思います。

C++ 11は、「移動」と「コピー」の別々の概念をサポートしています。通常のC++では、基本的にこれらの両方を行う=演算子があります。しかし、実際には、1つの演算子で2つの別々のアイデアを表現しているので、危険です。

これが便利な最もわかりやすい例は、新しいunique_ptrです。古いauto_ptrおよびscoped_ptrのすべての最高の機能を備えています。オブジェクトを指す唯一のポインターであることが保証されているポインターが必要だとします。 a = bをどのように処理しますか?まあ、以前は行き詰まっていたので、(scoped_ptrとして)完全に拒否するか、a = bがbから所有権を盗む場所でauto_ptrが行うことを実行できます。 auto = ptrのこの動作は、a = bが実際にbを変更するため、非常に混乱します。 unique_ptrがこれを処理します。a= bは許可されていませんが、所有権を盗むためにa = std :: move(b)があります。これはどのように役立ちますか?コピーのセマンティクスではなく移動のセマンティクスを使用するスワップの別の(オーバーロードされた)バージョンがあります。つまり、unique_ptrは問題なく交換できます。つまり、auto_ptrとは異なり、unique_ptrはコンテナーで安全に使用でき、sortと言えます。 unique_ptrは基本的に、同じオブジェクトで複数のポインタが必要ない場合の安全なメモリ管理のすべてであり、すべてです。

別の素晴らしい例:コピーできないオブジェクトがあるとします。これは多くの状況で役立ちます。関数が終了すると、返されているものはすべてコピーされるため、関数からこのオブジェクトを返すことはできません。皮肉なことに、通常、コンパイラはこれを実際に最適化します(つまり、実際には最後に何もコピーされず、戻り値は最終的な割り当てのアドレスに作成されます)。ただし、これをコピー不可にした理由とは関係ありません。関数からの戻りは、オブジェクトを関数スコープの内側から外側に移動するだけです。これで、コピーはできなくても移動可能なオブジェクトを記述でき、これらのオブジェクトは関数から返すことができます。

移動セマンティクスにより、リークせず、スレッドセーフなコードを簡単に記述できます。

4
Nir Friedman

学習は常に有益です。知識は力である。

それが基本的に答えです。それ以外のすべては、それからどのように正確に利益を得ることができるか、そしてそれを知ることによってどのような力を持つかに関する詳細であり、それらは非常に多く、列挙は不完全です。

一例はあなた自身の質問です。少なくとも少しは学ばなければ、それを尋ねることさえできないでしょう。

そして私がコメントしたように-本当の関心事はなぜ学ぶべきかではなく、なぜseなのかです。それはまったく別の問題です。

4
littleadv