If by "better approach" you mean "safer approach", then yes, I've implemented a "non-owning" smart pointer here: https://github.com/duneroadrunner/SaferCPlusPlus. (Shameless plug alert, but I think it's relevant here.) So your code would look like this:
#include "mseregistered.h"
...
class foo{
public:
mse::TRegisteredPointer<bar> pntr;
};
int main(){
mse::TRegisteredObj<bar> a;
foo b;
b.pntr=&a;
}
TRegisteredPointer is "smarter" than raw pointers in that it knows when the target gets destroyed. For example:
int main(){
foo b;
bar c;
{
mse::TRegisteredObj<bar> a;
b.pntr = &a;
c = *(b.pntr);
}
try {
c = *(b.pntr);
} catch(...) {
// b.pntr "knows" that the object it was pointing to has been deleted so it throws an exception.
};
}
TRegisteredPointer generally has lower performance cost than say, std::shared_ptr. Much lower when you have the opportunity to allocate the target object on the stack. It's still fairly new though and not well documented yet, but the library includes commented examples of it's use (in the file "msetl_example.cpp", the bottom half).
The library also provides TRegisteredPointerForLegacy, which is somewhat slower than TRegisteredPointer but can be used as a drop-in substitute for raw pointers in almost any situation. (In particular it can be used before the target type is completely defined, which is not the case with TRegisteredPointer.)
In terms of the sentiment of your question, I think it's valid. By now C++ programmers should at least have the option of avoiding unnecessary risk of invalid memory access. Raw pointers can be a valid option too, but I think it depends on the context. If it's a complex piece of software where security is more important than performance, a safer alternative might be better.