ロベールのC++入門講座を読んで C++ を初歩の初歩から再入門するよ - 後編

ロベールのC++入門講座
ロベールのC++入門講座を読んで C++ を初歩の初歩から再入門するよ - 前編の続きです。

13章 もっと深く(11:12)

13-12 から再開。
テンプレート引数には typename 以外のものも使えるよという話。


まずはテンプレート引数にクラステンプレートを渡す話。
簡単に写経。

template <template <typename, typename> class TEMPL>
class Huga
{
public:
    TEMPL< int, allocator<int> > v;
};

Huga<vector> huga;


次にテンプレート引数に整数定数を渡す場合。
おお。これは使えるなあ。

template <int N>
class SBit
{
public:
    static const int VALUE = 1 << N;
};


int main(int argc, char *argv[])
{

    cout << SBit<0>::VALUE << ' '
         << SBit<1>::VALUE << ' '
         << SBit<2>::VALUE << ' ';
}


次はクラステンプレートの特殊化。これは理解できていると思う。
その次は関数ポインタ。
メンバ関数ポインタは以前はまったので復習しておくか。

class HogeHoge
{
public:
    HogeHoge() : f(&HogeHoge::getThree) {
        (this->*f)();
    }
private:
    int getThree() { return 3; }

public:
    int (HogeHoge::*f)();
};


メンバ変数ポインタすげーというか。ちょっと気持ち悪い。
何が起きているか初心者には分からないね。

struct IntPair
{
    int first;
    int second;
};

int main(int argc, char *argv[])
{
    int IntPair::*mp;
    IntPair ip;
    mp = &IntPair::first;
    ip.*mp = 3;
    mp = &IntPair::second;
    ip.*mp = 4;
    cout << ip.first << ' ' << ip.second << endl;
    return 0;
}

14章(11:49)

  • short cicuit
  • void ポインタ
  • #if
  • 組み込みマクロ __DATE__, __TIME__ 知らなかったλ...
  • 可変個引数
  • main の return する値
  • コマンドライン引数
  • exit/abort
  • アラインメント

構造体の padding の話。padding が入る理由と気をつけるべきことは知っていたが offsetof は知らなかった。

struct Pad
{
    char c;
    int i;
};

cout << offsetof(Pad, c) << ' ' << offsetof(Pad, i) << endl; // offset とれる!

プリコンパイル済みヘッダ使ったことないや。やってみようっと。
いままで書いたサンプルで include していたヘッダをプリコンパイルする。

Pch.h を用意する。

#include <stdio.h>
#include <stdint.h>
#include <iostream>
#include <new>
#include <iomanip>
#include <vector>

プリコンパイルする

% g++ Pch.h

Pch.h.gch というファイルが出来ました。
#include "Pch.h" してやれば OK。
あれ。全然速くならないぞ。そんなもの?

15章 データ構造(12:11)

このあたりは死ぬほどやってきたので理解できていることが多いな。

  • 単方向リスト
  • 双方向リスト
  • iterator
  • スタックとキュー


placement new も知っているよと思ったら長年の疑問を解消してくれた。

class Foo
{
public:
    Foo() { cout << "Foo()" << endl; }
    Foo(int n) { cout << "Foo(" << n << ")" << endl; }
};

のようなクラスがあったとして Foo(n) で初期化した Foo を配列に入れたい。

//  Foo* manyFoo = new Foo[50]; // Foo() が呼ばれてしまい悲しい

Foo* manyFoo2 = reinterpret_cast<Foo*>(new char[sizeof (Foo) * 50]);

for (int i = 0; i < 50; i++) {
    manyFoo2[i] = Foo(i);
    manyFoo2[i].~Foo(); // 明示的にデストラクタを呼ぶ
}

delete[] manyFoo2;

これで実現できる。


再帰関数 ktkr!。SICP読んだのでここは大丈夫なはず。OKだった。安心。
ツリーとかハッシュとかこれも一時期勉強していたので基礎的なことは分かるよ。

さて15章も終わったのでお昼ご飯に行ってきます。
と思ったけど。あと少しなので読んでしまおう。

16章(12:53)

  • union
  • 無名構造体
  • ビットフィールド
    • ビットフィールドは gcc 拡張だと思っていた人がここにいますλ...。
  • 可変長配列メンバ
    • 知っているけど。こんなテクニックまで紹介するとは良い本だ
  • extern "C"
  • volatile

付録(13:08)

付録もちゃんとしている
付録C C言語C++の重要な相違点。
付録D Boostライブラリ

まとめ

10時間近くかけて読み終わりました。
C++ に関して知らないことが本当にたくさんありました。ロベールのC++入門講座を手に取って購入したのは正解だったようです。
C++ を better C として使っていた自分にはピッタリのレベルでかつ読みやすい文章。


ページ数が 947ページもあり読むのは大変ですが、僕の読んだ限りでは親切すぎるほど例や説明を繰り返してくれるので読んでいて「分からない!」という状態になったことは一度もありません。
なので C++ を使っているんだけどいまいち自分の力量に自信がないという方は本屋で手にとってみると良いと思います。
知らないことが複数個見つかればもう「買い」です。


念のため書いておきますがロベールのC++入門講座C++ の入門書として、さらには中級者へのステップアップの本として最適だと僕は思うのですが、オブジェクト指向をあわせて学ぶのには向いていないと感じました。
オブジェクト指向は別の本で理解した方がよいでしょう。


さてと次は何を読もうかなあ?
光成さんと、中島さんがたくさん C++ の本を持っていて自由に読んでいいよと言ってくれているのでお言葉に甘えよう。