Given the new toolset provided by c++ lots of programmers, aiming at code simplification, expressiveness, efficiency, skim through their old code and make tweaks (some pointless, some successful) to achieve their goals. Whilst trying not to loose too much time on such labors and just make non intrusive and self contained changes, what are the best practices?
Let me cross out the obvious :
Use auto to run iterator based loops :
for (std::vector<foo>::const_iterator it(lala.begin()), ite(lala.end()); it != ite; ++it); // becomes for (auto it(lala.cbegin()), ite(lala.cend()); it != ite; ++it);
Use tie for multiple assignments that just produce C-style rows of code ( how to assign multiple values into a struct at once? )
a = 1; b = 2; c = 3; d = 4; e = 5; // becomes std::tie(a, b, c, d, e) = std::make_tuple(1, 2, 3, 4, 5);
To make a class non inheritable just declare it as "final" and delete the code that achieved such a behavior http://www.parashift.com/c++-faq/final-classes.html
Use the delete keyword to explicitly hide constructors/destructors instead of declaring them private (eg code to create heap based objects, non copyable objects etc)
Turn trivial functors created just to facillitate the execution of a single STL algorithm into lambda functions (apart from reducing code cluttering you'll have guaranteed inlined calls)
Simplify RAII wrapping of an object by just using a smart pointer
Get rid of bind1st, bind2nd and just use bind
Replace hand written code for type traits (Is_ptr_but_dont_call_for_const_ptrs<> and such :) ) with standard code provided by < type_traits >
Stop including boost headers for functionallity now implented in STL (BOOST_STATIC_ASSERT vs static_assert)
Provide move semantics to classes (although this wouldn't qualify as a dirty/quick/easy change)
Use nullptr where possible instead of the NULL macro and get rid of the code that filled containers of pointers with 0's casted to object type
std::vector<foo*> f(23); for (std::size_t i(0); i < 23; ++i) { f[i] = static_cast<foo*>(0); } // becomes std::vector<foo*> f(23, nullptr);
Clear the vector data accessing syntax
std::vector<int> vec; &vec[0]; // access data as a C-style array vec.data(); // new way of saying the above
Replace throw() with noexcept (apart from avoiding the deprecated exception specifiation you get some speed benefits http://channel9.msdn.com/Events/GoingNative/2013/An-Effective-Cpp11-14-Sampler @ 00.29.42)
void some_func() noexcept; // more optimization options void some_func() throw(); // fewer optimization options void some_func() ; // fewer optimization options
Replace code where you'd push a tempory in a container and hoped that the optimizer would ellide the copy away, with an "emplace" function where available, in order to perfectly forward the argument and construct directly an object into a container without temporary at all.
vecOfPoints.push_back(Point(x,y,z)); // so '03 vecOfPoints.emplace_back(x, y, z); // no copy or move operations performed
UPDATE
The answer by Shafik Yaghmour was rightfully awarded the bounty for having the greatest acceptance by the audience.
The answer by R Sahu was my accepted one, because the combination of features it proposes captures the spirit of refactoring : making code clearer and cleaner and simpler and elegant.
.data()
instead of&container[0]
. It will NOT work forstd::string
if you wish to modify the internal data. Why because.data()
forstd::string
is the same as.c_str()
and returns a constant pointer. Also for MSVC2013,push_back
takes aT&&
and is the same asemplace_back
. – Amarillasoverride
to indicate that a function overrides a virtual function in base class instead of introducing a new one/hiding function in base class. Also I would advise against making every class you can a final. It should be used sparingly, because it can make testing the code more painful than it has to be. – Eitenvector
data access worked well enough earlier, the same way as now guaranteed forstd::string
, so no reason to usedata()
at all. Also, they could have madeNULL
better instead of introducing the longernullptr
. There's a useless difference to C. – Dorise