アルゴリズムとデータ構造に触れるためにC++基礎を学んでみる

初心者にオススメし難いけれども、コンピュータの根本を知れると言われるC言語。

私も初めてプログラミングに触れたのは大学時代のC言語でした。

TaNA
学生時代、コンソール操作に苦手意識があり、またプログラミングも苦手だったのですが、今こうしてIT業界に身を置いている技術者の端くれとして、C言語に触れずエンジニアと名乗って良いものか…最近そう感じるようになりました。

そして一歩上の技術者になる為、そして以下の動機から今更C++を触ってみました。

・アルゴリズム+データ構造系の参考書を読むため.

・AtCoderの過去問を解くため.

・コンピュータサイエンス基礎理解.

C言語はコンピュータを完全に制御する為に作られた言語。

それ故に昨今のメジャー言語に比べてコンピュターサイエンスの基礎知識が求められるせいか、アルゴリズム系の参考書もC(もしくはC++)で解説される事も多いですが、C++と言っても範囲が随分広いので、今回は以下参考書を読み進められるレベルを目標にC++を触ってみました。

C++は強力な機能を多く搭載しています。

上手く活用すれば絶大な能力を発揮する事から「ヌンチャク」に例えられるらしい。

C++言語の特徴

C言語は1970年代前半に生まれ、C++言語はC言語を拡張した言語です。

◼️C++の特徴

・オブジェクト指向がサポートされているコンパイル型言語.

・性能に関して妥協が無く、ハードの性能を最大限に引き出せる.

・古いバージョンでも動作するよう後方互換性が重要視されている.

そもそも人間が書いたプログラムをコンピュータが実行するにはどうすれば良いのか!?

まずマシン語に翻訳しますが、翻訳方法にはコンパイル型とインタープリタ型の2種類があります。

TaNA
ちなみにコンパイルについて、正確には人間が書いたコードをアセンブリ語に変換するのがコンパイラで、アセンブリからマシン語への変換をアセンブラが担当しているそうです。通常コンパイルと言えば、これらを一括りにして呼んでますね。

ちなみに両者の違いは以下の通り。

◼️コンパイル型

・実行前にマシン語に変換する必要がある.

・既にマシン語に変換されているので実行速度が速い.

・実行時にコンパイルが必要なので開発効率は下がる.

◼️インタープリタ型

・実行時にマシン語に変換される.

・事前にマシン語への変換が不要なのですぐに実行できる.

・都度マシン語に変換されるので実行速度が遅い.

JavaやC++がコンパイル型で、PHPやRubyがインタープリタ型になります。

初めてのHello World

どんな言語でもまずは「Hello World」の表示から!!

何か規約エラーがあると、コンパイルに失敗して実行エラー。

◼️サンプルプログラムでの注意事項.

・全角と半角、大文字と小文字は区別される

・C++の実行プロセスはmain()の呼び出しから.

・「std::cout << "文字列"」で画面上への文字列表示.

・文字列は二重引用符「”」で囲む必要がある.

・改行は\n、また「<< endl;」でも改行が可能.

・処理の最後にはセミコロン「;」が必要.

・coutを利用にはヘッダ(#include)の記述が必要.

変数と型

基本型の変数を定義には、宣言→定義→初期化の三段階。

変数ではなく定数(初期化は1度のみ)として定義する場合はconst利用。

基本型は8種類(char・short・int・long・long long・float・double・long double)。

ただし変数の型が事前に分からない場合は型推論の機能利用。

基本制御文

C++の制御文にはif、switch、for、while、do while、gotoなど、他の言語と大体同じ。

式の値によって場合分けをする場合にはswitch文を利用。

繰り返し処理は、for文やwhile文などを利用。

ポインタの概念

C言語を勉強し始めて、最初につまづくと言われるポインタの概念。

ポインタはオブジェクトのメモリ上での場所(アドレス)を利用するための仕組み。

◼️ポインタの初期化

対象となる型* 変数名 = 対象となる型のオブジェクトのアドレス;

[補足事項]

&(アドレス演算子):変数等のアドレスを取得.

*(間接演算子):指定したアドレスのデータにアクセス.

ポインタの動きについて、サンプルプログラムで確認。

ポイントの記述には以下2種類があり、解釈は違えど結果は同じになります。

int* pa:int型の変数にポインタ変数paを定義.

int *pa:*を付けるとint型になる変数paを定義.

ポインタの有効活用は別途勉強が必要そう。

コンテナと配列

複数のデータを一まとまりに扱いたい場合、vector、unordered_map、配列など。

またC++標準ライブラリの仕組みをコンテナと呼び、よく利用される一つがstd::vector。

TaNA
ただvectorはメモリ上で並ぶ様に制御されてるらしく、要素追加の為にあらかじめ予備の領域を確保、その領域に要素が追加されていきますが、足りなくなると別領域に全要素をコピーする仕様となっています。

先に格納要素数が分かっている場合、reserve()で領域確保するのが望ましい。

vectorは多くの場面で利用出来ますが、別コンテナを使った方が良いケースとは!?

・末尾以外の場所に要素追加や削除を頻繁に行う場合.

・要素を頻繁に検索する場合.

検索を多用する場合にはunordered_mapが有効!!

最後にC++の言語自体にも標準利用出来る配列。

昨今では配列の代替として、srd::arrayが用意されており、こちらの利用が望ましいと言われていますが、多くの既存コードで利用され、メモリ管理に学べる点を考慮し、配列ついて記載。

以下のように定義すると、自動メモリに配置されます。

もう一つnewによる定義方法があり、こちらはフリーストアに配置されます。

文字列 : string

stringで文字列定義ができ、文字列リテラル同士を「+」で結合は出来ない。

文字列から数値へ、数値から文字列の変換は以下のように実装。

以下の参考書をざっと1周しましたが、他言語に比べてメモリ周りを考える事が多い。

他にも構造体やらC++でのクラス(多重継承)とかまだまだ勉強の必要がありそうです。