Pointers Passed in As Out Parameters Come Out NULL

Dear Friends At Epic,

I am not calling this a bug so much as I am requesting undestanding.

I want to pass in two pointers, only 1 of which will get an actual value, so that’s why I am using them in out parameter fashion.

Neither of them ever get filled, it is only when I return the pointer value that it gets passed back to the calling context.

//returns a Evolver or an Ineff, only 1 will be valid
AActor* AVictoryGRI::GetCreatureWithVibe(int32 TheVibe, AEvolver* TheEvolver, AIneff* TheIneff)
{
	//Reset
	TheEvolver = NULL;
	TheIneff = NULL;
	//~~~~~~~~~~~~
	
	//search Evolvers
	for ( TObjectIterator It; It; ++It )
	{
		if(It->Vibe == TheVibe)
		{
			TheEvolver = *It;		//found!
			VictoryPC->OptInt("VGRI FOUND THE VIBE Searched For", TheVibe);
			VictoryPC->Optimize(TheEvolver->GetName());
			return *It;
			//~~~~~~~~
		}
	}
	
	//Search Ineffs
	for ( TObjectIterator It; It; ++It )
	{
		if(It->Vibe == TheVibe)
		{
			TheIneff = *It;		//found!
			return *It;
			//~~~~~~~~
		}
	}
	
	return NULL;
}

#My Assumption

I am assuming then that I cannot pass in pointers as out parameters to be given values?

:slight_smile:

Rama

Hi Rama – this is really a C++ question, not a UE4 question.

The bottom line is that the way you’ve written it, it only changes the value of the passed-in parameter locally to the function. Once you pass a parameter, that parameter becomes essentially indistinguishable from a local variable unless you pass it by reference, which you haven’t.

To fix it, you need to either pass a pointer to a pointer, or pass in a reference to a struct/class with a pointer member, or return such a struct.

I.e. you could do it this way:

AActor* AVictoryGRI::GetCreatureWithVibe(int32 TheVibe, AEvolver** ppEvolver, AIneff** ppIneff) {...}

and set them as

*ppEvolver = *It; // found!

and

*ppIneff = *it; // found!

That would change the pointed-to object (the actual pointer, since they’re passed as a pointer to a pointer).

A better way to do it would be to add some typedefs, like this:

typedef AEvolver* TEvolverPtr;
typedef AIneff* TIneffPtr;

and then change your function to pass in non-const references to those pointer typedefs:

AActor* AVictoryGRI::GetCreatureWithVibe(int32 TheVibe, TEvolverPtr & TheEvolver, TIneffPtr & TheIneff) {...}

… and then leave the rest of your function the same.

That should definitely work, and you won’t even have to change the way it’s called.

On the other hand, it might be cleaner to make your own custom data structure with two pointers in it, and return that instead.

Thanks for taking the time to lay that all out!

Sounds like there are several options :slight_smile:

I am curious how Epic tends to hand such situations :slight_smile:

Rama

ps: tho I am waiting for Epic’s answer before greening this, I am 1-upping your answer, again thanks for the info :slight_smile:

They got to the right answer before me :slight_smile:

Yes, this is a C++ question and what you are looking for is to understand “pass by reference”. Typically this is parameters of the form int& A. In your case you want a pointer to change on the inside so int*& A. They clean that syntax up a little bit above with the typedef, but it’s all the same.

On this theme int** A is also effective. “A pointer to a pointer”, so the “copy” is of the double pointer. Inside the function you dereference the internal pointer and change it’s data so that when the function returns the data inside has changed.

Passing in a structure by reference that has internal pointers is also ok.

As for the “Epic Way” there isn’t really a right answer, it all depends on what you are trying to do. I wouldn’t say there are any real differences in your choices unless you want to talk about the assembly generated or how registers get involved, but that’s probably not an optimization that needs to be made.

Dear Josh,

Thank you for expanding on Mothership’s answer!

You both have helped me very much with this topic :slight_smile:

#:heart:

Rama

As far as I know, there is nothing stopping you from passing a pointer as a reference and using it as an out-parameter.

Let’s say we wanted to write a function for a class inheriting from USceneComponent that saves the owning Actor to an out parameter. In the function definition you would simply append & to the class specification (AActor *) of the parameter like so:

void UMySceneComponent::SaveComponentOwner(AActor *& OutOwnerActor)
{
    AActor* CurrentOwer = GetOwner();
    OutOwnerActor = CurrentOwner;
}

You can then call the function in BeginPlay like so:

void UMySceneComponent::BeginPlay()
{
    Super::BeginPlay();

    // Save the current owner to MyOwner
    AActor* MyOwner = nullptr;
    SaveComponentOwner(MyOwner);

    // Check to ensure the pointer is not null
    if(MyOwner)
    {
        UE_LOG(LogTemp, Warning, TEXT("My owner is: %s"), *MyOwner->GetName());
    }
}

Now this has been working for me as of version 4.19 (earliest checked) and I’ve never had issues. However, it might not be recommended by Epic or could cause problems down the line, I don’t know.