2013年9月25日水曜日

C++ new演算子

前回の続き
ここでは動的なオブジェクト生成について見て行きます。^^
new演算子を使うと、malloc()関数で動的にメモリ確保するのと同じように、
動的なオブジェクトの生成ができます。

//PeachBoxクラスのポインタを準備
PeachBox *pPeachBox = NULL;        //NULLで初期化しておきます
pPeachBox = new PeachBox;     //new演算子でPeachBoxオブジェクトの
                                                    //領域確保します
                        //pPeachBoxはPeachBoxオブジェクトの
                       //先頭アドレスを指し示します

このようにまとめて書いてもOKです。^^

PeachBox *pPeachBox = new PeachBox;

こちらは初期化もされるので一石二鳥ですね。

new演算子を使用してオブジェクトを生成すると、オブジェクトのためのメモリ領域が
動的に確保させます。そして、メモリ確保のタイミングでコンストラクタが呼ばれます。

一方静的にオブジェクトを生成した場合は、宣言と同時にコンストラクタが呼ばれます。
PeachBox myPeachBox;

メモリ確保の注意点
オブジェクトのメモリ確保についてですが、C言語のmalloc()関数を使うとコンストラクタが
呼ばれないのでメンバ変数が初期化できません。
そのため、実行時に予期せぬ動作をしてしまいます。オブジェクトを生成するときは、
malloc()関数を使わないようにしてください。

