What exactly is the point of the construct std::observer_ptr in the library fundamentals technical specification V2?
It seems to me that all it does is wrap a bare <
Aside from the documentation use case, there are real world issues that can happen when passing around raw pointers without the observer decoration. Other code may incorrectly assume lifetime responsibility for raw pointers and pass the pointer into ownership taking std::unique_ptr
, std::shared_ptr
, or just plain dispose of the object via delete
.
This is especially true of legacy code that maybe being upgraded where ownership rules aren't fully established. The observer_ptr
helps enforce the rule that the lifetime of the object cannot be transferred.
Consider the following example:
#include
#include
struct MyObject
{
int value{ 42 };
};
template
void handlerForMyObj(T ptr) noexcept
{
if (42 != ptr->value) {
// This object has gone rogue. Dispose of it!
std::cout << "The value must be 42 but it's actually " << ptr->value << "!\n";
delete ptr;
return;
}
std::cout << "The value is " << ptr->value << ".\n";
}
void func1()
{
MyObject myObj;
MyObject *myObjPtr = &myObj;
myObj.value = 24;
// What?! Likely run-time crash. BOO!
handlerForMyObj(myObjPtr);
}
void func2()
{
MyObject myObj;
std::observer_ptr myObjObserver{ &myObj };
myObj.value = 24;
// Nice! Compiler enforced error because ownership transfer is denied!
handlerForMyObj(myObjObserver);
}
int main(int argn, char *argv[])
{
func1();
func2();
}
In the raw pointer case, the incorrect deletion of the object might only be discovered at runtime. But in the observer_ptr
case, the delete
operator cannot be applied to the observer.