I want to return an invalid reference in this function.
Something that I can then check using IsValid() for example.
These returns only work for pointers. (NULL, nullptr, 0)…
Any way to do it?
Thank you so much!!
I want to return an invalid reference in this function.
Something that I can then check using IsValid() for example.
These returns only work for pointers. (NULL, nullptr, 0)…
Any way to do it?
Thank you so much!!
Because FUniqueNetIdRef
is a reference to an ID, you should return an empty reference.
Because FUniqueNetIdRef
has virtual functions, if you want to call IsValid()
on it, you have to have a concrete instance. You’ll need to see if the particular subsystem has a way to manufacture such an ID, if that’s what you want.
But, in this case, just return FUniqueNetIdRef()
as an empty/invalid value.
Like this?
return FUniqueNetIdRef();
The compiler gives an error if I do it like this.
C2259 “FUniqueNetId”: Cannot instantiate an abstract class.
Thank you very much for your help!!
What do you think about this way?
I got the compiler to not give me errors like this…
FUniqueNetIdRef *nullref=nullptr;
return *nullref;
I haven’t tried it yet. Maybe it crashes. I’ll see what happens if I use it.
It doesn’t work either!! it crashes!!
Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x0000000000000000
Hi, @Ivan3z When you want to work with references, you usually make a function like
bool GetSomething(something& smth)
you initialize a variable before function then call the function, by passing the variable in the function. Because it is passed by reference, everything you do in function is changing the variable also out of scope of the function. And then you check, if the function did what you wanted it to do (it does not have to be only IsValid
) and that’s it. I usually prefer to check it like this:
if (CheckSomething(smth))
{
// TODO
}
It is not concerning Unreal Engine, just code in general, good practice I would say.
Yes, I know I can’t return the address of a local variable.
The problem is that I can’t instantiate an abstract class.
The only way to get an instance of the class is using this.(I think).
(I think it must be a static class, a singleton pattern or something like that)
ToSharedRef()
I was looking at how it was done.
And I was also looking at how the standard class works
https://en.cppreference.com/w/cpp/memory/shared_ptr
With the standard class you can return a null pointer like this.
std::shared_ptr (nullptr)
But this way doesn’t work with TSharedRef.
For now I think the easiest way is to simply return the pointer.
and then get the reference.
At least it saves me typing that monstrosity every time I want to get the pointer.
Well, it’s a shame can’t be returned the reference directly from the function. Everything would have been more comfortable.
Thank you so much for your help!!
Really very much appreciated!!
Sorry – I missed that the FUniqueNetIdRef
was a TSharedRef
. TSharedRef
is not nullable.
Thus, my expectation is that the if()
statement won’t ever test true – a TSharedRef
is never == nullptr
.
And, if it were, why wouldn’t you just return localUserIdPtr
that you have right there?
Mea culpa: I thought it would be very convenient to do all the validations in the same function and return the reference.
And that maybe there was some way to return a null reference. And handle it somehow, or catching the exception if necessary.
This is because I am very used to working with pointers, very little used to working with references.
It is the baggage I have from my first programming language, the ANSI standard C. I always thought that anything could be programmed using only pointers. When I learned some C# I almost had a heart attack XD.
Despite the fact that I have been learning C++ for 20 years, every day I learn something new.
Well, today I learned that references cannot be null.
Yes, you are right. Definitely the best solution was to return the pointer itself.
Thank you very much for your help!!
Very much appreciated!!
references cannot be null
well …
don’t tell anyone:
int * someglobal = nullptr; // to avoid flow analysis proving it's NULL
int & undefined_behavior_reference() {
return *someglobal; // most compilers won't generate code that crashes here
}
Under the covers, a reference is just a pointer. But they’re not supposed to be NULL – if you make one that is NULL, somehow (like the above code,) then that’s “undefined behavior.” Unfortunately, compilers aren’t required to detect and warn/error on undefined behavior; they are allowed to optimize assuming that nothing you do is undefined behavior. This is a common source of security flaws in C/C++ code.
The code above will probably not crash when called, but instead, it will crash when you try to use the reference.
What’s extra … delicious … in this case is that the Unreal template uses a pointer internally, it’s just coded to always make a non-null value in the constructor, and blow up if you try to assign null to it.
The constructor of FUniqueNetId
is protected because of Online Subsystem shenanigans. You can return an empty unique id like this:
static FUniqueNetIdRepl EmptyId;
return EmptyId;
I always imagined of references as a nice hexadecimal number that marked the position of a specific byte in memory. Something static. Something like a hotel room.
And the pointer is something dynamic that allows you to take a walk through all the rooms in the hotel.
From this perspective a four byte integer actually has four references.
So the pointer points to the first bytes. And you can read/write structured byte blocks.
Thank you very much for your help!!
Unfortunately in this specific case this way does not work because it is an abstract class. i just tried it.
Thanks for your help!!
If you do mean FUniqueNetIdRepl
, is the idea that that class has an implicit conversion to FUniqueNetIdRef
?
I’m not finding one.
Or is the idea to use FUniqueNetIdRepl
instead, in places where a FUniqueNetIdRef
are currently used?
It seems to deal with FUniqueNetIdPtr
instead, which can be null, so maybe that’s why it’s an alternative?
My bad, I didn’t see that he wants to return an FUniqueNetIdRef
. I’m not too familiar with smart pointers but i believe this would work.
static FUniqueNetIdRepl EmptyId;
const FUniqueNetIdPtr& EmptyIdPtr = EmptyId.GetUniqueNetId();
return EmptyIdPtr->AsShared();
The FUniqueNetIdRepl
type is a wrapper class that contains an FUniqueNetIdPtr
. The other unique net id types are just forwards:
// CoreOnlineFwd.h in UE5
using FUniqueNetIdPtr = TSharedPtr<const FUniqueNetId>;
using FUniqueNetIdRef = TSharedRef<const FUniqueNetId>;
using FUniqueNetIdWeakPtr = TWeakPtr<const FUniqueNetId>;
It compiles fine. But then it crashes when you use it.
I think someone designed it with the intention that it’s not possible to do this.
At least we tried!!
Thank you so much!!
Indeed. The intention seems to be that, if you have a Ref
then you know it’s good.
So the initial test for nullptr
above isn’t ever necessary – it won’t ever be the case.
Which, once you’re in this situation, you’re good! You know it’s never bad.
It’s almost like a strong memory model language (well, a little bit)