//address_sample.cpp
#include <iostream>
using namespace std;
int main()
{
int x = 3;
cout << "xの値は" << x <<
endl;
cout << "xのアドレスは" << &x
<< endl;
}
まだ、ポインタという言葉はでてきていませんね。
実は、xのアドレスが、あとで必要になることもあります。この場合、このアドレスを格納しておく変数があるといいですね。それがポインタなのです。ポインタは何のアドレスを保持するか決めておかなければ定義できません。今の例では「int型変数のアドレス」を格納しておきたいわけです。「int型変数のアドレス」を格納する変数、つまりint型に対するポインタは一般に
int* p;
と書かれます。ここで、変数名を「p」としましたが、これはどう変えても大丈夫です。そして、「p = &x;」とすれば、pにxのアドレスが代入されるわけです。この辺の話のサンプルを書くと、たとえば次のようになるでしょう。
//pointer_sample.cpp
#include <iostream>
using namespace std;
int main()
{
int x = 3;
int* p;
p = &x;
cout << "xの値は" << x << endl;
cout << "xのアドレスは" << p
<< endl;
}
実行結果は前のものと同じようになります。(アドレスの値は変わるかもしれませんが。)意味はわかったのではないでしょうか。もし、とりあえず、わかったと思ったら、整数型の変数を二つ用意して、そのアドレスを二つのポインタに格納して書き出すプログラムを書いてみてください。それは、
//pointer_sample2.cpp
#include <iostream>
using namespace std;
int main()
{
int x = 3, y = 4;
int* p1;
int* p2;
p1 = &x;
p2 = &y;
cout << "xのアドレスは" << p1
<< endl;
cout << "yのアドレスは" << p2
<< endl;
}
ポインタの説明はこれでほぼ終わりです。どうですか?わかりましたか?
はじめてポインタを見たとき、私が思ったことは「これが何の役に立つのか?」という疑問でした。その疑問は膨らんで、自分は何をやっているんだろう、という不安につながっていきました。今そう思っている人も多いのではないでしょうか。
今私に言えることは、C++をやっている限り、ポインタは避けて通れないということと、慣れればどうということはないということです。これは何なんだろう、どうやって使いこなすのだろうと悩まずに、「次にまた出てきたときに考える」という風に大きく構えていた方がよいと思います。(大きく、は変かな?)何の役に立つかは、次回にとても大事な例をお見せしますので、それまで、待ってください。
それと、ちょっと面倒な話題ですが、書き方についてのコメントがあります。
int* p1;
は int *p1;
int *p1; int *p2;は、まとめて、
int *p1, *p2;
と書けます。int* p1, p2;
と書くとp2はポインタにならない(という規則があります)ので注意してください。
//pointer_neko.cpp
#include <iostream>
#include <string>
using namespace std;
class Neko
{
string name;
public:
Neko(string);
void naku() const;
};
Neko::Neko(string s) : name(s){}
void Neko::naku() const{
cout<<"にゃあ。俺様は"<<name<<"だ。"<<endl;
}
int main()
{
Neko dora("ボス");
//Nekoのインスタンスを指し示すポインタpcat
Neko* pcat;
pcat = &dora;
dora.naku();
pcat->naku();
}
ここでpcatがポインタです。
実行すると、ボスという名の猫が2度鳴いて終わりです。一度目はもちろんdora.naku()です。2度目の方は pcat->naku()ですが、説明しましょう。まず、pcatは「Nekoのインスタンスを指し示すポインタ」です。(これを「Nekoのインスタンスへのポインタ」とも言います。まあ、言い方の問題ですが。)これはintの例と同じ形ですね。そこに「pcat
= &dora;」で、doraのアドレスを代入しています。したがって、pcatも実質的にはdoraと同じものを表しているのです。ただ、doraがオブジェクトそのものを表すのに対して、pcatはポインタです。そこにわずかな違いがあります。
さて、doraのnaku()を呼び出すにはピリオド「.」を使って、「dora.naku();」とすればよかったのですが、pcatはポインタなので、同じやり方でnaku()を呼び出すことはできません。pcatを通してnaku()を呼び出すには
(*pcat).naku();
とすればよいのです。「*pcat」が「pcatが保持するアドレスにある変数」つまりdoraを表すからです。しかし、もっと簡単に、「->」を使って、
pcat->naku();
で、同じことができるようになっています。これで、「pcatが指し示すオブジェクト」(つまりdora)のnaku()を呼び出すことになるのです。
このように、ポインタが指し示すオブジェクトのメンバを呼び出すときには、「->」が使われることを覚えておいてください。
今日はつくづく、何の役に立つのか、という例ばかりあげました。実際、今日のプログラムはどれもポインタの説明用ですので、自分で書くプログラムの参考にはしないでくださいね。(^^;)ポインタのちゃんとした使い方や重要性の説明は難しいのですが、たとえばnewやdeleteという演算子を使うためにはどうしても必要なものです。これらについては、次回に説明します。どうか、今回の内容だけで、ポインタを判断しないでください。