こんにちは、
シゲチィです。
ラボでは隅っこによくいます。最近、風邪こじらせてマスクしてるメガネ野郎です。
2年生はC言語からステップアップしてC++を勉強していると思います。
今回はC++の機能の一つ、参照の落とし穴について紹介したいと思います。
[0回]
参照についての説明は省きます。各自で調べてください。
先日、次のような構造体を作った時の失敗について、紹介します。
sturct RGBA : public DirectX::XMFLOAT4
{
float& r; // 赤
float& g; // 緑
float& b; // 青
float& a; // アルファ
// コンストラクタの初期化子で参照を初期化。
RGBA() : r(x), g(y), b(z), a(w)
{
}
};
4Dベクトルのメンバを(XMFLOAT4にはx,y,z,wがメンバで含まれます。)を
r,g,b,a(カラー値)で
使えるようにしようとした構造体です。
この構造体を作ったときは、RGBAで指定できるようになったぞと安易に思っていたのですが、
次の処理を行ったときにそれは起きました。
RGBA rgba;
ZeroMemory(&rgba, sizeof(rgba));
rgba.r = 1.0f;
rgba.g = 1.0f;
rgba.b = 1.0f;
rgba.a = 1.0f;
この処理を見てすぐ気付いた方はもうこの記事を閉じてもらって大丈夫です。
参照の正体を理解しているということですから。
さて、なにが起こったかというと...
3行目で実行時にエラーが発生してしまうのです。
理由はアクセス違反。r,g,b,aはXMFLOAT4の
x,y,z,wを指しているのになぜなのでしょう。
実は原因は2行目の「ZeroMemory(~);」にあったのです。
RGBA構造体をバイト単位でゼロクリアしたことにより、
r,g,b,aの
参照アドレスが
0番地になってしまっているのです(&rgba.rをすると0が取得できます)。
つまり、参照の正体はポインタのように参照先のアドレスを保持しているということ。
(このことについては
ロベールのC++教室で解説されていました。)
「参照≒ポインタ」を直に感じれた失敗でした。いい経験になった・・・(しみじみ)。
みなさんは大丈夫だと思いますが、このような参照の使い方はやめましょう。
(※参照は参照先を初期時でないと指定できないため。ダウンキャストなどが危ない。)
ちなみにポインタ同様、参照をメンバにすると、
4バイトずつその分の容量も食います(構造体だとアライメント次第でどんどん肥大することも)。
これもやる内容によってはバグの原因になります(
私はなりました)。
以上で今回の内容は終わりです。
長々として、ためにならなかったかな?っていう記事でしたが、
次はためになる記事になるよう努力します。
でもたまに、こういうトリビア的な内容も書いたりします。
なにか他に知りたいことがあれば、だいたいラボの隅っこにいますので、声かけてください。
PR
COMMENT