C、Perl、Pythonなどの代わりにC ++を使用する理由はありますか?[閉まっている]


164

Linux(サーバー側)開発者として、C ++をどこで、なぜ使用する必要があるのか​​わかりません。

パフォーマンスに行くとき、最初と最後の選択肢はCです。

「パフォーマンス」が主要な問題でない場合は、PerlやPythonなどのプログラミング言語が適切な選択です。

この分野で私が知っているほとんどすべてのオープンソースアプリケーションは、C、Perl、Python、Bashスクリプト、AWK、さらにはPHPで書かれていますが、誰もC ++を使用していません。

GUIやWebアプリケーションのような他の分野については話していません。Linux、CLI、デーモンについてだけ話しているのです。

C ++を使用する十分な理由はありますか?


5
STLのせいでC ++だけを考えています。
dan_waterworth

46
したがって、C、perl、およびpythonを一緒に使用して実行できることは、C ++のみを使用して実行できます。そして、C ++を使用する理由を尋ねていますか?
マノジR

36
«パフォーマンスに行くとき、最初と最後の選択肢はCです。»はい、確かです:Dこれは証明されておらず、些細な間違いです。
-deadalnix

16
@deadalnix:私はそうは思わないでしょう。C ++には複雑なルールがありますが、これはオプティマイザーを裏目に出す可能性があります。これは、いくつかのことを実行できないためです。そして、目に見えないパフォーマンスキラーに足を踏み入れるのは非常に簡単です。それはかなり公理的であり、したがって真実です:Dそれでも実際には、より効果的なアルゴリズムとデータ構造を使用するため、C ++コードはより高速になることがあり、実際にはCコードを実際に最適化する人はいません。したがって、C ++を正しく実行すると、より安全で効果的なCになります。互換性の問題や100%の可用性ソフトウェアの要件がない場合は、C ++よりもC ++を選択する必要があります。
コーダー

4
投稿された回答で考慮されていない最良の理由は、OPの質問に直接関連しています。依存関係!!!!、平均的なシステムにc ++ライブラリが欠けているわけではありませんが、組み込みシステムでは利用できない可能性があります。すべてのシステムでプログラムを取得する唯一の方法は、プログラムを通常のCで作成することです。他のすべては、C ++を使用しない、またはあまり表現しない理由を議論しているだけです。C ++がより頻繁に使用されない理由に対処するものはなく、メリットに関係なく、その理由は依存関係です。OおよびLinusの有名なc ++の暴言。
JMベッカー

回答:


308

パフォーマンスに行くとき、最初と最後の選択肢はCです。

そして、それはあなたがバックアップすべき場所です。今、私はできません、すべてでは、サーバー開発のために話します。おそらく、選択肢よりもC ++を好む説得力のある理由はないでしょう。

しかし、一般的に言えば、他の言語ではなくC ++を使用する理由は実際にパフォーマンスです。その理由は、私が知っている他のすべての言語とは異なり、C ++が実行時にパフォーマンスのオーバーヘッドを持たない抽象化の手段を提供するからです。

これにより、依然として非常に高い抽象化レベルを持つ非常に効率的なコードを記述できます。

通常の抽象化、仮想関数、関数ポインター、およびPIMPLイディオムを検討してください。これらはすべて、ポインター演算によって実行時に解決される間接化に依存しています。言い換えると、パフォーマンスコストが発生します(ただし、小さい場合もあります)。

一方、C ++は、(パフォーマンス)コストを発生させない間接化メカニズム(テンプレート)を提供します。(この利点は、(場合によっては非常に)長いコンパイル時間で支払われます。)

一般的なソート関数の例を考えてみましょう。

Cでは、関数qsortは、要素が相互に関連して順序付けられるロジックを実装する関数ポインターを取ります。JavaのArrays.sort機能にはいくつかのバリエーションがあります。それらの1つは任意のオブジェクトをソートしComparator、Cの関数ポインターのように機能するオブジェクトを渡す必要がありますqsort。しかし、「ネイティブ」Java型にはさらにいくつかのオーバーロードがあります。そして、それぞれにsortメソッドの独自のコピー(恐ろしいコードの複製)があります。

Javaは、ここで一般的な二分法を示しています。コードの重複があるか、実行時のオーバーヘッドが発生します。

C ++では、sort関数qsortはCの場合とほとんど同じように機能しますが、1つだけ小さな根本的な違いがあります。関数に渡されるコンパレータはテンプレートパラメーターです。これは、呼び出しをインライン化できることを意味します。2つのオブジェクトを比較するために間接指定は必要ありません。タイトループでは(ここにあるように)これは実際に大きな違いを生む可能性があります。

驚くことではないが、C ++ sort関数はsort、基礎となるアルゴリズムが同じであってもCよりも優れています。これは、実際の比較ロジックが安価な場合に特に顕著です。

さて、私は、C ++がC(または他の言語)よりもアプリオリに効率的であるとか、アプリオリがより高い抽象化を提供すると言っていません。提供するのは、非常に高いと同時に非常に安価な抽象化であるため、多くの場合、効率的なコードと再利用可能なコードを選択する必要はありません。


16
私は今、C ++について十分に知っていて、あなたがスポットにいるかどうかを知っています。しかし、あなたがたった1票しか受け取っていないので、リラックスしてください。これがインターネットであり、下票が発生します。しかし、技術的に健全であれば素晴らしい答えです!
クリス