//予測不可能な動作をするダメダメな例
PeachBox *pPeachBox = (PeachBox *)malloc(sizeof(PeachBox));
if (pPeachBox != NULL) {
                :

でも、このような斬新なことを試みる発想力は悪くないと思います。^^
次回はdeleteとサンプルプログラムの紹介です。

今日の名言
「北風がバイキングを作った」スカンジナビアにこんなことわざがあるが、これは我々の
人生に対する警鐘と考える事もできる。安全で快適な生活、楽しくのんびりした生活さえ
あれば人間は自然に幸福になり、善良になるという考え方は、いったいどこから来たの
だろう?それどころか自己憐憫に陥っている人間は、クッションの上にそっと寝かされて
いても依然として自分を哀れみ続ける。歴史を見ればわかるように、人間が自己の責任
を背負って立てば、環境が良かろうと悪かろうと中程度であろうと、気骨のある人格が
育ち、幸福が必ずやってくる。だからこそ、北風がバイキングの生みの親となったのだ。
                                 ハリー・エマーソン・フォスディック

現代は演出の時代である。単に事実を述べるだけでは十分ではない。事実に動きを与え
興味を添えて演出しなければならない。興行的な手法を用いる必要がある。映画、ラジオ、
テレビなど、みなこの手法を使っている。人の注意を引くには、これによるのが何よりも
有効だ。
                                 デール・カーネギー

2013年9月23日月曜日

メモリの確保と解放の話

これまでの記事で、クラスからオブジェクトを生成する際、
変数宣言と同じような書き方をしていました。
この方法では、普通に変数宣言したのと同様に、オブジェクト用のメモリは
プログラム実行時に自動的に確保されます。
このようなメモリ確保は、静的なメモリ確保といいます。

一方で、プログラム実行時の条件やユーザからの入力内容に応じて、
メモリを確保したい場合があります。実務でもこちらの使い方が大半です。
このような実行時の状況に応じて、プログラムの処理上でメモリを確保する事を
動的なメモリ確保といいます。

例えば、読み込んだ画像を右に90度回転させて表示させるプログラムというものを
考えてみます。
このようなプログラムでは、実行時に使用する画像は横長の長方形かもしれませんし、
あるいは正方形かもしれません。
様々なサイズに対応することを考えると、あらかじめ読み込む画像の大きさを
決めることができません。

あらかじめ非常に大きなメモリを確保して、大半の画像を読み込めるようにして
対応することも可能ですが、それはとても非効率です。

実際にプログラムを動かす環境は、最近のPCなどとは違い、搭載メモリが128メガ
だったりします。読み込み画像だけのためにほとんどを使ってしまうと、他の処理が
使えるメモリが少なくなってしまいます。
仮に今それでよかったとしても、将来の機能追加を考えると...です。(-_-;)

ちなみに搭載メモリを増やすという解決策はNGです。(>_<)
コストが高くなるため、作り手と買い手、どちらにとっても嬉しい結果になりません。
喜ぶのはメモリ製造会社だけ!?

そんなわけで、普通は実行時の画像サイズや色数をもとに確保するメモリ量を
変えるようにするのです。いわゆる業界の常識というやつですね。

オブジェクトも、動的なメモリ確保によって生成できます。
このとき使うのがnew演算子です。そして、動的に生成したオブジェクトを解放する
ときはdelete演算子を使います。
これは、C言語のメモリ確保/解放関数のmalloc()/free()と同じ関係にあります。

C++でもmalloc/freeは使えますが、newとfree(), malloc()とdeleteといった混ぜて
使うようなことはできませんので注意してください。
newとdelete、malloc()とfree()というようにそれぞれでセットになります。

今日の名言
天才の生み出すものは、すべて熱中の産物に違いない。
                                  ベンジャミン・ディズレーリ

もし私に涙を流させたければ、まず君自身が苦痛を感じることだ。
                                  ホラティウス

私は移民の子であったので、頑迷、思いやりのなさ、偏見のすべてをなめ尽くした。
だが、私は苦しまなかった。むしろ一段と努力に励むための鞭だと考えた。
                                  バーナード・バルーク

失敗は一種の教育である。「思考」とは何であるか知っている人間は、成功からも
失敗からも、非常に多くの事を学ぶ。
                                  ジョン・デューイ

私は災難の起こるたびに、これを良い機会に変えようと努力し続けてきた。
                                   ジョン・D・ロックフェラー

2013年9月21日土曜日

C++ this !?

this なにがコレなんでしょう? というthisの話です。^^

this とはそれを記述したオブジェクトそのものを指し示すポインタです。
オブジェクト内のメンバ変数や関数は、変数名や関数名だけで利用できました。
実は正確に記述するならば、 this-> がつきます。
省略可能なため、普通は書かないことが多いです。あまり見たこともないです。(^_^;)

thisを使うと何がいいのでしょうか?
それは、メンバ関数の引数やローカル変数にメンバ変数と同じ名前を付けることが
できるということです。もちろんどちらの変数を使うといった区別は必要ですが。

具体的にthisを使った例を見て行きます。
引数の値をメンバ変数に代入するコンストラクタです。

#define NAME_SIZE_MAX  32
MyPerson(char *string, int number) {
    strncpy(name, string, sizeof(NAME_SIZE_MAX));
    age = number;
}

ここでは、受け取った引数string、numberをメンバ変数name, ageに代入しています。
このときthis->を使うとメンバ変数名と重複した名前にできます。
もっともあまりメリットがあるような気はしませんが...(-_-;)

MyPerson(char *name, int age) {
    strncpy(this->name, name, sizeof(NAME_SIZE_MAX));
    this->age = age;
}

this->name でオブジェクトのメンバ変数nameである事を明示的にしています。
一方、nameはコンストラクタの引数のnameです。

どうでしょう? コレ(this)

今日の名言
人の興味を引こうと思えば、まず自分が本当に興味を感ずることが必要だ。
                                    ジョン・モーリー子爵

真の熱中の持つ美と力について考えようではないか。そして自分であろうと他人であろうと
その目を開かせようと努力する時には、ほんの一つの熱意でも、抑えたり冷却したり
しないように気をつけようではないか。
                                    ジョセフ・タッカーマン

恐怖心を克服したければ、自分の事ばかり考えていてはダメだ。他人を助けるように
心がければ、恐怖は消え去る。

熱中は性格を作る原動力である。 物事に熱中できなければ、いくら才能があっても
いつまでも芽を出さない。大抵の人は、まだ使い方を知らない隠れた才能をたくさん
持っていると断言してよかろう。たとえ教養があり、しっかりした判断力があり、考えが
理知的であっても、心を打ち込んで思考し行動する事を知らないうちは、隠れた才能の
存在は、誰にもわからない-本人ですら知らないのだ。
                                    デール・カーネギー

2013年9月16日月曜日

C++ 関数へ値を渡す方法を考える

関数に値を渡す方法は、「値渡し」、「アドレス渡し」、「参照渡し」という3種類があります。
今回はそれぞれの使いどころを見て行きます。

3つの方法の比較
それでは、 「値渡し」、「アドレス渡し」、「参照渡し」を比べてみます。
            :
struct Person{
    char name[32];
    int age;
};

void PrintPersonReference(Person &psn);  //参照渡し
void PrintPersonPointer(Person *psn);       //アドレス渡し
void PrintPersonValue(Person psn);           //値渡し
            :

int main(void)
{
            :
     PrintPersonReference(person1);        //参照渡しなので&を付けない
     PrintPersonPointer(&person1);          //アドレス渡しなので&を付ける
     PrintPersonValue(person1);              //値渡しなので&を付けない
            :

これを見ていると、一つ問題がある事に気づきます。(^_^;)
 
参照渡しと値渡しは関数の呼び出し方法が全く同じなので
引数の値が変更されるかどうかわからないのです。(ーー;)

この問題を避けるために、関数の中で引数の値を変更するのは
「アドレス渡し」にするというルールにすると良さそうです。^^

このように、状況別に使い分ける事をおススメいたします。
      関数側で引数を変更しない 関数側で引数を変更する
int型など小さいデータを渡す 値渡し アドレス渡し
構造体など大きいデータを渡す constにした参照渡し アドレス渡し


今日の名言
弁護士になろうとしっかり心に決めれば、それだけで目的は半分達成されたも同然である。
きっと成功してみせる、と決心することが、何よりも重要だということを、常に暗記すべきだ。
                                     エイブラハム・リンカーン

一度に一つずつ事を行え。あたかも自分の生死がそれにかかっているかのような気持ちで。
                                     ユージン・グレース

事実を知れ-事実を抱き締めよ。すべてに基本は熱中である。
そして熱中は純真な心から生まれる。
                                     ラルフ・ワルド・エマーソン

 空気から歌は生まれない。自分が何を創造しつつあるか理解し、感じ取らねばならない。
                                     アーヴィング・バーリン

2013年9月14日土曜日

C++ 引数を参照にする 其の弐

今回は参照引数に const をつけて定数にすることの話です。

関数の引数をconst形式の参照にしてみる
前回は、関数の仮引数を参照にすると、関数の中から実引数の値を
変更できることを紹介しました。
しかし、実引数の値が変わると困ることが、往々にしてあります。
そんなときのために、このように仮引数にconstをつけることができます。

void NoChangeValue(const int &number);

引数がconst形式の参照となるため、値の変更ができなくなります。
では、それを確かめるサンプルプログラムです。

 #include <iostream>

using namespace std;

void NoChangeValue(const int &number); //const形式の参照

int main(void)
{
    int num1 = 500;

    NoChangeValue(num1);

    return 0;
}

void NoChangeValue(const int &number)
{
    number = 100;  //値を代入して、変更を試みます
}

すると、当然コンパイルエラーになります(ーー;)

# g++ -o test test.cpp
value.cpp: In function ‘void NoChangeValue(const int&)’:
value.cpp:18:14: error: assignment of read-only reference ‘number’

read-onlyと言われてしまいました。
確かに変更できなくなっていることがわかりましたね。^^


引数をconst形式の参照にすると何が良いか、どんなときに使う?
構造体などの大きなデータを関数に渡すときは、次のようなメリットがあるため
引数をconst形式の参照にする効果が期待できます。^^

  • 値渡しと同じように、実引数へ影響しない
  • 大きなデータの値渡しは、コピーに時間がかかってメモリも多く消費する

では、サンプルプログラムです。

include <iostream>

using namespace std;

struct Person{
    char name[32];
    int age;
};            //36バイトで全然大きくはないのですが、構造体を用意します

void PrintPersonReference(const Person &psn) //こちらは参照渡し
{
    cout << "Name : " << psn.name << endl;
    cout << "Age  : " << psn.age << endl;

    return;
}

void PrintPersonPointer(const Person *psn) //こちらはアドレス渡し
{
    cout << "Name : " << psn->name << endl;
    cout << "Age  : " << psn->age << endl;

    return;
}

int main(void)
{
    Person psn1 = { "Bob", 20 }; //構造体の宣言と同時に初期化しています

    PrintPersonReference(psn1);  //参照渡しでコール
    PrintPersonPointer(&psn1);    //アドレス渡しでコール
    return 0;
}

実行結果
# ./test2
Name : Bob
Age  : 20
Name : Bob
Age  : 20

まぁ、当然表示される結果は同じです(^_^;)
ですが、速いプログラムを書けるように、方法を知っておく必要があります。
あとは習うより慣れろ!ということですね。^^


今日の名言
雄弁に欠かせないものは誠実さである。自分に対して誠実な人間になれば、
人を説得することができる。
                                    ウィリアム・ハズリット

他人のために尽くすことだ。そうすれば、つまらない劣等感など、7月の畑にかかる
朝露のように、跡形もなく消え失せてしまう。
                                    デール・カーネギー

人は皆、深く根を下ろした興味や趣味を持つべきだ。精神は豊かになるし、生活が
グッと楽しくなる。そのうえ、興味の種類と性質によっては、自分の国に対して
貢献もできる。
                                    デール・カーネギー

目的をあくまで追求し、道徳を堅固に保ち、あくまで自分自身を守り通せば、
あらゆる目標が達成できるとともに、この心構え一つで、一段と大きな
仕事をする腹が決まる。
                                    フレデリック・B・ロビンソン

2013年9月8日日曜日

C++ 引数を参照にする 其の壱

関数の引数も参照で宣言できます。
Cでは引数をアドレスで渡せましたが、C++では参照で同様のことが実現できます。

では、関数の引数に参照を使う例を紹介します。

//関数定義
double AddNumber(double &x, double &y)  //引数を参照で宣言しています
{
    return x * y;    //*(アスタリスク)がついていないことがポイントです
}

//実際の呼び出し例
double number1 = 3.141592, number2 = 1.2345;
double answer = AddNumber(number1, number2); //&がついていないことがポイント

ここでは、もし x と y の値を変更すると number1, number2 の値も変わることを
押さえてください。

それでは、参照の機能を使って引数を渡すとアドレスで引数を渡した時と
同じことができます、というサンプルプログラムです。

#include <iostream>

using namespace std;

void ValueChanger(double &x);  //参照の関数のプロトタイプ

int main(void)
{
    double number1 = 10;

    cout << "number1 = " << number1 << endl;

    ValueChanger(number1);  //ValueChanger関数の呼び出し

    cout << "number1 = " << number1  << endl;

    return 0;
}

void ValueChanger(double &x)
{
    x = 500;
}

実行結果
# ./test
number1 = 10
number1 = 500

解説
main関数の中の変数number1は最初10で初期化しています。
ValueChanger関数をコールすると、値が500に変わっていますね。(^^)
これはValueChanger関数の中で引数 x に500を代入したためです。


今日の名言
男女を問わず物事に集中できる人間は、自分と接触する人間を惹きつけてやまない。
まるで磁石である。
                                 H・アディングトン・ブルース

うんと熱中せよ。熱中が熱中を生む。
                                 ラッセル・H・コンウェル

私は口角泡を飛ばして熱弁を振るう人間が好きだ。泥のぬかるみになるより、
間欠泉になって熱湯を吹き上げるほうが良い。
                                 ジョン・G・シェッド

私が心ゆくまで作曲したり、文章を書いたり、お祈りしたり、説教したりするときは、
怒りを込めてやる必要がある。その時、私の血液は沸き立ち、私の理解力は
研ぎ澄まされるのだ。
                                 マルティン・ルター

彼は思う存分にそれを行い、富み栄えた。
                                 旧約聖書「歴代志上」

美徳は自信を生み、自信は熱中を生む。そして熱中は世界を征服する。
                                 ウォルター・H・コッティンガム

2013年9月7日土曜日

C++ 参照とは何か?

今回はC++で使えるようになった参照という機能の紹介です。^^
この機能を使えば、変数に別名(エイリアス)をつけることができます。
例えば、参照を使って変数numberに別名newnumをつけるとこのようになります。

int number;
int &newnum = num;  //もととなる変数と同じ型で宣言してください
                               //&newnum で参照の宣言です^^

このように別名をつけると、元々の変数名でも別名でも同じようにアクセスできます。
どちらかの値を変更すると、もう一方も変更されます。

#include <iostream>

using namespace std;

int main(void)
{
    int number = 0;
    int &newnum = number;

    newnum = 10;
    cout << "number = " << number << endl;
    cout << "newnum = " << newnum << endl;  //アクセス方法に注目です。
                               //&が要りません。
    return 0;
}

実行結果
# ./test
number = 10
newnum = 10

number, newnumのどちらも同じ10になっています。
同じことをCで実現すると、ポインタを使います。しかし、ポインタの場合は
その指示す先のデータにアクセスするときは*(アスタリスク)をつけなければ
なりません。

プログラム例
int number;
int *newnum = &number;  //ポンタの宣言と代入

*newnum = 100;  //*を付けてアクセス、星々の問題が!?

参照のほうがシンプルですね。(^^)
このように、わずか1文字でも入力は少なくするのがポイントです。

もう少しだけ参照で遊んだサンプルプログラム
#include <iostream>

using namespace std;

int main(void)
{
    int number = 0;
    int &newnum = number;  //参照の宣言

    newnum = 10;       //まずnewnumに10を代入
    cout << "number = " << number << endl;
    cout << "newnum = " << newnum << endl;

    number = 100;      //今度はnumberに100を代入 
    cout << "number = " << number << endl;
    cout << "newnum = " << newnum << endl;

    newnum = 1000;          //最後はまたnewnumに
    cout << "number = " << number << endl;
    cout << "newnum = " << newnum << endl;

    return 0;
}

実行結果
# ./test2
number = 10
newnum = 10
number = 100
newnum = 100
number = 1000
newnum = 1000

newnumはnumberの別名なので、どちらの値を変更しても
もう一方が同じ値になっています(^^)

今日の名言
信念を持たない限り、人に信念を与えることはできない。自分で納得いかない限り、
人を納得されることはできない。
                                 マシュー・アーノルド

人生もフットボールも原則は同じだ。ラインに向かって突っ込め、ファウルするな。
ボールから身をかわすな。ラインに向かって突っ込め。
                                 セオドア・ルーズヴェルト

失敗は成功の母である。落胆と失敗は、人を確実に成功に向かわせる二つの
試金石である。この二つを自発的に研究し、何か今後に役立てられることを
掴み取ることができれば、これほどプラスになるものはない。過去を振り返ってみよう。
失敗が成功の助けになった場合があるはずだ。
                                 デール・カーネギー

天才は力の集結である。手に入れる価値が有るものなら何でも手当たり次第に
手に入れる人間は、猫を追うブルドッグのように、全身の筋肉を緊張させて、
ただひたすらに自分の目標に向かって進む。
                                 W・C・ホルマン

2013年9月4日水曜日

C++ 参照概論

変数にニックネームをつけてみる?答えは聞いてない...
C++には、新しく参照という機能があります。参照とは、変数に別名(エイリアス)を
つけるための機能です。例えば、Peggyさんに「PeachGirl」というニックネームをつけた
としても、Peggyさん本人は一人だけです。PeachGirlに桃を一つあげれば、それは
Peggyさんに桃を一つあげたことと同じことになります。

因みにPeggyさんは、いつもやっているECC英会話ポッドキャストに登場します^^
http://www.eccweblesson.com/podcast/
毎週短いダイアログが2つあり、それらはわりと身近な単語で構成されているし
バッチリ解説もあるのでとても聴きやすいと思います。無料なのに!
たまに思わずクスリと笑ってしまうやりとりがあるので、電車で聞いている人は
変な人に思われないよう要注意でしょう^^

話を戻して、実際にプログラムの変数で考えてみます。
ここでは、Peggyという名前の変数に、PeachGirlという別名をつけます。
変数Peggyに10を代入すると、それはPeachGirlに10を代入したのと同じことです。
PeachGirlが10人も!冗談です(^_^;)
さらに変数Peggyに1を加えれば、なんと自動的にPeachGirlにも1が加わるのです。

もしC言語を使いこなしている方は、ポインタと同じじゃないか!と思ったかもしれません。
そうです、同じようなことができます。ただ、C言語の場合のポインタと違って*PeachGirlの
ようにアスタリスクを付けてアクセスする必要がなくなるのです。
星が何個付けばいいんだ?まぁ、とりあえずコンパイルしてみるかといった、曖昧さを
含んだ星々の問題に頭を悩ませる事がなくなります。 (^O^;)
さすがC++、便利ですね。

関数にニックネームを渡してみる?いいよね...
この参照という機能、関数を呼び出す時の引数に使うと便利です。実引数と仮引数が
同じ所を参照する形で引数を渡すことを、「参照渡し」といいます。
C言語では参照渡しの時にはポインタを使っていました。
実はこの時、ポインタそのものは「値渡し」の形で関数に渡っているのです。^^
つまりCでは実質、値渡ししか存在しなかったといえます。
参照渡しはポインタを使って擬似的に行われていたのです。
C++では新しく、ポインタを使わないで参照渡しが出来るようになりました。(本格サポート)
星々の問題がなくなることで、プログラムが見やすくなります。
次回以降で、関数への引数の渡し方についてオススメの方法を紹介していきますので
是非参考にしてみてください(^^)


今日の名言
優柔不断は疑いと恐怖心を生み出し、行動は勇気を生み出す。恐怖心を克服するには
家に閉じこもってくよくよしていては駄目だ。外へ出て仕事に精を出す事だ。
                                    デール・カーネギー

自分が恐怖を抱いている事柄を一覧表にして、無意味なものはないか調べてみることだ。
率直な気持ちで調べれば、その大部分が取るにも足りぬ恐怖であることが分かる。
                                    デール・カーネギー

我々は、安楽と贅沢が得られなければ人生の幸福はありえない、と考えているが、
実際に人を真に幸せにするものは、何か我を忘れて取り組める事柄を持つことである。
                                    チャールズ・キングズリー

ひとかどの人間になりたければ、物事に熱中できる人間になることだ。人に好かれる
ようになるし、機械のように毎日同じことの繰り返しばかりする退屈な人生から逃れられる。
どんな分野でも先頭に立てるようになる。そうなるに決まっている、これが人生だから。
仕事に全身全霊を打ち込めば、楽しさがどんどん増していくばかりでなく、人に信用される
ようになる。ちょうど発電機を目撃した人間が電気を信用する気になるように。
                                   ジョナサン・オグデン・アーマー