人々はC ++について文句を言うのが好きなようですが、なぜC ++ではなくCを選択するのかについて、多くの証拠を見つけることができませんでした。Cはほぼ同じように不安定にならず、C ++にこれらすべての問題がある場合、なぜCサブセットに制限できないのでしょうか。あなたの考え/経験は何ですか?
人々はC ++について文句を言うのが好きなようですが、なぜC ++ではなくCを選択するのかについて、多くの証拠を見つけることができませんでした。Cはほぼ同じように不安定にならず、C ++にこれらすべての問題がある場合、なぜCサブセットに制限できないのでしょうか。あなたの考え/経験は何ですか?
回答:
ジョエルの答えは、あなたがかもしれない理由のために良いです持っているいくつかの他の人がありますが、Cを使用します:
いくつかのケースでは、しかし、あなたは可能性がしたいですというC ++よりもCを使用します:
Cサブセットを使用してC ++コンパイラーでコンパイルするだけでよいと主張しますが、そのようにすると、コンパイラーによってわずかに異なる結果が得られることがわかります。
とにかく、あなたがそうしているなら、あなたはCを使っています。あなたの質問は本当に「なぜCプログラマはC ++コンパイラを使わないのですか?」もしそうなら、言語の違いを理解していないか、コンパイラの理論を理解していません。
私はミニマリズムとシンプルさが好きです。
パフォーマンスへの恐怖や肥大化は、C ++をやめる理由にはなりません。すべての言語には潜在的な落とし穴とトレードオフがあります-優れたプログラマーはこれらについて学び、必要に応じて対処戦略を開発すると、貧しいプログラマーは言語に反して責任を負いません。
解釈されたPythonは多くの点で「遅い」言語と見なされていますが、重要なタスクの場合、熟練したPythonプログラマは、経験の浅いC開発者よりも速く実行されるコードを簡単に作成できます。
私の業界、ビデオゲームでは、RTTI、例外、または内部ループの仮想関数などを回避することにより、C ++で高性能コードを記述しています。これらは非常に便利ですが、パフォーマンスまたは膨らみの問題があり、避けることが望ましいです。さらに一歩進んで完全にCに切り替えると、C ++のほとんどの有用な構成要素がほとんど得られなくなります。
Cを選択する最大の実用的な理由は、サポートがC ++よりも広く普及していることです。C ++コンパイラさえ備えていない多くのプラットフォーム、特に組み込みのプラットフォームがあります。
ベンダー間の互換性の問題もあります。Cには安定した明確に定義されたABI(アプリケーションバイナリインターフェイス)がありますが、C ++にはありません。C ++のABIは、vtablesやコンストラクター/デストラクターなどの理由により、より複雑であるため、ベンダーごとに、またベンダーツールチェーンのバージョンによっても、異なる方法で実装されています。
つまり、あるコンパイラーで生成されたライブラリーを別のコンパイラーのコードまたはライブラリーとリンクして、分散プロジェクトまたはバイナリー・ライブラリーのミドルウェア・プロバイダーに悪夢をもたらすことはできません。
小さくてタイトな言語での作業を楽しんでいるので、Cで書くことにしました。私は、妥当な時間内に読むことができる標準へのアクセスが好きです(私にとっては、私は非常に遅いリーダーです)。さらに、(一部の PICマイクロコントローラーのように)望ましいC ++コンパイラーがほとんどない組み込みシステム用のソフトウェアを作成するために使用します。
私は別の見方をします:なぜCの代わりにC ++を使うのですか?
本「Cプログラミング言語(別名:K&R)」は、300ページ未満で言語が実行できるすべてのことを行う方法を明確に説明しています。ミニマリズムの傑作です。C ++の本も近づきません。
明らかな反論は、現代の言語のすべてではないにしても、ほとんどの場合同じことが言えます-彼らはまた、数百ページですべてを行う方法をあなたに教えることができないということです。そうだね。では、なぜ代わりにC ++を使用するのでしょうか。機能の豊富さ?力?より機能豊富な機能や強力な機能が必要な場合は、C#、Objective C、Javaなどを使用してください。C ++の複雑さを自分で負担するのはなぜですか?C ++が付与する制御の程度が必要な場合は、Cを使用することを主張します。Cは何でも実行でき、うまく実行できます。
Linusの質問に対する答えは、「C ++は恐ろしい言語だから」です。
彼の証拠はせいぜい逸話ですが、彼はポイントを持っています。
低レベル言語の方がいいので、C ++よりも好みます。C++は、追加機能のライブラリとコンパイラサポートが追加されたCです(両方の言語には他の言語にはない機能があり、実装方法が異なります)。 Cでの時間と経験、追加された低レベルの関連パワーの恩恵を受けることができます... [編集済み](慣れているため)言語/コンパイラ自体から得られるいくつかのパワーの恩恵を受けるのではなく、手動でより多くの作業を行うている)
リンクを追加する:
私は考えグーグル論評の多くは、すでにウェブ上があるので。これのために
プラグインを作成していて、C ++には標準のABIがないためです。
コンパイル時間が長いと面倒です。C ++を使用すると、コンパイル時間が非常に長くなる可能性があります(つまり、当然、スタックオーバーフローの時間が長くなります!)。
私のプロジェクトではC ++を使用しています。それから私はプレーンなCが使われている仕事を得ました(20年前に開発されたAVソフトウェアのコードベースで、ドキュメントが不十分です...)。
私がCで好きな3つのことは:
暗黙的なものは何もありません。プログラムが正確に何を行うか、何を行わないかがわかります。これにより、デバッグが容易になります。
名前空間とオーバーロードの欠如は利点になる可能性があります。特定の関数が呼び出される場所を知りたい場合は、ソースコードディレクトリをgrepするだけでわかります。他の特別なツールは必要ありません。
関数ポインタの力を再発見しました。基本的に、C ++で行うすべてのポリモーフィックなことを実行できますが、さらに柔軟性があります。
void*
が問題を引き起こした1つのケースを思い出せません。ミスから保護するための防御的なプログラミング手法は数多くあります。アサートをどこにでも配置し、マジックナンバーを構造体に(デバッグビルドで)追加するなどです。しかし、今日では、valgrind、drがあります。メモリ、およびMSVCでさえコードを計測して問題を検出するため、メモリ破損の問題を簡単に解決できます。
void*
には、whatever*
コンパイラは誠実に受け入れるものです。私は自分のコンパイラーが私を信頼しないことを望み、堅牢な型チェックを実施する可能性があります。C ++コンパイラによって発行されたテンプレート置換エラーは読むのが面倒ですが、少なくともガベージはコンパイルされません。
void*
通常避けることができます。カスタム動作を追加するときの一般的なパターンは、関数ポインターとvoid*
ユーザーデータのを渡すことです。一般的なインターフェイスは通常、次のようになります。次に、ライブラリはこれをvoid*
他の何もせずにコールバックに返します。ほとんどの場合、余分なデータがないため、NULLを渡し、コールバックのユーザーパラメータを無視します。あなたはこれを知っていたと思います。
誰も言及していないライブラリに驚いています。多くの言語がCライブラリにリンクし、C関数(extern "C"を含むC ++を含む)を呼び出すことができます。C ++は、C ++ lib( 'CにはないC ++の機能を使用するlibとして定義された[オーバーロードされた関数、仮想メソッド、オーバーロードされた演算子など...]を使用してエクスポートできない唯一のものextern "C"を介したC互換インターフェースを介したすべてのもの)。
C ++には同等の機能がないC99の機能を使用したいからです。
ただし、C ++に役立つC99機能は、一見したところほど多くはありません。可変長配列?C ++にはstd :: vectorsがあります。複素数/虚数のサポート?C ++には、テンプレート化された複合型があります。タイプジェネリック数学関数?C ++は標準の数学関数をオーバーロードし、同じ結果を引き起こしました。
名前付き初期化子?C ++ではありませんが、回避策があります。
struct My_class_params {
int i;
long j;
std::string name;
My_class_params& set_i(int ii)
{
i = ii;
return *this;
}
My_class_params& set_j(long jj)
{
j = jj;
return *this;
}
template <typename STRING>
My_class_params& set_name(STRING&& n)
{
name = std::forward<STRING>(n);
return *this;
}
My_class_params()
{
// set defaults
}
};
class My_class {
My_class_params params;
public:
My_class(const My_class_params& p) : params(p) { }
...
};
これにより、次のような記述が可能になります。
My_class mc(My_class_params().set_i(5).set_name("Me"));
std:vector
。
c ++の重要な機能のほとんどは、何らかの形でクラスまたはテンプレートに関係しています。これらは、コンパイラがこれらをオブジェクトコードに変換する方法を除いて、すばらしい機能です。ほとんどのコンパイラは名前のマングリングを使用しており、少なくとも面倒なことは何もしません。
多くのアプリケーションの場合のように、システムが単独で稼働している場合は、C ++が最適です。
システムがC ++で必ずしも書かれていないソフトウェア(最も頻繁にはアセンブラーまたはFortranライブラリー)と対話する必要がある場合は、窮地に陥っています。これらの種類のケースを操作するには、これらのシンボルの名前のマングリングを無効にする必要があります。これは通常、これらのオブジェクトを宣言することによって行われますextern "C"
、、テンプレート、オーバーロードされた関数、またはクラスにすることはできません。それらがアプリケーションAPIである可能性が高い場合は、ヘルパー関数でラップし、それらの関数を実際の実装と同期させる必要があります。
そして実際には、C ++言語は、純粋なCで簡単に実装できる機能の標準構文を提供します。
つまり、相互運用可能なC ++のオーバーヘッドは高すぎるため、ほとんどの人が正当化できません。
これはかなり浅いですが、忙しい学生としてC ++を学ぶのに時間がかかりすぎると思ったのでCを選びました。私の大学の多くの教授はPythonでの宿題を受け入れません。私は何かをすぐに取り上げる必要がありました。
「使用したいC ++のサブセットを使用する」についての1つの注釈:このアイデアの問題は、プロジェクトの全員が同じサブセットを使用することを強制するためにコストがかかることです。私の意見では、これらのコストは疎結合プロジェクト(オープンソースプロジェクトなど)の場合は非常に高く、C ++はCを使用した場所ではどこでも使用できないという意味で、より優れたCになることに完全に失敗しました。
ああ、C対C ++、炎上戦争を始めるのに最適な方法です。:)
Cは、ドライバーと埋め込みコードに適していると思います。
C ++にはCにはない優れた機能がいくつかありますが、C ++のオブジェクト指向機能の多くは、裏で発生する明らかでない副作用を伴うコードを書くときに、途方もないコーディングの混乱を引き起こす可能性があります。クレイジーなコードは、コンストラクター、デストラクター、仮想関数などに隠すことができます。Cコードの美しさは、言語の背後で目立たないことを行わないため、コードを読み取ることができ、すべてのコンストラクターとデストラクターを調べる必要がありません。等々。問題の多くは、一部の人々による不適切なコーディング方法です。
私の完璧な言語は、C99と、バイナリ出力にゼロ(またはゼロに近い)コンパイラオーバーヘッドを追加する、より安全なC ++機能の最小限のサブセットの組み合わせです。完璧な追加は、データと関数のクラスのカプセル化と命名の概念です。
なぜC ++ではなくCを選択するのかについて、多くの証拠を見つけることができませんでした。
私が証拠について言おうとしていることをほとんど呼ぶことはできません。それは私の意見です。
Cは、文法家の心の中にうまく収まるので、Cが好きです。
C ++には多くの複雑なルールがあります[いつ仮想デストラクタが必要なのか、いつコンストラクタで仮想メソッドを呼び出すことができるのか、どのようにオーバーロードとオーバーライドが相互作用するのか...]。それらすべてを習得するには多くの労力がかかります。また、参照、演算子のオーバーロード、関数のオーバーロードの間で、コードの一部を理解するには、見つけるのが簡単な場合とそうでない場合がある他のコードを理解する必要があります。
組織がC ++よりもCを好む理由についての別の質問。私はそれを知りません、私はただの人々です;-)
C ++を守るために、それは価値ある機能を表にもたらします。しかし、私が最も重視するのは、おそらくparametric( 'ish)polymorphismです:1つ以上の型を引数としてとる操作と型。
++score
:「プログラマーの心の中にうまく収まるので、Cのような人は」というあなたの発言は、非常にうまく述べられたものです。見たものが得られるものであることがわかっている単純な言語でプログラミングできることは、プログラミング言語にとって本当に魅力的な特性です。
CはC ++よりも最適化と効率をよりよく制御できるため、メモリやその他のリソースが制限されていて、すべての最適化が役立つ状況で役立ちます。もちろん、設置面積も小さくなります。
リソースが限られているシステム(組み込みシステム、またはカーネルのような実際のベアメタルコードなど)を記述していて、オーバーヘッドをできるだけ少なくしたいからです。
ほとんどの組み込みシステムにC ++コンパイラがない理由はそこにあります。人々がそれを望まないということではありません。それは、C ++コードをその小さなスペースに詰め込むことが、不可能に近づくタスクだからです。