46
実行時にパフォーマンスのオーバーヘッドがありません-常にそうとは限りません。STLベクトルの実装を見ると、realloc()を使用する利点を持たないことがわかります(ポインター、長い話のためにできない)が、私が知っているすべての高レベル言語はrealloc( )ベクトルimplの。これは、それほど明白ではなく、すべて白黒ではないことのほんの一例です。
mojuba

19
@ Jaroslaw、@ Steve:ただし、同じ(=コードの肥大化、命令キャッシュミス)は、各データ型に適合した手で最適化されたコードにも当てはまります(JavaのさまざまなArrays.sort実装を参照)。あなただけが高い抽象化の利点を失います。これはテンプレートの特定の欠点ではなく、一般的なコードの重複の欠点です。さらに、タイトループでは、通常、ロードされるコードは常に同じであるため、これは重要ではありません。
コンラッドルドルフ

18
@Jaroslaw:命令キャッシュの面白い点は、それがキャッシュであることです。つまり、すべてを保存しようとするのではなく、最近使用したコードのみを保存します。テンプレートは、異なるタイプ(vector.push_backfor vector<int>、および別のfor vector<float>)に対して多くの同様のコードを生成する可能性がありますが、a vector<int>で作業している間、vector<float>コードが命令キャッシュにある理由はほとんどありません。個々のテンプレートのインスタンスは、高度に最適化され、通常は、より汎用的なキャッチすべての実装よりもコンパクト
jalf

29
@ Steve314:「肥大化」と呼ぶものは、CおよびJavaで手動で行われることです。C ++では、自動化が可能であり、コンパイラは、肥大化を回避するためにベンダーが敢えて作成するのと同じくらいスマートになります。遅い(Cのように)か、重複したコード(Javaのように)を使用するかを決定する必要がある場合、コンパイラーに複製を行わせる(そしておそらくそれについて賢くする)ことはかなり良いように思えますか?
sbi

166

C ++が嫌いなCプログラマが多すぎると思います。何が良いのか、何が悪いのかをゆっくりと理解するのにかなりの時間(年)かかりました。それを表現する最良の方法はこれだと思います:

コードの削減、ランタイムのオーバーヘッドなし、安全性の向上。

記述するコードが少なければ少ないほど良いです。これは、卓越性を追求するすべてのエンジニアですぐに明らかになります。バグを1か所ではなく、1か所で修正します。一度アルゴリズムを表現し、それを多くの場所で再利用します。あなたがそれについて賢明であること」。事実、C ++を正しく使用すると、ランタイム速度を犠牲にすることなく、Cよりも安全に(つまり、コンパイル時に多くのエラーをキャッチして)、Cよりはるかに少ないコードで表現できます。

レンダラーの簡単な例を次に示します。三角形のスキャンラインでピクセル値を補間する場合。X座標x1から開始し、X座標x2(三角形の左側から右側)に到達する必要があります。そして、各ステップで、通過する各ピクセルで、値を補間する必要があります。

ピクセルに到達する環境光を補間すると:

  typedef struct tagPixelDataAmbient {
      int x;
      float ambientLight;
  } PixelDataAmbient;

  ...
  // inner loop
  currentPixel.ambientLight += dv;

色を補間すると(「グーロー」シェーディングと呼ばれ、「赤」、「緑」、「青」フィールドは各ピクセルのステップ値によって補間されます):

  typedef struct tagPixelDataGouraud {
      int x;
      float red;
      float green;
      float blue;  // The RGB color interpolated per pixel
  } PixelDataGouraud;

  ...
  // inner loop
  currentPixel.red += dred;
  currentPixel.green += dgreen;
  currentPixel.blue += dblue;

「Phong」シェーディングでレンダリングするとき、強度(ambientLight)または色(red / green / blue)を補間しなくなりました-通常のベクトル(nx、ny、nz)を補間し、各ステップで、 -補間された法線ベクトルに基づいて、照明方程式を計算します:

  typedef struct tagPixelDataPhong {
      int x;
      float nX;
      float nY;
      float nZ; // The normal vector interpolated per pixel
  } PixelDataPhong;

  ...
  // inner loop
  currentPixel.nX += dx;
  currentPixel.nY += dy;
  currentPixel.nZ += dz;

さて、Cプログラマーの最初の本能は「一体、値を補間する3つの関数を書き、設定モードに応じてそれらを呼び出す」でしょう。まず第一に、これはタイプの問題があることを意味します。私のピクセルはPixelDataAmbientですか?PixelDataGouraud?PixelDataPhong?ああ、待って、効率的なCプログラマーはユニオンを使うと言った!

  typedef union tagSuperPixel {
      PixelDataAmbient a;
      PixelDataGouraud g;
      PixelDataPhong   p;
  } SuperPixel;

