" I read about stackoverflow in many posts that when using a pointer (for an argument or return value) and nullptr (which makes it optional), it is generally better to use std::optional .
Presumably, you mean using std::optional to wrap a value other than a pointer or reference. In this case, you are talking about an optional argument or an optional return value .
Using optional for an optional argument has the disadvantage that the object is being copied, or at least moved, which may be undesirable. In addition, this eliminates polymorphism.
The easiest way to do this, which also avoids unnecessary copying and supports polymorphism, is to use a pointer to const :
void foo( Some_type const* p_object )
But then the caller will need to use the & operator for the actual argument.
To simplify calls, you can provide overload as syntactic sugar:
void foo() { foo( nullptr ); } void foo( Some_type const& object ) { foo( &object ); }
which supports type calls
foo();
and
foo( o );
Using optional for the return value has the advantage that a throw exception can be avoided when the calling code correctly checks for the value. But it apparently excludes the usual RVO (return value optimization) for the wrapped object - the affectionate word βappearsβ because I cannot see this harmless proof of this, but still I do not see how RVO can be done. Therefore, when a case without a return value is rare, and / or efficiency is very important, it is best to simply throw an exception. C ++ only supports (raw) pointers and references for polymorphic return values, and there is no difference in this respect between using optional and throwing an exception so as not to indicate the return value.
For a polymorphic optional return value, you can use a smart pointer such as std::unique_ptr or std::shared_ptr , which handles ownership.