ビャーネ・ストラウストラップ : プログラミング言語 C++ [第4版]

作成日 : 2015-09-19
最終更新日 :

概要

C++ を一通り学んだ人に対する事典。

感想

分厚くて値段が高い。1 ページあたりの値段は約 7 円なので、きちんと勉強すればもとが取れるだろう (借りて一部を読んだだけでいうのもおこがましいが)。

サンプルコードは断片的だ。実際に動かすためには、省略された箇所に関して、コード(ドライバーやスタブなど)を適切に補完する必要がある。 どのような点で省略されているかというと、たとえば、p.97 の 「4.1.2 標準ライブラリヘッダと名前空間」では、次のように述べている。

簡単化するために、本書のサンプルでは、std:: を明示的に記述することはほとんどない。 また必要なヘッダを常に明示的に #include するたけではない。本書のコードを、コンパイルして実行するためには、 読者自身が適切な(§4.4.5,§4.5.5,§30.2 に示している)ヘッダを #include して、宣言されている名前が利用できるようにしなければならない。

このためのコードがうまく書ければ中級者から上級者といえる。わたしは初級者なので、うまく書けない。それでも例を挙げてみよう。

第3章 C++ を探検しよう:抽象化のメカニズム

2025-06-13 追記:p. 86 のメンバ関数の下記の定義について考える。

template<typename T>
Vector<T>::Vector(int s)
{
  if (s<0) throw Negative_size {};
  elem = new T[s];
  sz = s;
}

このままでは、Negative_size の関数を書かないといけないのが煩わしい。既に備わっている例外機構を次のように使うことが別案としてある。

template<typename T>
Vector<T>::Vector(int s)
{
  if (s<0) throw length_error {"Negative size"};
  elem = new T[s];
  sz = s;
}

なおいずれの場合でも、using namespace std; は必須である。

第 17 章 構築と後始末とコピーとムーブ

2025-06-11 追記:pp.508-509 にある2次元 Matrix は次のようにするとコンパイルが通る。これには、Duck.ai の GPT-4o の助けを借りた。

#include <array>
#include <stdexcept>
#include <algorithm> // for std::copy
#include <utility>   // for std::move

template<typename T>
class Matrix {
  std::array<int, 2> dim; // 2次元
  T* elem;                // T型の dim[0]*dim[1]個の要素へのポインタ

public:
  Matrix(int d1, int d2) : dim{d1, d2}, elem{new T[d1 * d2]} {} // 簡単なもの(エラー処理なし)

  int size() const { return dim[0] * dim[1]; }

  // コピーコンストラクタ
  Matrix(const Matrix& m) : dim{m.dim}, elem{new T[m.size()]} {
    std::copy(m.elem, m.elem + m.size(), elem); // 要素をコピー
  }

  // コピー代入
  Matrix& operator=(const Matrix& m) {
    if (this != &m) { // 自己代入チェック
      if (dim[0] != m.dim[0] || dim[1] != m.dim[1])
      throw std::runtime_error("bad size in Matrix = ");
      std::copy(m.elem, m.elem + m.size(), elem); // 要素をコピー
    }
    return *this;
  }

  // ムーブコンストラクタ
  Matrix(Matrix&& m) noexcept : dim{m.dim}, elem{m.elem} {
    m.elem = nullptr; // 元のオブジェクトのポインタを無効化
  }

  // ムーブ代入
  Matrix& operator=(Matrix&& m) noexcept {
    if (this != &m) { // 自己代入チェック
      delete[] elem; // 既存のリソースを解放
      dim = m.dim;
      elem = m.elem;
      m.elem = nullptr; // 元のオブジェクトのポインタを無効化
    }
    return *this;
  }

  ~Matrix() { delete[] elem; } // デストラクタ
};

int main() {
  // 使用例
  Matrix<int> mat(3, 4); // 3行4列の行列を作成
  return 0;
}

第 40 章 数値演算

