NonNull template

Jonathan M Davis newsgroup.d at jmdavisprog.com
Sat Apr 19 10:35:01 UTC 2025


On Saturday, April 19, 2025 3:17:29 AM MDT Meta via Digitalmars-d wrote:
> On Saturday, 19 April 2025 at 06:05:53 UTC, Walter Bright wrote:
> > On 4/18/2025 12:21 AM, Ogion wrote:
> >> Isn’t `ref` essentially a non-null pointer?
> >
> > It's supposed to be. But you can write:
> > ```d
> > int* p = null;
> > ref r = *p;
> > ```
> > and you get a null ref.
>
> How is this possible? Shouldn't dereferencing p crash the program
> before r is initialized?

It doesn't, because nothing is actually dereferenced. This is like if you
have a null pointer to a struct and then call a member variable on it, e.g.

```
void main()
{
    S* s;
    s.foo();
}

struct S
{
    int i;

    void foo()
    {
    }
}
```

This does not crash, because s is never actually used. It's just passed to
foo. Of course, if you then changed foo to something like

```
void foo()
{
    import std.stdio;
    writeln(i);
}
```

it would crash, because then it would need to dereference s to access its i
member, but until it needs to access a member, there's no reason for any
dereferencing to take place.

The same happens with C++ classes as long as the function isn't virtual.

Where you _do_ get it failing in basically any language would be with a
class' virtual function, because the class reference needs to be
dereferenced in order to get the correct function.

This is one of those bugs that can be _very_ confusing if you don't think it
through, since you do naturally tend to assume that when you call a member
function, the pointer is dereferenced, but if the function isn't virtual,
there's no reason to dereference it to make the call. The funciton is just
passed the pointer or reference as in invisible argument. So, you can end up
with a segfault inside of your function instead of at the call site and get
rather confused by it. It's happened to me a couple of times in my career,
and it's initially been pretty confusing each time, even though after it was
explained to me the first time, I understood it, because you just tend to
think of calling a member function as derferencing the object even though it
it doesn't actually have any reason to do so unless the function is virtual.

And with

int* p = null;
ref r = *p;

no dereferencing occurs, because the compiler is converting int* to ref int,
and underneath the hood, ref int is just int*, so it's simply copying the
value of the pointer.

- Jonathan M Davis






More information about the Digitalmars-d mailing list