このページの趣旨 

January 25 [Tue], 2005, 0:10
職業上、本を読むことが多いのですが、あまりに忘れっぽいので
備忘録をつけることにしました。
購入の際、参考にしていただけると幸いです。

Effective C++ 改訂2版 

January 25 [Tue], 2005, 0:15

Scott Meyers著/吉川邦夫訳

言わずとしれた名著です。
Tips系のものが50個収録されています。
読み返すうちにうなるものばかりです。
おすすめです。

【1項】#defineではなく、constとinlineを使おう 

January 25 [Tue], 2005, 0:38
#define ASPECT_RATIO 1.653
->const double ASPECT_RATIO = 1.653;
コンパイルの段階で解釈されるので、シンボルテーブルに入らない

const char * const authorName = "Bibouroku";
const対象を決める

クラスに特有の定数を定義

class TEST
{
private:
static const int TEST_NUM = 5; //宣言
int test[TEST_NUM];
};

const int TEST::TEST_NUM; //定義

あるいは

class TEST
{
private:
enum {TEST_NUM=5}; //enum Hack
int test[TEST_NUM];
};


#define max(a, b) ((a) > (b) ? (a) : (b))
template
inline const T& max(const T& a, const T& b) {return a > b ? a: b;}

【2項】<stdio.h>ではなく、<iostream>を使おう 

January 25 [Tue], 2005, 0:48
int i;
TEST t;
cin >> i >> t;
cout << i << t;

class TEST
{
public:
friend ostream& operator<<(ostream& s, const TEST &t);private:
int _a;
};

ostream& operator<<(ostream& s, const TEST &t)
{
s << t._a ;
return s;
}

<参考>19項、22項

【3項】mallocとfreeよりも、newとdeleteを使おう 

January 25 [Tue], 2005, 0:52
malloc, freeはconstructorとdestructorを知らない
String *strArray = static_cast(malloc(10 * sizeof(String)));

String *strArray = new String[10];

【4項】コメントはC++スタイルで書こう 

January 25 [Tue], 2005, 0:56
省略

【5項】newとdeleteのペアは、同じ形式に揃えよう 

January 26 [Wed], 2005, 1:04
string *strintPtr1 = new string;
string *stringPtr2 = new string[100];

delete stringPtr1;
delete[] stringPtr2;

typedef string AddressLine[4];
string *pal = new AddressLine; //AddressLineはnew string[4]として解釈される

delete pal;
delete[] pal;

【6項】デストラクタでポインタメンバにdeleteを使うのを忘れないようにしよう 

January 26 [Wed], 2005, 1:10
クラスメンバの追加に際して忘れがちなこと
・それぞれのコンストラクタで、ポインタを初期化すること
・代入演算子では、既存のメモリを削除して、新しいメモリを割り当てること (17項)
・デストラクタで、そのポインタに対してdeleteを行うこと

NULLポインタを削除するのはいつでも安全

【7項】メモリ不足に備えよう (1) 

January 27 [Thu], 2005, 1:58
Newを使ったときのメモリ不足に対処する方法

#define NEW(PTR, TYPE) \
try { (PTR) = new TYPE; } \
catch (std::bad_alloc&) {assert(0);}


色々なnew(ユーザー定義型)に対処できない
-> new-handlerを使う

typedef void (*new_handler)();
new_handler set_new_handler(new_handler p) throw();



void noMemoryCase()
{
//TODO;
cerr << "no more memory";
abort();
}

int main()
{
set_new_handler(noMoreMemory);
int *piInteger = new int[10000000];
}


1. もっと多くのメモリを使えるようにする
2. 別のnew-handlerをインストールする
3. インストールされているnew-handlerを外す
4. 例外を送出する
5. リターンしない

【7項】メモリ不足に備えよう (2) 

January 27 [Thu], 2005, 2:19
<クラスへの適応例>
class X
{
public:
static new_handler set_new_handler(new_handler p);
static void* operator new(size_t sizee);
private:
static new_handler currentHandler;
};

new_Handler X::set_new_handler(new_handler p)
{
new_handler oldHandler = currentHandler;
currentHandler = p;
return oldHandler;
}

void* X::operator_new(size_t size)
{
new_handler globalHandler = std::set_new_handler(currentHandler);
void *memory;
try
{
memory = ::operator new(size);
}catch(std::bad_alloc&)
{
std::set_new_handler(globalHandler);
throw;
}

void noMemory();
X::set_new_handler(noMemory);
X *px1 = new X; //Xのnew_handlerを送出
string *ps = new string; //標準のnew_handlerを送出
X::set_new_handler(0);
X *px2 = new X;  //すぐに例外を送出

<上記の機構を汎用的に>
template
class NewHandlerSupport
{
public:
static new_handler set_new_handler(new_handler p);
static void * operator_new(size_t size);
private:
static new_handler currentHandler;
};

class X: public NewHandlerSupport
{
};

<補足>
昔のC++コンパイラはメモリ確保失敗時に0を返す
現在はstd::bad_allocをthrowする。
明示的に0を返してほしいときはnothrowをもちいる

Test *pTest1 = new (nothrow) pTest1;