..そして、あなたは機能を持っています...

  RasterizeTriangleScanline(
      enum mode, // { ambient, gouraud, phong }
      SuperPixel left,
      SuperPixel right)
  {
      int i,j;
      if (mode == ambient) {
          // handle pixels as ambient...
          int steps = right.a.x - left.a.x;
          float dv = (right.a.ambientLight - left.a.ambientLight)/steps;
          float currentIntensity = left.a.ambientLight;
          for (i=left.a.x; i<right.a.x; i++) {
              WorkOnPixelAmbient(i, dv);
              currentIntensity+=dv;
          }
      } else if (mode == gouraud) {
          // handle pixels as gouraud...
          int steps = right.g.x - left.g.x;
          float dred = (right.g.red - left.g.red)/steps;
          float dgreen = (right.g.green - left.a.green)/steps;
          float dblue = (right.g.blue - left.g.blue)/steps;
          float currentRed = left.g.red;
          float currentGreen = left.g.green;
          float currentBlue = left.g.blue;
          for (j=left.g.x; i<right.g.x; j++) {
              WorkOnPixelGouraud(j, currentRed, currentBlue, currentGreen);
              currentRed+=dred;
              currentGreen+=dgreen;
              currentBlue+=dblue;
          }
...

混が入り込むのを感じますか?

まず、コードをクラッシュさせるのに必要なのは1つのタイプミスだけです。これは、コンパイラが関数の「Gouraud」セクションで実際に「.a」にアクセスするのを止めないためです。(アンビエント)値。C型システムによって(つまり、コンパイル中に)キャッチされないバグは、実行時に現れるバグを意味し、デバッグが必要になります。left.a.green「dgreen」の計算でアクセスしていることに気づきましたか?コンパイラーは確かにそう言わなかった。

その後、あらゆる場所に繰り返しがあります- forループはレンダリングモードと同じ回数だけ存在し、「右から左をステップで割ったもの」を繰り返します。glyい、エラーが発生しやすい。「j」を使用すべきだったときに、グーループで「i」を使用して比較したことに気づきましたか?コンパイラーは再びサイレントです。

モードのif / else /ラダーはどうですか?3週間で新しいレンダリングモードを追加するとどうなりますか?すべてのコードのすべての「if mode ==」で新しいモードを処理することを覚えていますか?

次に、上記のさを、このC ++構造体のセットとテンプレート関数と比較します。

  struct CommonPixelData {
      int x;
  };
  struct AmbientPixelData : CommonPixelData {
      float ambientLight;
  };
  struct GouraudPixelData : CommonPixelData {
      float red;
      float green;
      float blue;  // The RGB color interpolated per pixel
  };
  struct PhongPixelData : CommonPixelData {
      float nX;
      float nY;
      float nZ; // The normal vector interpolated per pixel
  };

  template <class PixelData>
  RasterizeTriangleScanline(
      PixelData left,
      PixelData right)
  {
      PixelData interpolated = left;
      PixelData step = right;
      step -= left;
      step /= int(right.x - left.x); // divide by pixel span
      for(int i=left.x; i<right.x; i++) {
          WorkOnPixel<PixelData>(interpolated);
          interpolated += step;
      }
  }

これを見てください。ユニオンタイプスープはもう作成しません。各モードごとに特定のタイプがあります。基本クラス(CommonPixelData)から継承することにより、共通のもの(「x」フィールド)を再利用します。そして、このテンプレートにより、コンパイラーは、Cで記述した3つの異なる関数をCREATE(つまり、コード生成)しますが、同時に、型については非常に厳格です!

テンプレート内のループでは、無効なフィールドにアクセスしてアクセスすることはできません。コンパイラが実行すると、barえます。

テンプレートは一般的な作業(ループ、毎回「ステップ」で増加)を実行し、実行時エラーを発生させない方法で実行できます。タイプごとの補間は(AmbientPixelDataGouraudPixelDataPhongPixelData)で行われoperator+=()、我々は構造体に追加すること-基本的に指示する、各タイプが補間されます。

そして、WorkOnPixel <T>で行ったことがわかりますか?タイプごとに異なる作業を行いたいですか?テンプレートの専門化を単に呼び出します:

void WorkOnPixel<AmbientPixelData>(AmbientPixelData& p)
{
    // use the p.ambientLight field
}


void WorkOnPixel<GouraudPixelData>(GouraudPixelData& p)
{
    // use the p.red/green/blue fields
}

つまり、呼び出す関数は、タイプに基づいて決定されます。コンパイル時に!

言い換えると:

  1. コードを(テンプレートを介して)最小化し、共通部分を再利用し、
  2. いハックを使用せず、厳密な型システムを維持するため、コンパイラは常に私たちをチェックできます。
  3. そして何よりも:実行したことによる影響はありません。このコードは、同等のCコードと同じ速さで実行されます-実際、Cコードが関数ポインターを使用してさまざまなWorkOnPixelバージョンを呼び出す場合、コンパイラーは型固有のWorkOnPixelテンプレート特殊化をインライン化するため、C ++コードはCより高速になりますコール!

コードの削減、ランタイムのオーバーヘッドなし、安全性の向上。

これは、C ++がすべての言語であり、すべての言語であるということですか?もちろん違います。それでもトレードオフを測定する必要があります。無知な人は、Bash / Perl / Pythonスクリプトを書くべきだったときにC ++を使用します。トリガー対応のC ++初心者は、それらを停止してパッキングを送信する前に、仮想多重継承を使用して深くネストされたクラスを作成します。彼らは、これが必要ではないことに気付く前に、複雑なBoostメタプログラミングを使用します。テンプレートとの代わりにchar*strcmpとマクロをまだ使用しますstd::string

しかし、これは、あなたと一緒に仕事をしている人に注目してください。無能なユーザーからあなたを守る言語はありません(いいえ、Javaさえも)。

C ++の学習と使用を続けてください-過剰に設計しないでください。


18
「いいえ、Javaでさえない」ための+1 :)
ネイサンオスマン

53
例では+1。長い投稿でしたが、CコードとC ++コードの比較は印象的です。
パールセバル

そして、これは、紳士men女、lex / yaccが存在する理由です。同じ理由で、私はc ++の一部が同じコード生成哲学に陥ることに決して気づきませんでした。いつかもう一度見直さなければなりません。
スペンサーラスブン

2
私はたくさんの2Dレンダリングコードを書いて(10年以上前)、CからC ++への移植中にこの問題に遭遇しました:スキャンラインが1ビットピクセル(8ピクセル)でできている場合、ピクセル構造をどのように定義しますかバイト)?スキャンラインがR、G、Bバイト(ピクセルあたり3バイト)で構成されている場合 また、R、G、Bの3つの個別のバッファーがある場合 C ++が役に立たないのである、とテンプレートを使用して主張することで、空間と時間の最適化に多くの失うようになります:あなたは答えは知っている
ウォルターTross

