Some time ago, I decided strictly following the rule to check each pointer before dereferencing it the first time in a scope, I also changed pointers to references where appropriate: in some cases statically in the code base, in some cases dynamically (after asserting the pointer isn't null of course). This finally led to code like this:
std::string LoadText0(const std::string& fileName)
{
TStrings& lines = *new TStringList;
lines.LoadFromFile(fileName.c_str());
std::string result = lines.Text.c_str();
delete &lines;
return result;
}
...which I don't really "like", but it's consistent with the above rule, because I don't care failing news at all: I assure it to throw an exception based on compiler settings.
But: this code is far from being exception-safe. Since the static analysis tool Cppcheck has an issue in the current version 1.65, stating that I try to delete an auto-variable which causes undefined behaviour, I found the lack of exception-safety worth rewriting the code, now I'm using std::auto_ptr
.
But now, I dislike all the ->
operators: they give the false feeling that the pointers are optionally assigned. This look is especially a problem when the scope gets larger, and it's also a lot of work to rewrite all dots to arrows.
std::string LoadText1(const std::string& fileName)
{
std::auto_ptr<TStrings> lines(new TStringList);
lines->LoadFromFile(fileName.c_str());
std::string result = lines->Text.c_str();
return result;
}
So I tried to figure out a solution that combines the best from the two worlds and this is what I found (with the downside of two "access points" to the same object)
std::string LoadText2(const std::string& fileName)
{
std::auto_ptr<TStrings> plines(new TStringList);
TStrings& lines = *plines;
lines.LoadFromFile(fileName.c_str());
std::string result = lines.Text.c_str();
return result;
}
Is this overkill in your eyes? Would you consider it to be idio(ma)tic?