How do I correctly use pointers in this situation?

Hello.

I’m desperately trying to remember C++ right now and I have stumbled across this problem.

I’m trying to deserealize data from JSON for which I am using UE4 libraries.

Consider the signature for the FJsonObject::TryGetArrayField method that I am trying to use:

bool TryGetArrayField
(
    const FString & FieldName,
    const TArray < TSharedPtr < FJsonValue > > *& OutArray
)

This code works if I pass a variable declared as const TArray<TSharedPtr<FJsonValue>> *OutArray as the second parameter, but leaves me wondering about 2 things:

  1. Isn’t there a better way to use pointers in case of “OutArray” variable? Can I avoid using the native const “*” pointer here and use a smart pointer instead? Using TSharedPtr<TArray<TSharedPtr<FJsonValue>>> OutArray gives me compile time errors about assigning temporary object to a reference.

  2. Why does trying to delete “OutArray” pointer later on gives me an exception at runtime? Does that mean UE4’s GC manages this pointer for me? How can I be aware if data reference by “*” pointer is managed by GC if it’s not an explicit “UPROPERTY()”?.

Thanks in advance.

1 Like

I have the exact same question…

OutArray should just be a reference to a pointer that is pointing to a const TArray.

So if I pass in a const TArray<TSharedPtr<FJsonValue>> *myOutArray to FJsonObject::TryGetArrayField, when it returns myOutArray will be pointing to memory somewhere. Who’s managing that memory?

Maybe I just suck at C++ and I’m missing something?

1 Like

A little late to the ball, but I found and answer and thought I’d share in case anyone else finds it useful in the future.

FJsonObject::TryGetArrayField() returns a pointer to the FJsonObject’s internal array of type TArray<TSharedPtr<FJsonValue>>.

If you wanted to iterate through the returned array from its pointer, you just have to dereference the pointer. It would look something like this:

const TArray<TSharedPtr<FJsonValue>> *MyJsonArray;
if (MyJsonObject.JsonObject->TryGetArrayField("MyArray", MyJsonArray) != true)
{
    // error
}
for (TSharedPtr<FJsonValue> MyJsonArrayValue: *MyJsonArray)
{
    // do something
}

And just to answer to this: TSharedPtr is managing the memory, because it’s a smart pointer.

As you can see in the documentation:

A Shared Pointer owns the object it references, indefinitely preventing deletion of that object, and ultimately handling its deletion when no Shared Pointer or Shared Reference references it. A Shared Pointer can be empty, meaning it doesn’t reference any object. Any non-null Shared Pointer can produce a Shared Reference to the object it references.