このためにC ++でテンプレートを使用するのはなぜですか?メソッドは基本クラスのパラメーターを宣言しているので、私の[C#プログラマー]の観点からは、派生型インスタンスを基本型パラメーターに渡すことができるように見えます。C ++がわかりません。説明してください。
Vlad

79

勝利の赤ちゃんのためのRAII

真剣に、C ++の決定論的な破壊により、オーバーヘッドがまったくなく、コードがより明確で安全になります。


20
「C ++:唯一の真剣に決定的なオプション。今日、医師に相談してください。」
カイルストランド14

2
フォローアップ:Rustは現在、この分野の競争相手です。基本的なRAIIの例、Rustのデストラクタメソッドに関するドキュメントを参照してください。
カイルストランド

1
Cは確定的ですが、mallocされたメモリを使用するときに実際に発生するようにするには、より多くの作業が必要です
Baldrickk

1
Cの@Baldrickkでは、リソースを使用するすべての場所でクリーンアップコードを記述する必要があります。C ++では、リソースの定義に1回記述します。クリーンアップは自動ではないため、CとJavaの両方に「廃棄後に使用されるリソース」と「リソースをリークする」バグがあります。メモリが唯一のリソースではありません。
カレス

70

C ++を使用する納得のいく理由はありますか?

  1. テンプレートとSTL。かなりの実行時パフォーマンスヒットなしで、多くの便利な抽象化ツールと省力化ツールを使用して、少しのビルド時間(および潜在的に理解できないエラーメッセージ)を交換します(ただし、バイナリフットプリントは少し大きくなります)。

    頭を包むにはしばらく時間がかかります(クリックする前に数年かかりました)が、一度やると、人生がずっと簡単になります。

  2. C ++でのテキスト処理は、Cの場合よりも桁違いに痛みが少なくなります。


35
+1でテキスト処理を行いましたが、回答で完全に忘れていました。
コンラッドルドルフ

8
ふむ、私は、特にテキスト処理苦痛はのは、Pythonを言わせる比べた...
ニルス

7
Boostが私がまだC ++を使用している唯一の理由です。
フェルッチオ

33
@Nils:1から1のスケールで、C ++でのテキスト処理は、Pythonのような最新の言語よりも明らかに悪いです。Cでのテキスト処理が痛みを定義するだけです。その特定のアプリケーションの選択がCとC ++の間であれば、C ++が簡単に勝ちます。
ジョンボード

8
C / C ++でのテキスト処理のようなものでなぜ人々がそのような困難を抱えているのか、私は知りません。ライブラリを使用するか、独自のライブラリを作成します。低レベルの関数を作成すると(一度限りの痛み)、大規模なパフォーマンス、タイトなコード、優れた柔軟性が得られます。はい、Pythonをクイック/ダーティなコマンドラインユーティリティに使用しますが、本格的な製品コードにはC / C ++を使用します。

41

はい。

実行可能性の効率を探している場合は、CまたはC ++を使用しているので、それに焦点を当てます。

テンプレートが一般的になる前から、1990年代半ばに議論した種類の実行可能ファイルには、オブジェクトポリモーフィズムRAIIという2つの非常に単純な理由で、C ++よりもC ++を使用することを好みました。

あらゆる種類の興味深いことにポリモーフィックC ++オブジェクトを使用しました。たとえば、私はOMAPおよびXScale ARM CPUでフレームバッファーオーバーレイを使用する組み込みLinuxシステムで作業していました。2つのハードウェアアーキテクチャには、非常に異なるAPIを備えた異なるオーバーレイ機能があります。共通の仮想「オーバーレイ」基本クラスを使用して、オーバーレイの理想的なビューを公開し、「OmapOverlay」および「XScaleOverlay」クラスを作成しました。

単純化すると、RAIIは、オブジェクトのコンストラクター中、またはオブジェクトの存続期間中にオブジェクトに接続されたリソースを割り当て、オブジェクトのデストラクタでリソースの割り当てを解除または解放するという考え方です。C ++では、自動変数であるオブジェクトがスコープから外れると破壊されるため、これは本当に素晴らしいことです。CとC ++で同等の能力を持っている人にとっては、C ++でのリソースリークとメモリリークを回避する方がはるかに簡単です。また、の呼び出しの前にある関数の最後にラベルの非常に一般的なCミームがあり、そこにジャンプする関数ブロック内のfree()さまざまなgotoのC ++コードはあまりありません。

これらすべてをCで実行できることを完全に承知しています-それは、はるかに多くの作業であり、コードの行数がはるかに多く、最終的にははるかにく、理解するのが難しくなります。Xサーバーの内部にはすべてポリモーフィズムのコードがありますが、それは、くて奇妙で、トレースするのが難しい場合が多いのです。

また、GTK +やClutterなどのGNOMEテクノロジーでも多くの仕事をしています。これらはすべて、GObjectシステムを使用してCで記述されています。GObjectは、C ++オブジェクトシステムに似ており、素敵なカバーが外され、すべての見苦しい内部が公開されています。私は現在、いくつかを書いていますがClutterActors、数学は本当に面白いのですが、「これはすべてC ++ではもっと簡潔でわかりやすいものになるでしょう」と常に考えています。

「Cの代わりにC ++でこれを書いているなら、午後9時にオフィスに座っているのではなく、妻と一緒にMythBustersを見ながらリビングにいるだろう」とよく思います。


9
ここで言っていること、特に1)RAIIについてのポイント、2)「Cの代わりにC ++でこれを書いているなら...」という考えに本当に関係します。私は多くの組み込みシステム開発をしています、そしてチームが「C」または「クラスのあるC」のようなショップであるとしても、割り込み操作、ミューテックス操作、トレース/ロギング(特にI / Oの切り替えなど)についてRAIIを奨励するように心がけています。行)。そして、ポリモーフィックフレームバッファの説明から、分散システムでのポリモーフィックメッセージバッファの使用を思い出しました。
ラジアン

