Another before and after snippet is related to accessing associative containers.
I recently saw some code and was reminded of an example by presented at CppCon 2014 Talk by Chandler Carruth.
Below is the original code:
std::unordered_map<int, MyClass> myContainer;
// ...
void invokePattern1(const int key)
{
myContainer[key].invokeA();
myContainer[key].invokeB();
myContainer[key].invokeC();
myContainer[key].invokeD();
}
Improved version
After I watched the talk I felt the need to improve it to this:
std::unordered_map<int, MyClass> myContainer;
// ...
void invokePattern1(const int key)
{
auto& accessedElement = myContainer[key];
accessedElement.invokeA();
accessedElement.invokeB();
accessedElement.invokeC();
accessedElement.invokeD();
}
By just accessing the container once we reduce the number of calls to the containers [ ] operator. This reduces the amount of computation we have to do per invokePattern call.
Why not make invokePatternA a member function?
You may think that a better way to restructure that would be to encapsulate the calls to the invoke member functions in one single invokePattern member function of MyClass all together:
void invokePattern1(const int key) // Possible improvement
{
// Just forward the call to MyClass
myContainer[key].invokePattern1();
}
But what if you need another pattern, that MyClass cannot know (and does not care) about right now:
void futurePattern(const int key)
{
myContainer[key].invokeA();
myContainer[key].invokeA();
myContainer[key].invokeB();
myContainer[key].invokeB();
}
The more functions can access private parts of a class, the greater its encapsulation. If you’d add another invokePattern1 member you would increase that number and decrease encapsulation.
Of course you could make all invokeA, B, C, D member private after you have written your new invokePattern1 member, but that will cause a change every time a caller might need a new pattern. That will drastically decrease the classes flexibility and is probably not what you want.
See a full explanation of why to not make the change from a non-member (non-friend!) function to a member function in Item 23 of Scott Meyer’s Effective C++.