| |
 | Posted by Jonathan M Davis in reply to Meta | Permalink Reply |
|
Jonathan M Davis 
| 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
|