Uhm... try to use polymorphism without pointers. Ok, references, but how often do you see code like
Object& obj = *(new DerivedObject);
Not to mention the cleanup:
delete &obj;
Besides, there is no such thing as "smart references" to help you avoid memory leaks and accessing invalid objects. Apart from that, pointers and references have only a few differences under the hood. It's not like they are doing completely different things. References are more convenient in syntax and unless someone deliberately does something stupid you shouldn't have to worry about them being valid.
RAII examples? Sure. std::fstream, std::vector and pretty much anything that keeps track of its resources and releases them when going out of scope. Like scoped_lock or unique_ptr.
If the constructor and destructor is really empty, it has little to do with RAII. Apparently the object doesn't "acquire" any resources during initialization and has nothing to release on destruction. That would be like calling an empty chassis an example of a light weight car.
An example for RAII and smart pointers.
//without
char* tmpBuffer = new char[chunkSize];
mutex.lock();
loadData(tmpBuffer);
mutex.unlock();
delete[] tmpBuffer;
Oh no, loadData just threw an exception. I must ensure proper cleanup in all cases.
//without
char* tmpBuffer = new char[chunkSize];
mutex.lock();
try
{
loadData(tmpBuffer);
}
catch (...) //and I don't really know what kind of exception to expect
{
mutex.unlock();
delete[] tmpBuffer;
}
mutex.unlock();
delete[] tmpBuffer;
How about doing it the smart way (without a mess)?
vector<char> tmpBuffer(chunkSize);
scoped_lock lock(mutex);
loadData(&tmpBuffer[0]);
See? No cleanup, no mess to deal with exceptions, no chance of someone screwing it up by spamming early returns all over your function.