ゲームが作れるようになるまでがんばる日記

ゲーム制作のことを中心にゲームに関することを書いています

C++

const参照渡し

久しぶりにEffective C++を読みながら勉強の再開。第4章20項。 関数にオブジェクトを渡すときは値渡しよりもconst参照渡しを使うほうが良い。値渡しではオブジェクトのコピーが行われるためコンストラクタやデストラクタが実行されることになる。const参照渡…

ループを使わずに配列の順序を逆にする

C++

昨日(id:toburau:20100302)のウェブの記事にあった"ループを使わずに配列の順序を逆にする"という問題。日記を書いていたときにはまったく解法を思いつかなかったけど、ふと再帰を使えばできるのではと思ったのでやってみた。 アルゴリズムは配列を半分に分…

型のデザインで注意すること

Effective C++を読みながらC++の勉強を再開。第4章19項。 クラスのデザインは型のデザイン。デザインするとき考えるべき問題を本より引用。 ・新しい型のオブジェクトはどのように生成され、破棄されるのか? ・オブジェクトの初期化と代入は、異なる操作に…

一貫性

Effective C++ 第4章18項 インタフェースには一貫性を持たせよう。 ある機能を提供するライブラリを作った場合、そのインタフェースには一貫性を持たせておくべき。 たとえば、あるオブジェクトの配列を扱うクラスがあり、その配列の要素の個数を得るメンバ…

スマートポインタは独立で

Effective C++ 第3章17項 次のような引数を持つ関数があるとする。 void Func( std::tr1::shared_ptr<Test> p, int value ); この関数を次のように呼び出したとする。 int getValue(); Func( std::tr1::shared_ptr<Test>(new Test), getValue() ); 一見正しそうに見える</test></test>…

newとdelete

Objective C++ 第3章16項 配列をnewで確保したときはdeleteではなくdeleteを使うこと。また配列でないものをdeleteで破棄しようしてはならない。 配列をtypedefして使っているときにはdelete[]を使うのを忘れないように注意が必要。 typedef float pos[3]; i…

auto_ptrその2

C++