2025-05-29 追記:たとえば、40 章 数値演算の p.1165 にある関数 f は、ドライバー関数 main を書き、さらにいくつか記述を補足して、初めて動く。 補足例を示す。

/* cerrno.cpp
* stroustroup p.1165
*
*/
#include <cmath>
#include <cerrno>
#include <iostream>

using namespace std;

void f()
{
	errno = 0; // 古いエラー状態をクリア
	sqrt(-1);
	if (errno == EDOM) cerr << "sqrt() not defined for negative argument" << endl; // 定義域エラー
		pow(numeric_limits<double>::max(), 2);
	if (errno == ERANGE) cerr << "result of pow() too large to represent as a double" << endl; // 値域エラー 
} 
int main(void) {
	f();
}

人名の例

本書の例から、人名が出ている例を拾ってみた。

14 章「名前空間」のうち、本書の p.413 で、こんなコードがある。
American_Telephone_and_Telegraph::String s3 = "Grieg";
American_Telephone_and_Telegraph::String s4 = "Nielsen";
続いて、p.414 では名前空間 Lib が ある使用中のライブラリとして、
Lib::String s5 = "Sibelius";
と記されている。明らかに、この3人は、北欧の作曲家である。すなわち、s3 のグリーグはノルウェー、s4 のニールセンはデンマーク、 s5 のシベリウスはフィンランドの作曲家である。本書著者のビャーネ・ストラウストラップはデンマーク出身だから、北欧の誇りがあるのだろう。

17 章「構築と後始末とコピーとムーブ」のうち、本書の p.491 で、こんなコードがある。

struct Work {
	string author;
	string name;
	int year;
};
	
Work s9 { "Beethoven",
	  "Symphony No. 9 in D minor, Op. 125; Choral",
	  1824
	}; // メンバ単位の初期化
	
Work currently_playing { s9 }; // コピー初期化
Work none {}; // デフォルト初期化	

これは言わずと知れた、ベートーヴェンの交響曲第9番「合唱」である。s9 の s は symphony (交響曲)のことだと思えばいい。

規則

37 章「正規表現」の p.1053 に デフォルトでは、パターン比較処理は常に最長一致で探索する(C++ の Max Munch 規則と同様である:§10.3)とある。 さて、Max Munch 規則とは何か。その前でのことから最長一致のことと考えていいのだろう。念のため、同書の§10.3 を見てみる。 p.266 ではこうある。文法規則が適用される前の段階で、字句上のトークンは、文字の並びとして切り出されて構築される。 このとき、もっとも長い並び文字の並びが、トークンとして切り出される。たとえば、&& は単一の演算子であって 2 個の & 演算子ではない。 また、a+++1 は (a ++) + 1 である。この規則は、最長一致法 ( Max Munch rule ) と呼ばれる。 Wikipedia では、Maximum munch が表題となっている。

誤植

p.438 サンプルコード dc.h の namespace Lexer で定義された class Token_strem の public 領域のコンストラクタ Toekn(istream& s) の初期化リストが ip{&s}, owns(false}, ct{Kind::end} {} となっている。ここの owns は owns{false} が正しいと思われる。

p.537 下から 5 行目、「complex クラスは具象型なで、」とあるが、 これは「complex クラスは具象型なので、」が正しいだろう。

p.566 中央付近、特に、無名共用体 ( anonymous union ) と呼ばれる union を利用していいる とあるが、 文末は「利用している」が正しい。

サポートページ

http://isbn.sbcr.jp/75954/(isbn.sbcr.jp)にある。

書誌情報

書名プログラミング言語 C++ [第4版]
著者ビャーネ・ストラウストラップ
訳者柴田 望洋
発行日2015 年 3 月 7 日
発行元SB クリエイティブ
定価8800 円(本体)
サイズ??版
ISBN978-4-7973-7595-4
その他越谷市立図書館で借りて読む

まりんきょ学問所コンピュータの部屋コンピュータの本C++, C#> ビャーネ・ストラウストラップ : プログラミング言語 C++ [第4版]


MARUYAMA Satosi