p223〜p239まで

今日はもうこんな時間だけどちょっと勉強しときます。

静的ローカル変数

知ってたけど忘れてたものの一つ。

静的変数は初期化されなければ0で初期化される。

ついつい癖で明示的に0で初期化しちゃいます。

お、新しい関数発見。fill_n()。ちょっと使ってみよう。

#include "main.h"
#include <iostream>

using namespace std;

class Static1 : public BaseClass
{
	void update()
	{
		int dummy[100];
		fill_n(dummy, 100, 0);
		for( int i = 0; i < 100; ++i )
		{
			if( dummy[i] != 0 )
			{
				cout << "not zero:" << dummy[i] << endl;
			}
		}
	}
};

コンストラクタやらなんやらがなかったりするのを気にしたら負け。ちゃんと0に初期化されてました。fill_nはずすと・・・。

not zero:14
not zero:1378120
not zero:2088830565
not zero:27
not zero:3801464
not zero:3822296
not zero:3822208
以下同様

スコープ

スコープ解決演算子。名前知りませんでしたorz

リンケージ

リンケージ
ファイルを越えて利用できるかどうか。
外部でも利用できるものを外部リンケージを持つ、
内部のみのものを内部リンケージを持つという。
ローカル変数などはリンケージなし。

その昔望洋さんのC++本で覚えたんだけど、あんまり理解してなかったんでメモ。要約すると簡単だなぁ。

おー、extern出てきた。これいっつも見て見ぬフリしてたんで(ォィ)、この際だからしっかり覚えよう。

関数に外部リンケージを持たせるには戻り値の型にexternを加える。
ただし、externは省略可能。グローバル変数も同様。

ってことは暗黙的にいつもextern使ってたわけねorz。ただし、二重定義担っちゃう場合には話は別。その場合は明示的に変数をexternで修飾する。

変数宣言の前にexternがついている場合には初期化しない限りは変数の実体は作られず、
外部リンケージにその変数が定義されていることを示すようになる。

また、ローカル変数としてexternのついた変数は、
外部リンケージのグローバル変数を操作するためのもの。
ただし、そのexternがついた変数のスコープ自体はローカル変数のものと同じになる。

それと、関数プロトタイプは定義を兼ねていないので、関数内で宣言することができるらしい。ただし、応同名同型の関数プロトタイプ宣言や関数の実体定義があればそのリンケージを受け継ぐらしいです。前回の宣言が内部リンケージなら今回の宣言でexternと明示的に記述しても内部リンケージになるらしい。

逆に、変数に内部リンケージを持たせるためにはstaticで修飾してやる。うん、これは知ってた。

ちなみに、extern,static,auto,registerといったものを「記憶クラス指定子」というらしい。また、これらで決められるものをまとめて「記憶クラス」と呼ぶ。autoとregisterは後々説明があるらしいが、名前は聞いたことあるなぁ。内容は忘れちゃったぜ。

ついでに関数プロトタイプが関数内で宣言できるの例と内部リンケージをもつ関数を外部リンケージに書き直そうとしてみるの例。これであってるかな?
extern1.cpp

#include <iostream>
using namespace std;

static void Fuga();	// 内部リンケージ
extern void Fuga();	// 外部リンケージで宣言しなおしてみる
void Fuga()
{
	cout << "fuga" << endl;
}

int main()
{
	void Hoge(); // 関数内でプロトタイプ宣言
	Hoge();
}

extern2.cpp

#include <iostream>
using namespace std;

void Fuga();	// Fugaは内部リンケージ(リンクエラー)

void Hoge()
{
	cout << "hoge" << endl;
	Fuga();
}

リンケージは意外に手こずった!まぁこんなコード書くことってもうほとんどないと思うけど・・・。一応C使う時のために覚えとこう。