29

C ++はCとほぼ同じ速度(一部は高速、一部は低速)であり、より優れた抽象化と編成を提供します。クラスはプリミティブ型と同様に機能し、気にせずに大量のコードを使用できます。演算子のオーバーロードとテンプレートを使用すると、データ表現が変更された場合に機能が向上するコードを作成できます。例外により、エラー処理が容易になります。コンパイラは、コンパイル時にさらに多くのものをチェックするために使用できます。

あなたがこれに支払う代価はかなり厄介な学習曲線であり、私が精通している他のほとんどの言語よりも微妙な間違いを犯しやすいです。

ですから、あなたが今何をしているのかを学ぶことがあなたにとって価値があるかどうかはわかりません。PythonまたはPerlとCの組み合わせで確かにうまくいくことができますが、C ++は1つの使いにくいパッケージで抽象化とパフォーマンスの両方を提供します。


13
ありません何もそれが高速である場合は、常にCの方法を使用することができますので、C ++はCよりも遅くなっている場合には(そして、あなたは気に)。
ジャックエイドリー

1
@JackAidley-C ++が制限および静的配列パラメーターをサポートしていないことを除きます。また、ある場所でC ++スタイルを使用すると、他の場所で強制的に使用されることを除きます。
martinkunev

@martinkunevは、restrict最適化をエイリアシングからの除外を作るために使用されているので、どのように物事を作るのを助けるん速いですか?「静的配列パラメーター」とは何ですか?「スタイル」はパフォーマンスにどのように影響しますか?
underscore_d

1
@underscore_d restrictは、非エイリアスの保証に基づいて最適化を許可します。静的配列パラメーターにより、コンパイラーはポインター引数がNULLではなく、このポインターが少なくとも指定された数の要素を指していると想定できます。「スタイル」という言葉にはいくつかの意味があり、コンテキストから外すとその意味が変わります。たとえば、例外がスマートポインターの使用を強制する方法について話しているところです。
martinkunev

1
@martinkunevうーん、静的配列パラメーターが、T (&arr)[n]or を使用したC ++テンプレートと機能的に異なるものを有効にするのかどうかは疑問に思うstd::array<T, n>。スマートポインターについては理にかなっています。これは間違いなく良い例です。同等の条件でコーディングする場合、例外を使用しないため、潜在的なコストは発生しません...危険にさらされています。
underscore_d

27

私はC ++を1990年代の言語、過ぎ去った時代の言語だと考えています。

当時は、パフォーマンスの観点から低コストで高レベルの言語構造とメカニズムを提供していたため、大きなものでした。これは、アドレス帳アプリケーションからアビオニクスソフトウェアまですべてを開発するための普遍的なツールであり、オブジェクト指向の流行を引き起こしました。OOPは飢hungとエイズを解決しました。そして、はい、1990年代後半にオブジェクト指向以外の言語は学習する価値がないプログラミングを始めたときに洗脳しようとしたC ++を非難します。

ハードウェアが非常に進歩し、より新しい、現代の言語が登場した今、まだ抽象化が必要な計算集約的なソフトウェア(ゲーム、物理シミュレーション、CADシステムなど)を除き、ほとんどのアプリケーションプログラミングにC ++が適切な選択肢として残っているとは思えません。 )。Cでコンパクトなモジュラーエンジンを記述し、高レベルのアプリケーションロジックを適切なスクリプト言語に委任すると、後者も回避できます。

メタルに降りる必要がある場合はCを使用し、高レベルにする必要がある場合は、カプセル化をアドバタイズしない最新の言語で行いますが、ポインターを介して各バイトを自由に変更できます。


11
したがって、ポインターを使用してランダムバイトを変更しないでください。それを避けるのはそれほど難しくありませんか?
デビッドソーンリー

11
@Blagovest:C ++の複雑さについては同意しますが、C ++を使用してオブジェクト指向言語を置き換えることは決してありません。しかし、その複雑さにもかかわらず、さまざまな答え(抽象化、リソース処理、文字列処理など)で説明されている多くの利点があるため、Cに勝っています。実際には、C ++はまだ関連しているいくつかの有効な領域を命名している、そしてそれがCにはるかに優れだところ
コンラートルドルフ

6
@Blagovest:だからこそ、私は暗い隅にとどまらない。私が知っている他のどの言語よりも、C ++で簡単に強引に取得できます。それを使用することにより、私ははるかに良い文字列はC、STL型テンプレートクラス、オブジェクト指向の機能、および他の利点は、それはC.の上に持っていることを取り扱い、RAIIの恩恵を受ける
デヴィッド・ソーンリー

