C++
C++は、1950年にデンマークで生まれたBjarne Stroustrup(ビャーネ・ストロヴストルップ)が1985年に作成したプログラミング言語である。仕様の標準として現在のところ5個の標準がある。それぞれの通称は、C++98、C++03、C++11、C++14、C++17である。
言語標準には、標準ライブラリも含まれている。標準ライブラリの一部として、Standard Template Library (STL)がある。STLは、1950年にロシアで生まれたAlexander Stepanov(アレクサンドル・ステパノフ)が開発した。
言語標準は、有料であって無料で公開はされていない。しかし、ほとんど等価な草案は公開されていて、そちらが広く利用されている。どの標準についてどの草案を参照すべきか、cpprefjpというウェブサイトに記載されているようだ。例えば、C++17の標準についてはDocument Number N4659をHTMLで閲覧できる。なお.pdfファイルは1,622ページある。
Hatena Blogでは、Markdown記法が使える。
const correctness
という言葉がある。
律儀にconstを多用すると、かえって面倒なことにならないだろうか? 例えば、class Tを変更しないメンバ関数void print() const;があるとする。しかし、もしprint()した回数を状態として持ちたくなったら、インタフェースの規約に実装が縛られて困るのではないだろうか? あるいは、キャッシュを保持したくなる場合もあるかもしれない。mutableキーワードというものがある。外部に公開しない内部の状態についてはこれを使い、外向きにはconstとする考え方もあるようだ。話が複雑になる気がする。
rule of five
rule of threeあるいはrule of fiveという言葉がある。
- destructor
- copy constructor
- copy assignment operator
- move constructor
- move assignment operator
rule of zeroという言葉もある。
exception safety
という言葉がある。David Abrahamsが考案した。
- No-Throw Guarantee
- 最も高い安全性。ユーザにとっては正常系しか存在しないように見えるもの。
- Strong Exception Safety
- rollbackして元の状態に戻れることは保証されているもの。
- Basic Exception Safety
- 例外が発生したとしてもシステムを矛盾した状態にはしないもの。
- No Exception Safety
- 最も低い安全性。例外が生じた場合の状態について保証はない。
参考:
copy and swap idiom
という言葉がある。
Joint Strike Fighter Air Vehicle C++ Coding Standards
というものがある。Lockheed Martin社が2005年に定めたもの。F-35のために作られた。F-35より前はAda言語が使われていた。
move semantics
という言葉がある。C++11で導入された。右辺値参照型(T&&)が導入されたことによる。
従来でも、ポインタを陽に使えば同じ性能を出せる。所有権の操作を陰に書けるようにした。
C++には、garbage collectionの機能はない。RAII (Resource Acquisition Is Initialization)によることが原則であり、それで済まないときには、newとdeleteを対応させることを基本にしてきた。garbage collectionの方法には、大きく分けて、TracingとReference Countingがある。shared_ptrは参照カウント方式によるgarbage collectionであり、unique_ptrは、所有者が1つのときのそれだが、JavaのようなTracing方式のgarbage collectionは、言語仕様としては今なお持っていない。その意味で、C++にはgarbage collectionの機能はない。
move semanticsやsmart pointerは、ポインタなどによるboilerplate codeを抽象化して隠蔽し、外見をJavaやPythonに似せる方向性なのではないかと思う。しかし、Tracing方式のgarbage collectionが存在しない以上は、参照カウントや所有権といった話になり、プログラマが気にかける事柄は必然的に存続する。
RAII
RAIIを使わずに、オブジェクトの生成と破棄を常にnewとdeleteでやると、C++の基本はずっと分かりやすいのではないだろうか。しかしそれではコードが煩雑になるためRAIIが導入され、連鎖的に、コピーコンストラクタ、さらにはデフォルトの暗黙的なコピーコンストラクタなどが定義された。そのため、smart pointerやmove semanticsが導入される以前から、コピーコンストラクタについてだけでも、C++は少し難しさのある言語になってしまっている気がする。
恐らく、C++の理解が浅いときに起こる問題は、動作がおかしくなるものと、動作が非効率になるものとに分けられるのではないだろうか? 例えばmoveで済むところで、大量のコピーを行っていれば、処理のパフォーマンスが下がるだろう。しかしとりあえずは気にせず、コードを書くことでC++の基本的な機能に慣れていくことのほうが大切だろう。