人々がC++をバッシュする理由を私が聞いた典型的な理由は、彼らが実際にはC++を知らず、「クラス付きのC」だけを知っているということです。私はC++を学び始めたばかりですが、単に「クラスでのC」ではなく、実際にC++を学びたいです。 C++を適切に学習するにはどうすればよいですか?いくつかの例は素晴らしいでしょう。
まず、STLを使用します。何よりも、コンテナ(vector
、deque
、list
、map
、set
、&c。)とそのパフォーマンス特性を把握してください。基本(accumulate
、transform
、remove_if
)で定義されたアルゴリズムプリミティブの<algorithm>
ヘッダー。 C++はマルチパラダイム言語であることを理解し、すべてをOOモデルに強制することを試みないでください。
あなたがやっていることがわかりやすく、読みやすく、タイプセーフでない場合は、Cの方法でやっている可能性があります。型の安全性、const
の正確さ、参照セマンティクス、およびRAIIの基本的な標準について学びます。微妙に非常に Cとは別にC++を設定します。最新の最新情報を言語(auto
、ラムダ、右辺値参照による型推論)を適用して、コードの明確さと品質を向上させます。
@Fred Nurkはすでに本のリストへのリンクを投稿しているので、詳細には触れませんが、-Accelerated C++から学ぶ最初の本を検討します。
例として、かなり単純なプログラムを考えてみましょう。標準のUnix "sort"コマンドの単純化されたバージョンです。コードを短く(ただし、少なくとも少し興味深い)に保つために、コードをフィルターとして動作させ、sort -u
とほぼ同等の結果を生成してみましょう。 Classesタイプのコードを使用したCでは、通常、次の順序で何かが表示されます。
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
const int max_lines = 1024 * 1024; // allow up to one megaline of input.
int sort_func(void const *a, void const *b) {
return strcmp(*(char const **)a, *(char const **)b);
}
int main() {
char buffer[1024];
char **lines;
unsigned current_line = 0;
lines = new char *[max_lines];
while (cin.getline(buffer, sizeof(buffer))) {
char *temp = new char[strlen(buffer) + 1];
strcpy(temp, buffer);
lines[current_line++] = temp;
if (current_line == max_lines)
break;
}
qsort(lines, current_line, sizeof(lines[0]), sort_func);
cout << lines[0];
for (int i=1; i<current_line; i++)
if (strcmp(lines[i], lines[i-1]))
cout << lines[i] << "\n";
for (int i=0; i<current_line; i++)
delete [] lines[i];
delete lines;
return 0;
}
さて、これは特定のひどいコードではありません(私が完全に正直だったとしたら、おそらくもっと悪くなるでしょう)。バッファサイズをgetline
に渡すため、バッファはオーバーフローしません。次に、ラインにバッファを割り当て、データをバッファにコピーして、次のバッファに進みます。ファイルの終わりなども正しくチェックします。
それを、おそらくC++でコードを書く方法と比較してみましょう。
#include <iostream>
#include <iterator>
#include <set>
#include <string>
class line {
std::string data;
public:
operator std::string() const { return data; }
friend std::istream &operator>>(std::istream &is, line &l) {
return std::getline(is, l.data);
}
};
int main() {
std::set<std::string> lines((std::istream_iterator<line>(std::cin)),
std::istream_iterator<line>());
std::copy(lines.begin(), lines.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
このバージョンは明らかに少し短いです。また、最大行長や最大行数などの固定制限のほとんどを排除しました。ただし、さらに重要な点として、明示的なループは含まれていません。入力ループはセットのコンストラクターで暗黙的に処理され、出力ループはcopy
の呼び出しで処理されます。セットの定義では、重複のソートと削除は暗黙的に行われます。
C++の設計者が考えていることを読んでください 新しい言語としてのC++の学習 。
標準C++ [C++、1998]を最大限に活用するには、C++プログラムの作成方法を再考する必要があります。このような「再考」へのアプローチは、C++をどのように学習(および教示)できるかを検討することです。どのデザインとプログラミング手法を強調したいですか?言語のどのサブセットを最初に学習したいですか?実際のコードで強調したい言語のサブセットは何ですか?
このペーパーでは、標準ライブラリを使用してモダンスタイルで記述された単純なC++プログラムのいくつかの例を、従来のCスタイルソリューションと比較します。これらの簡単な例からの教訓は大規模なプログラムに関連していると簡単に主張しています。より一般的には、低レベルのスタイルと比較して効率を損なうことなく優雅さを提供するために抽象化に依存する高水準言語としてのC++の使用を主張しています...
C++は、クラス、デストラクタの自動クリーンアップ(RAII)、例外、ポリモーフィズム、演算子のオーバーロード、テンプレート(ジェネリック)、およびコレクションとアルゴリズムを提供するジェネリックで構築された標準ライブラリを備えたCです。
「C with classes」と言うと、確かにそうです。ある程度は、上記の多くがクラスの機能の一部であるためです。
Cを知っていて、C++を学びたい場合は、「Accelerated C++」を読むとよいでしょう。ただし、C++のほとんどの「使用する必要がある」部分であるshared_ptr(一部C++ 0xですが、現在ブーストで長期間利用可能で、すでにstdに含まれている可能性があります)。
したがって、「Accelerated C++」の後に「Beyond the Standard Library」を読んでください。
ソースコードファイルが適切に整理されたクラスのCを使用すると、コンパイルと実行の両方でアプリを高速化できます。一方、後の「アカデミックC++」の悪用により、コンパイルが最大100倍遅くなり、アプリケーションが適切に実行できなくなります。パフォーマンスが重要な場合。私が取り組んでいる会社(おそらくその分野で最大のもの)には、コンパイルに最大30分またはそれ以上かかるツールがいくつかありますが、自宅で同じ機能を自分で作成し、コンパイル時間は1分未満であり、バグははるかに少なく、作業時に使用されるテンプレートのスパゲッティよりはるかに保守しやすくなっています。したがって、本当に重要なのは、仕事をやりたい場合、または完璧なアカデミックC++をコーディングしていると言いたい場合です。
しかし、これを実現するには、多くのコーディングを行い、クラスでCを適切にコーディングする方法を学ぶ必要があります。おそらく、最初にアカデミックC++を学習する必要があります:)かそうでないかは、スキルと意志と忍耐力に大きく依存するため、クラスでC++またはCのいずれかをひどくコーディングすることはありません。
私はこれが物議を醸すことになることを知っていますが、本当にC++を研究するために、ポインタを使用しないでください。ポインターはC++で役立ちますが、最初の使用は、C++を「クラス付きのC」として認識することに影響を与える可能性があります