24
@Blagovest:いいえ、そうではありません。たとえば、RAIIを達成するには、これまで述べてきたことは不十分であり、コンテナクラスには、単純な手作りのデータ構造を超える機能があります。それが可能だと思うなら、C ++をよく学んだことはないでしょう。
デビッドソーンリー

5
@JaroslawマルチコアマシンがOOPを重大なものにする理由がわかりません。C ++を意味する場合、どこから来たのかがわかります。OOPは、多くの最新のプログラミング言語、特に高レベル言語の基本概念です。そのようにプログラムすれば、Cでもオブジェクト指向になります。C ++ IMOほど便利ではありません。
ヴェドシティ

21

Linusよると、いいえ:

Gitのソースコードを最初に見たとき、2つのことが奇妙だと思いました。1. C ++ではなく純粋なC。理由はわかりません。移植性については話さないでください、それはBSです。

あなたはでたらめでいっぱいです。

C ++は恐ろしい言語です。多くの標準以下のプログラマーがそれを使用するという事実によって、それはさらに恐ろしくなりました。率直に言って、Cの選択がもせずにC ++プログラマを排除することであっても、それ自体がCを使用する大きな理由になるでしょう。

言い換えれば、Cの選択が唯一の正気の選択です。Miles Baderが冗談めかして「腹を立てる」と言ったのは知っていますが、実際はそうです。私は、プロジェクトがCよりもC ++であることを好むプログラマーは、おそらく私が本当に腹を立てることを好むプログラマーであるという結論に達しました。 と。

C ++は本当に悪い設計選択につながります。STLやBoostなどの言語の「素敵な」ライブラリ機能の使用を常に開始します。これはプログラムを「支援」する可能性がありますが、次の原因になります。

  • 動作しないときの無限の痛み(そして、STLと特にBoostは安定していてポータブルだと言う人はだれでもBSでいっぱいで、面白くさえない)

  • 効率の悪い抽象化されたプログラミングモデルでは、2年後には抽象化があまり効率的ではないことに気づきますが、コードはすべてその周辺のすてきなオブジェクトモデルに依存しており、アプリを書き直さずに修正することはできません。

言い換えると、優れた、効率的で、システムレベルで移植性のあるC ++を実行する唯一の方法は、基本的にCで利用可能なすべてのものに制限されることになります。また、低レベルの問題を実際に理解し、ばかげた「オブジェクトモデル」がらくたで物事を台無しにしない多くのプログラマーを獲得することを意味します。

申し訳ありませんが、効率性が主な目的であったgitなどの場合、C ++の「利点」は大きな間違いです。それを見ることができない人々を怒らせているという事実は、大きな追加の利点にすぎません。

C ++で記述されたVCSが必要な場合は、Monotoneで遊んでください。本当に。彼らは「実際のデータベース」を使用します。「素敵なオブジェクト指向ライブラリ」を使用します。「素敵なC ++抽象化」を使用します。そして、率直に言って、CSの一部の人々にとって非常に魅力的であるこれらすべての設計決定の結果として、最終結果は恐ろしく、維持できない混乱です。

しかし、あなたはgitよりもそれを好むと確信しています。

      Linus

62
Linusがここで議論に行くべき人物だとは思わない。彼の暴言は恐ろしく主観的で未熟です。彼は実際にいくつかの良い点を持っていますが、それらは非常に深く埋まっているので(「でたらめ」だけでなくでたらめ)、見つけるのは非常に困難です。
コンラッドルドルフ

19
ハハ、それは大笑いでした。私はこの男に会いたくない。
Felix Dombek

30
Linusは、シートロックを掛けたことがない非常に才能のある屋根職人を思い出させますが、釘の代わりにネジを使用しているため、シートロックガイパンジーを呼び出します。
ボブマーフィー

8
Linusにはポイントがありますが、それをあまりにも厳しく表現して真剣に受け止めることはできません。
Blagovest Buyukliev

39
@Danielに同意します。ハードウェアの限界を押し広げることについて話すことができる人がいるのなら、運命、地震などのゲームの作成者であり、Idソフトウェアの創設者であるJohn Carmackです。彼は数ヶ月前にcとc ++についてこれを書いています:「IMO、良いC ++コードは良いCコードよりも優れていますが、悪いC ++は悪いCコードよりもずっと悪いことがあります。」twitter.com/#!/ID_AA_Carmack/status/26560399301
オネマ

18

C ++を使用する説得力のある理由はないと思います。オブジェクト指向プログラミングを行いたい場合は、代わりにPythonを使用して、Cで高速なパフォーマンスが必要な部分を記述できます。

編集:Cとうまくインターフェースする他の言語がありますので、Pythonが気に入らない場合は、代替手段があります。


3
組み込み開発はどうですか?Pythonは常に利用できるとは限らず、Cと適切に記述されたC ++の速度の違いは、一定レベルの処理能力を超えるデバイスでは無視できます。もちろん、私はC ++コンパイラは、常にどちらか...利用できないでしょう仮定
ジェームズ・

