Const is documentation as much as it is a compiler directive, so all code should strive to be const-correct.
- Passing function arguments by const pointer or reference if those arguments are not intended to be modified by the function,
- Flagging methods as const if they do not modify the object,
- and using const iteration over containers if the loop isn't intended to modify the container.
void SomeMutatingOperation(FThing& OutResult, const TArray<Int32>& InArray)
// InArray will not be modified here, but OutResult probably will be
void FThing::SomeNonMutatingOperation() const
// This code will not modify the FThing it is invoked on
for (const FString& : StringArray)
// The body of this loop will not modify StringArray
Const should also be preferred on by-value function parameters and locals. This tells a reader that the variable will not be modified in the body of the function, which makes it easier to understand. If you do this, make sure that the declaration and the definition match, as this can affect the JavaDoc process.
void AddSomeThings(const int32 Count);
void AddSomeThings(const int32 Count)
const int32 CountPlusOne = Count + 1;
// Neither Count nor CountPlusOne can be changed during the body of the function
One exception to this is pass-by-value parameters, which will ultimately be moved into a container (see "Move semantics"), but this should be rare.
void FBlah::SetMemberArray(TArray<FString> InNewArray)
MemberArray = MoveTemp(InNewArray);
Put the const keyword on the end when making a pointer itself const (rather than what it points to). References can't be "reassigned" anyway, and so can't be made const in the same way.
// Const pointer to non-const object - pointer cannot be reassigned, but T can still be modified
T* const Ptr = ...;
T& const Ref = ...;
Never use const on a return type, as this inhibits move semantics for complex types, and will give compile warnings for built-in types. This rule only applies to the return type itself, not the target type of a pointer or reference being returned.
// Bad - returning a const array
const TArray<FString> GetSomeArray();
// Fine - returning a reference to a const array
const TArray<FString>& GetSomeArray();
// Fine - returning a pointer to a const array
const TArray<FString>* GetSomeArray();
// Bad - returning a const pointer to a const array
const TArray<FString>* const GetSomeArray();