あるクラスのポインタを受け取るような関数があった場合、そのクラスのオブジェクトをauto_ptrを使って作成した場合にはそのままでは渡すことができない。 class Test; void Func(Test* p); int main() { auto_ptr<Test> pObj(new Test()); Func(pObj); // エラー</test>…

shared_ptr

C++

昨日試したauto_ptrでは一つのオブジェクトを複数のauto_ptrでは指すことができなかった。 その問題を解決したものとしてshared_ptrというのがある。これは参照カウンタ型のスマートポインタで参照回数を記録しておくことにより、同じオブジェクトを複数のsh…

auto_ptr

C++

標準ライブラリにauto_ptrというのがあるのは知っていたか、どう使うのか分からなかったので試してみた。 #include <iostream> #include <memory> using namespace std; class Test { public: Test() { cout << "Test Constructor" << endl; } ~Test() { cout << "Test Destruc</memory></iostream>…

すべてコピーするように

Effective C++ 第2章12項 コピーコンストラクタやコピー代入演算子ではオブジェクト全体をコピーするようにして、コピーし忘れたデータが無いようにしなくてはならない。 たとえば、途中からメンバ変数を追加した場合は、コピーコンストラクタやコピー代入演…

自己代入その2

Effective C++ 第2章11項 自分自身を代入しようとする自己代入のコードが書かれても大丈夫なようにoperator=を実装すべき。 簡単な方法としては同じかチェックするというもの。 Test& Test::operator=(const Test& rhs) { if(this == &rhs) return *this; //…

自己代入

Effective C++ 第2章11項 自己代入とは自分自身を代入する次のようなコード。 class Test; Test obj; obj = obj; こんなコード書くわけない。と思っても次のコードではどうかな。 Test obj[10]; obj[i] = obj[j]; 添え字のiとjが同じものを指していたら? *p…

代入演算子は*thisへの参照を戻すように

Effective C++ 第2章10項 コピー代入演算子を定義するときには*thisへの参照を戻すようにするべき。 class Test { public: Test& operator=(const Test& rhs) { ... return *this; } }; このようにしておけば、次のようにつなげて書くことができる。 Test a,…

コンストラクタやデストラクタ内で仮想関数を呼ばない

Effective C++ 第2章9項 基底クラスのコンストラクタやデストラクタ内で仮想関数を呼ぶようにしても、派生クラスで実装した仮想関数は呼ばれない。派生クラスのオブジェクトを作成した時はまず基底クラスのコンストラクタが実行されるが、その時にはまだ派生…

デストラクタでは例外を投げない

Effective C++ 第2章8項 デストラクタで例外を投げることはできるが、するべきではない。 たとえばデストラクタで例外を投げるクラスがあり、そのクラスのオブジェクトを配列で複数個作成した場合。その配列がいらなくなったときオブジェクトのデストラクタ…

仮想デストラクタにする?しない?

Effective C++ 第2章7項 基底クラスだからといってデストラクタを必ず仮想デストラクタにするというのは間違い。 基本は「ポリモーフィズムのための基底クラスは仮想デストラクタにする。」 ポリモーフィズム、つまり派生クラスのオブジェクトを基底クラスの…

仮想テーブルポインタ

Effective C++ 第2章7項 仮想テーブル(vtbl)とは関数ポインタの配列のことで、オーバーライドされた仮想関数のいろいろな実装を指すポインタの配列。 で、このvtblを指すのが仮想テーブルポインタ(vptr)。 あるオブジェクトで仮想関数が呼び出されたら、オブ…

基底クラスには仮想デストラクタ

Effective C++ 第2章7項 ある基底クラスから派生クラスを作成し、派生クラスのオブジェクトを基底クラスのポインタで扱うような場合。基底クラスのデストラクタが仮想でない場合、派生クラスのデストラクタが実行されなくなってしまう。 class Base { public…

コピーできないようにする

Effective C++ 第2章6項 あるクラスのオブジェクトをコピーできないようにするには、コピーコンストラクタとコピー代入演算子をprivateにしてしまえばよい。 class Test { private: Test(const Test&); Test& operator=(const Test&); }; 宣言だけしておいて…

自動で作られる関数

Effective C++ 第2章5項 C++でクラスを宣言したときには自動で作られる関数がある。 class Test {}; と書いたとしても次のように書かれたのと同じである。 class Test { public: Test() {...} Test(const Test& rhs) {...} ~Test() {...} Test& operator=(co…

関数に対するstaticなオブジェクト

昨日の「ローカルでない静的オブジェクト」の続き。 初期化の順番が意図しないものになってしまうことのある問題は、ローカルでない静的オブジェクトをローカルなstaticオブジェクトにしてしまえばよい。 問題のオブジェクトを適当な関数の中に移動して、そ…

ローカルでない静的オブジェクト

Effective C++ 第1章4項 本には次のように書かれている。 異なる翻訳単位にある「ローカルでない静的オブジェクト」の初期化の順番はきめられていない。 これを理解するのにちょっと時間がかかった。 翻訳単位というのはソースコードのこと。つまり異なる翻…

スタックオブジェクトとヒープオブジェクト

スタックオブジェクトとは関数内でローカルに定義されるオブジェクトなど。 ヒープオブジェクトとはnewによって生成されるオブジェクトなど。 どうもこの辺の知識が怪しいので復習。

配列の初期化は?

メンバ変数はコンストラクタのメンバ初期化子リストで初期化すべしということで、コードを書いていてふと疑問が。 メンバ変数に配列があった場合、どうやって初期化すればよいのだろう。 で、検索してみたところ、どうやら配列はできない模様。普通にコンス…

オブジェクトは使う前に初期化する

Effective C++ 第1章4項 オブジェクトは使う前に初期化すること。 class Test { private: string m_Text; public: Test() { m_Text = "this is test"; } }; このプログラムではTestクラスのコンストラクタ内でメンバ変数のstringを初期化しているように見え…

constと非constのメンバ関数の重複を取り除く

Effective C++ 第1章3項 あるクラスのメンバ関数でconstと非constの両方を用意した場合、それぞれに同じ処理のコードを書くという面倒なことになってしまう。それを避けるためには非constの関数ではconstな関数をconstを取り除いて呼ぶようにすればよい。実…

メンバ関数のconst

effectvie C++ 第1章3項 本に書かれていたメンバ関数のconstの意味。「ビットレベルでの不変性」(「物理的な不変性」)と「論理的な不変性」の二つ。 「ビットレベルでの不変性」とはC++のconstの定義。constなメンバ関数はそのオブジェクトが持つデータを変…

関数の戻り値にconst

Effectvie C++ 第1章3項 自分で定義したある型に掛け算の演算子を定義したとする。 class Test {...}; const Test operator*(const Test& lhs, const Test& rhs); この掛け算の演算子の関数にもconstを付けておけば、次のようなタイプミスを防ぐことができる…

constその2 const_iterator

Effectvie C++ 第1章3項STLのiteratorでのconstの場合。iteratorの宣言にconstを付けるとiterator自体がconstとなり、参照先のデータはconstとはならず変更できる。 std::vector<int> v; const std::vector<int>::iterator p = v.begin(); *p = 123; // これはOK p++; </int></int>…

ポインタのconst

Effectvie C++ 第1章3項 constについての項目。あいかわらずconstは苦手。バグを防ぐためにも値を変更しないばあいにはcosntを付ける癖をつけたい。 ポインタにconstを付けるときは位置によってポインタ自身がconstなのか参照している先のデータがconstなの…