6
@ジェームズ「よく書かれたC ++」-キャッチがあります:(
ds539

5
私はこの答えに同意し、Pythonで高レベルを実行します.3倍速くプロファイルを作成し、C / C ++に置き換えてボトルネックを解放するためです。「ボトルネックをC ++コードに置き換える」と言うのは冗長です。なぜなら、低レベルのコードになるため、高速化する必要があるコードで高レベルを実行しないからです。ひとつだけあります。C++とpython:/をインターフェイスさせる方法がわかりません。しかし、画面と効率の前で費やされる時間の観点から、私はそれが最良の解決策だと思います。なぜなら、ほとんどのC ++コードは何のためにも高速になるからです!
jokoon

8
大規模な金融会社で働き、Pythonの大規模な分散チームで複雑な金融システムを構築し、それがどのように気に入っているかを確認します。a)型安全性の利点、b)お尻を節約するコンパイラの利点、c)Pythonが初心者が書くことを許可するLUDICROUSコード。人々は、C ++で足を撃つのは簡単だと言います->いくつかのpythonのものは動作しますが、境界線狂気です。今は、C ++で仕事をしたいです
...-MrFox

1
@suslik:うわー、私は誰もが実際にその種のシステムにpythonを使用することにショックを受けています。悪いnoob Pythonコードについては同意します。私自身も見ました。
ラリーコールマン

13

C ++を使用する理由はありますか?もちろん。

一部の人々、他のオプションよりもC ++の使用を好む場合があります。C ++を使用する理由があるかどうかを尋ねることは、何百ものフレーバーのアイスクリームを用意する必要がある理由を尋ねるようなものです。誰もが単にバニラにこだわるのが好きというわけではありません。

開発者がすでにC ++に精通している場合、彼らに対する質問は「なぜ使用するのか?」ではなく、「なぜ使用しないのか?」このトレンディなアンチC ++のことは今SOで起こっているようですが、信じられないかもしれませんが、誰もがそれを購読しているわけではありません。一部の人々は、他の言語よりも単にC ++を好むかもしれません。

C ++ はアプリに使用する必要がありますか?もちろん違います。しかし、これとまったく同じ質問は、他の言語でも求められます。特定の言語をアプリケーションに使用する必要があるケースは非常にわずかです。


12

私はCからC ++に切り替えているだけで、テンプレートやOOPが必要ない場合でも、かなりの利益が得られると思います。

  • より良いメモリ管理
  • より強力な型システム
  • より良い標準ライブラリ
  • 名前空間

8

誰もまだこれについて言及していないことに驚いていますが、C ++は参照を紹介してくれました。これにより、ポインターのすべての問題と落とし穴がほとんど解決されます。

void ModifyVar(int& var)
{
    var = 5;
}

int test = 4;
ModifyVar(test);

の代わりに:

void ModifyVar(int * var)
{
    *var = 5;
}

int test = 4;
ModifyVar(&test);

はるかに安全で簡単です...そして、値渡しのオーバーヘッドがありません。


3
また、はるかに柔軟性が低い。参照(C ++スタイル)は、ポインターもある言語の特定の一般的な構成要素を単純化するのに適していますが、ポインターの代わりになるには程遠いため、面白くさえありません。そして、あなたの例は、参照のためのすべての良いケースではありません。
ベンフォークト

3
@ベン:それでは、なぜそれが悪い例なのか説明てもらえますか?
ネイサンオスマン

