諸言
学習履歴全体のリンク
https://qiita.com/shigural/private/444b991293e5ab1b40af
プログラミング言語C++(第4版)
第I部 はじめに
1.本書の読み進め方
2.C++を探検しよう:基礎編
auto型
C++では変数の型としてauto型を使うことができる。わざわざ型を明示する特殊な事情がない限りはautoを用いると良い
constexpr宣言
constexprを変数の型名の前につけるとコンパイル時評価がなされる。ただし、これを関数に利用する場合にはできるだけ単純な関数にしておくべきである
forによる走査
for文を利用して配列vの中身を一つづつxに取り出すような実装は次のように行える
//実装例1
int v[]={0,1,2,3};
for(auto x:v)cout << x << "\n";
//実装例2
for(auto x:{0,1,2,3})cout << x << "\n";
//実装例3(実装例1と比較して高速)
int v[]={0,1,2,3};
for(auto& x:v){
cout << x << "\n";
++x
}
nullptr
C++ではnullポインタをNULLではなくnullptrで表現する。
nullptrはNULLと異なり、ポインタ型であるために0と混同することがない
enumされた複数の列挙体を見分けるためにenum classという宣言を行う方法がある
enum class Color{red, blue, green};
Color x=Color::red;
例外
throwを利用すると例外を投げることができる。
try{
try{
throw out_of_range{"testMessage"}//例外を投げる
}
catch(out_of_range){
//例外が投げられたときの処理
throw;//更に下に同じ例外を投げる
}
}
catch(out_of_range){
//最終的な処理
}
コンパイル時警告
static_assertを利用するとコンパイル時にメッセージを出力することができる。
//intのサイズが4バイト未満であれば(つまり4バイト以上を満たさなければ)アサーションを出す
static_assert(4<=sizeof(int), "integers are too small");
3.C++を探検しよう:抽象化編
スマートポインタ
スマートポインタであるunique_ptrを利用するとリソース漏れをふせぐことができる
演算子の抑制
デフォルト定義に対して=deleteをつけるとその定義を除去することができる。
たとえば
Shape(const Shape&)=delete;//コピー演算はなくなる
といった事ができる。これはコピーコンストラクタをprivateに置くよりも明示的であり、推奨される。
関数オブジェクト
■ラムダ式は難解であるため略
可変個引数テンプレート
次のように可変引数テンプレートを用いることで、複数ある引数の1番目とそれ以降を分けて再帰的に処理が行える
void f() {}//引数がない場合
template<typename T,typename... Tail>
void g(T value) {
std::cout << value<<std::endl;
}
template<typename T, typename... Tail>
void f(T head, Tail...tail) {//引数がある場合
g(head);
f(tail...);
}
int main() {
f(5, 3, 7, 2);
return 0;
}
4.C++を探検しよう:コンテナとアルゴリズム編
ムーブ
コンテナ(vectorなど)を実装する際には、もとのコンテナのポインタをnullptrにして、コピー先のポインタを変更する「ムーブ」で実装すると効率が良い
using
using namespace std;
などは名前空間を混乱させるため、できる限り使わないほうが良い
vector
vector型の変数は
vector<変数またはクラスの型> 変数名(要素数,初期値)
と初期化される
map
mapのアクセスはO(logN)であり、意外に高速である
listとvector
一般に、特別な理由がない限りはvectorをlistよりも優先するべきである。一見listのほうが高速そうなInsert()でさえ、小データであればvectorのほうが高速である
スマートポインタ
unique_ptrはコピー演算子に対して、ムーブによるコピーを行う
shared_ptrはコピー演算子に対して、通常のコピーを行う
5.C++を探検しよう:並行性とユーティリティ編
並行処理
次のようにすると、タスクを並行で実行できる。ただしこの例では「PaHerallllel o World!」などと奇妙な出力が行われる可能性があるので、本来はタスクを完全に分離し、引数を与え、返却値を得て、共有データを一切使用しないべきである
void f() { std::cout << "Hello"; }
struct F {
void operator()() { std::cout << "Parallel World!\n"; }
};
int main() {
std::thread t1{ f };
std::thread t2{ F() };
t1.join();
t2.join();
Sleep(1000);
return 0;
}
■難解であるためその他は略
第II部 基本機能
6.型と宣言
初期化
変数の初期化は、自動キャストがなされないように
int a{8};
などと行うべきである。ただし、auto型では例外的に=で初期化すると良い
decltype
変数の型を実行時に決定するにはdecltype演算子を用いる。■難解であるため略
typedefの命名
typedefで新たにつけられた変数には伝統的に、末尾に_tをつける
using
using XXX=charなどとすると、以下XXXをcharとして利用することができる
7.ポインタと配列と参照
文字列
文字列は隣接している場合には自動的に連結される。
ex)
a="abc""def"
はa="abcdef"
と同値である。これを上手く使えばプログラムの可読性が向上する