参照型変数-4

参照型変数-2で、参照型変数とポインタはそれほど変わらないという結論を導きましたが、この発言は撤回させていただこうと思います。

参照が明確にポインタと異なる点、演算子のオーバーロードが使えるかどうかですが、これは可読性や記述の容易さに大きな影響を与えそうだということに気がつきました。例をいくつか挙げるので、比較してみましょう。

'参照
Dim obj1 As Object
Dim obj2 As Object
If obj1 = obj2 Then ...
Else ...
End If
'ポインタ
Dim obj1 = New Object As *Object
Dim obj2 = New Object As *Object
If obj1->Equals(obj2) Then ...
Else ...
EndIf

Equalsはまだいい方です。Compareはどうでしょう?

'参照
Dim obj1 As Object
Dim obj2 As Object
If obj1 > obj2 Then ...
Else ...
End If
'ポインタ
Dim obj1 = New Object As *Object
Dim obj2 = New Object As *Object
If obj1->Compare(obj2) > 0 Then ...
Else ...
EndIf

ちょっと読みづらくなりませんか?また、加算を考えてみましょう。例えばStringの文字列結合処理です。

'参照
Dim s1 As String
Dim s2 As String
s1 = s1 + s2
'ポインタ
Dim s1 = New String As *String
Dim s2 = New String As *String
s1 = s1->AppendingText(s2)

他にも、こういうこともあります。

'参照
Dim s1 As String
MessageBox(0, s1, "参照", MB_OK)
'ポインタ
Dim s1 = New String As *String
MessageBox(0, s1->GetButes, "ポインタ", MB_OK)

こういうわけで、演算子のオーバーロードもなかなか馬鹿にできません。ポインタより参照型変数の方が、若干使いやすさは上回るでしょう。

コメント

  1. tak より:

    参照が明確にポインタと異なる点 => 演算子のオーバーロードが使えるかどうか

    確かにポインタは内部的には数値として扱われますから直接的に演算子オーバーロードはできませんが、ポインタをたぐり寄せることでオーバーロードされた演算子を利用することができます。
    C++言語に似せて同じ例を記述すると、こんなかんじ。

    Object *obj1 = new Object;
    Object *obj2 = new Object;
    if (*obj1 > *obj2) {…}

    ABでは少しひねる必要がありますけど、一応できそう。

    Dim obj1 = New Object As *Object
    Dim obj2 = New Object As *Object
    If obj1[0] > obj2[0] Then …

    ・・・参照のほうが見た目が素直ですね。
    ABにも間接参照演算子(*)があればなぁと思う今日この頃。

  2. tak より:

    C++にも参照があることを思い出しました。
    積極的に使われているところを見たことはありませんけど。

    Object &obj1 = *new Object;
    Object &obj2 = *new Object;
    if (obj1 > obj2) {…}

    これだと、ポインタをたぐり寄せる * が消えてすっきりしますね。

  3. OverTaker より:

    なるほど、そういうものもあるのですか。でも、あまり良いものとは言えませんね。わざわざそうするのなら、演算子のオーバーロードを使わなくてもいいですね。C++の方は….どちらにしろ今のABでは無理ですね。

  4. イグトランス より:

    C++/CLI (C++を.NETに対応させた言語)では、従来のポインタ *と参照 &はそのままに、CLRでGC管理されるオブジェクトに対してのポインタと参照にあたるトラッキングハンドル ^とトラッキング参照%が追加されました。トラッキングハンドル型のオブジェクトに間接参照演算子(単項*)を適用するとトラッキング参照が得られますし、メンバへのアクセスには->を使いますが、演算子多重定義できるという言語仕様になっています。
    Object^ o1 = gcnew Object;
    Object^ o2 = gcnew Object;
    Object% r2 = *o2;
    o1->ToString(); (*o2).ToString(); r2.ToString();
    if (o1 > o2) {…} //実際のSystem::Stringに>演算子は定義されていませんが
    if (*o1 > o2) {…} //もし演算子関数が定義されていれば自動的にこれもできるようになっていたはず
    ちなみにトラッキングハンドルはポインタと言わないだけあってポインタ演算はできず、加減算や添え字演算子を使用した場合、演算子多重定義されていなければコンパイルエラーになります。(しかし間接参照演算子は警告付きながら定義できてしまうという混沌な世界です)

コメント投稿