6
@George:2文字(カウント 'em)短いこと以外は何も変わっていないのですか?問題を解決したり、落とし穴を強調したりすることはなく、一時変数(参照が得意なもの)の寿命を延ばすようなクールなことすらしません。
ベンフォイト

@Ben:何かを忘れている-参照は常に有効です。ポインタは、(NULLを含む)あらゆるものを指すことができ、物事が正しく行われないと、あらゆる種類のメモリエラーにつながる可能性があります。参照をNULLにすることはできず、参照するアドレスを変更することはできません。
ネイサンオスマン

5
@George:「参照は常に有効」は完全に偽です。必要な場合は例を挙げますが、このことを既に知っているのに十分な専門家であることを望んでいます。また、無効なポインターを使用して無効な参照を作成することについても話していません。ポインターを使用する関数には、引数の前提条件を記載したドキュメントが必要です。しかし実際には、すべての機能にはそのレベルのドキュメントが必要なので、ポインターに対するストライキと呼ぶのはばかげています。
ベンフォイト

5

通常、場所と理由は次のとおりです。

  • 親しみ
  • 希望する言語機能
  • 使用したい特定のライブラリ
  • 性能要件

サーバー側のプログラミングでは、多くの場合、コンパイルまたは解釈された無数の異なる言語から選択できます。通常、言語の選択は、あなたまたはあなたのチームが最も効果的なプラットフォームによって決まります。または、まだチームを持っていない場合、市場でのスキルの可用性。

ちなみに、多くのスクリプト言語はC / C ++で拡張可能であるため、パフォーマンス(のみ)に基づいてC / C ++を使用することを決定することを本当に理解していません。遅い部分をC / C ++拡張機能に移行する機能と相まって、迅速な開発言語の利点が得られます。確かに、すべての操作が重要なシステムプログラミングを理解している場合は理解できますが、ほとんどのアプリ開発では理解できません。


2
親しみやすさが一番の理由であり、あなたがそれについて最初に言及したことに驚いています。
ポール・ブッチャー

4

C ++ vs Python vs Perlは簡単に判断できません。プロジェクトと要件に依存します。

C ++には、多くのプラットフォームで実行される、古くからのユーティリティがあります。しかし、単にStringをIntegerに渡し、逆にストリームをたどり始めるのは苦痛です。

一方、C ++には、ライブラリへの依存関係が非常に多くあります。GCC XまたはVC ++ Yで何かをコンパイルすると、それらのツールの次のバージョンでコードが実行されることに頼ることはできません。同じ地獄がWindowsにあり、同じ地獄がUnixにもあります。

Perlは、Unixの世界から力を得ていますが、特に正規表現ツールとして使用されています。ほとんどの場合、これが使用されます。Javaでさえ通常の方法では実行できない非常に深刻なツール(ファイルをWebサーバーにアップロードする方法を確認してください)に加えて、Perlは「やるだけ」です。

Pythonは簡単で、柔軟性があり、動的な言語です。関数に整数を送信できるほど簡単なので、スクリプトは文字列を期待しますが、結果を得ることができます!予想外ですが、結果です。したがって、プログラマーは非常に慎重である必要があります。IDLEはデバッグを提供しますが、システムにTELNETで接続した場合、または3レベル下でSSHを使用して問題を見つけたい場合、デバッガーはそこに立ちません。しかし、それはいくつかの素晴らしい数学の仕事を速くすることができます。

Javaは流行語、エイリアンテクノロジー、ビッグワードのエコシステムであり、ファイルをWebサーバーにアップロードしたい場合、サーバーにJSPがある場合にのみ実行できることがわかります。システムライブラリまたは監視などのシステム機能を呼び出す場合は、多くを掘り下げる必要があることがわかります。そして、おそらくJNIに到達してOK ...あなたはそれから...「なぜ、主?」

それとは別に、Javaはビジネススイートやマルチスレッドに最適なツールであり、とても気に入っています。

すぐにプログラムを作成し、履歴書に「ああ、私もその技術を知っています」とあなたのボスになりたいと驚かせてください!とはいえ、この技術はそれほど必要ではないかもしれません...(OK、皆さん、私はSpring Frameworkが嫌いです....)


1
残念ながら、Pythonにはバージョン依存性があることを考慮する必要があります。特に、Python 3に移行した後は、perlと同じです。すべてに厄介な依存関係があります:
gbjbaanb

3

言語を選択する際に留意すべきことは、言語を使用することで得られるメリットと、言語を取得するのにかかる時間です。

pythonとperlのような言語間の主なアイデアは、より少ない人的時間で、より多くのCPU時間でより多くのことをすることです。実際、実行されるよりもPythonまたはperlスクリプトのコーディングにより多くの時間を費やすことになりますが、私の言いたいことは理解できます。

C / C ++の利点は、高速ですが、構文と厳密な型指定が犠牲になることです。コンパイル時にコンピューターが選択しないように、多くのことを自分で行う必要があります。

コードを作成すると、一部の行が他の行よりもはるかに多く実行され、それらの行が問題を引き起こす行です。一方、コードの残りの部分、つまり多くの時間を費やしたコードは、はるかに少ない頻度で実行されます。聞いたことがあるかもしれませんが、これは悪名高い80/20ルールであり、そのようなルールをバイパスすることはできません。

この問題の解決策は、すべてのコードを実行するために、より簡単な言語を使用することです(簡単に言うと、開発者に優しいことを意味します。

CやC ++で実行した場合と比較して、非常に迅速に実行できます。

プログラムは遅くなりますが、プロファイラーを使用すると、実行時間の80%を占める部分を分離し、CまたはC ++で実行します。

この方法でプログラムを作成することで、多くの時間を節約でき、プログラムは同じくらい効率的で、高速で、メモリリークの可能性がはるかに少なくなり、時間を節約できます。

スクリプト言語は開発者の側にあるように設計されましたが、最適化は依然として可能です。もちろん、デザインパターンの魔術師やSTLのブードゥー教徒、またはLispの戦士、さらにはハスケル修道士になることもできます。しかし、言語は私たちにコンピューターとの会話をさせます。コンピューターのために言語は作られません!



2

私が使用するC ++は、クラス付きのCと呼ばれます!


8
おっと、「class」キーワードを使用しました。これでオブジェクト指向の設計を理解できました!
dss539

私のC ++は、名前空間を持つCと呼ばれます。
jsz

6
私のC ++は、umm .. ManojのC ++と呼ばれます。
マノジR

+1それが私がC ++を使用する唯一の理由です。
mbq

...また、例外。
mbq

0

実際には、このように形成されたすべての質問に対する単一の答えがあります。tech Yの代わりにtech Xを使用する最大の理由(XとYはほぼ同じレベルです(ほぼすべての現代のプログラミング言語がそうであるように))既にXを知っていてYを知らないからです。

(しかし、Haskellが到着した後、他のものを使用する理由はありませんでした)


0

いいえ、まったくありません。パフォーマンスが必要でなく、他の言語を使用できるライブラリがある場合は、C / C ++を気にしないでください。私は、言語を(簡単に?)実行できない組み込みシステムをターゲットにしているときに、最近それを行います。プラグインを書いているのに、実際にはないので、時々Cを使用します。

ただし、CやCの使用を避けるためにPython、Perlなどを使用することはありません。私の好みは実際にはC#です。ブーは良い選択肢です。しかし、実際にはHaskellOCamlDMLなどはすべて問題ありません。


7
あなたはポイントを逃しました。
マットジョイナー

@Matt Joiner:私はそうではないと確信しています。私は何を取りこぼしたか?

問題は、C ++を使用しないことです。
マットジョイナー

@Matt Joiner:うーん、別の見方で私は尋ねられていることがわかります。私も(私は気にして私が使用する代替いけないと述べた)と答えたようにしかし、それはそうです

私はほとんどためのC#の本をdownvoteしたい...
Vreality
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.