読者です 読者をやめる 読者になる 読者になる

t-homさんが直近の記事でByRef As Variantで受けたときにアドレスが変わる事象について仮説を書いている。

thom.hateblo.jp

型一致参照であるShowPtr関数とVariant参照であるShowPtr2関数を作って比較し

ShowPtr2でVarPtr(IntArg)としたときは、Variant変数自体のアドレス1373176が表示されるが、Variant変数は内部で137362へのポインタを保持しているということだろう。

と結論付けているが、おおむね正しいと思う。


ただ、ByRef x As Variant としたときの x はいったい何者なのかと考えるとちょっと気持ち悪くて、引数の型によって参照だったり実体だったりするのではなくて、そもそも別々のものだと考えたほうがわかりやすいと感じた。
型一致参照であるShowPtr関数の挙動は明らかなので、ShowPtr2関数については疑似的にこういうふうに解釈すればいいんだと思う。

#include <iostream>

struct Variant {
    void* p;
    Variant() : p(nullptr)   { }
    //いろいろ省略
    template <typename T>   // 他の型で初期化するコンストラクタ
        Variant(T& t) : p(static_cast<void*>(&t))   { }
};

//Byref As Variant相当 実引数がVariantの場合 → 本当の参照
void ShowPtr2(Variant& v)
{
    std::cout << "varArg:" << &v <<std::endl;
}

//Byref As Variant相当 実引数がVariant以外の場合
template <typename T>
void ShowPtr2(T&& x)
{
    Variant v(x);    //→ 新たにVariant変数を作成
    std::cout << "intArg:" << &v <<std::endl;
}
 
int main()
{
    Variant varArg;
    int intArg = 0;
    std::cout << "-----------初期アドレス------------" <<std::endl;
    std::cout << "varArg:" << &varArg <<std::endl;
    std::cout << "intArg:" << &intArg <<std::endl;
    std::cout << "-----------Variant参照------------" <<std::endl;
    ShowPtr2(varArg);   // この ShowPtr2 と
    ShowPtr2(intArg);   // この ShowPtr2 は別物
}
-----------初期アドレス------------
varArg:0x7ffe5587a6e8
intArg:0x7ffe5587a6e4
-----------Variant参照------------
varArg:0x7ffe5587a6e8
intArg:0x7ffe5587a690