meyers-effective-cpp
Scott Meyers Style Guide
Overview
Scott Meyers authored the definitive "Effective" series—books that distilled C++ wisdom into actionable items. His approach: specific, numbered guidelines with clear rationale. Not language rules, but hard-won practical wisdom.
Core Philosophy
"Good interfaces are easy to use correctly and hard to use incorrectly."
"More than any other language, C++ rewards a deep understanding of how things work."
Meyers believes in understanding why, not just what. Every guideline has a reason; every reason teaches something about C++.
Design Principles
-
Make Interfaces Easy to Use Correctly: The right thing should be the obvious thing. Wrong usage should fail to compile or be obviously wrong.
-
Prefer Compile-Time Errors: A compile error is infinitely better than a runtime bug.
-
Understand What C++ Silently Generates: Default constructors, copy operations, destructors—know when they're generated and what they do.
-
Minimize Dependencies: Reduce coupling between components. Compilation dependencies are real costs.
When Writing Code
Always
- Declare destructors virtual in polymorphic base classes
- Have
operator=return*thisfor chaining - Handle self-assignment in assignment operators
- Ensure objects are fully initialized before use
- Prefer
const,enum,inlineto#define - Use
constwherever semantically meaningful - Initialize members in declaration order in initializer lists
- Make non-member functions when it improves encapsulation
Never
- Let exceptions escape destructors
- Call virtual functions in constructors or destructors
- Return handles (references, pointers) to object internals casually
- Define non-member functions that should be members
- Write functions that take
const T*when they should takeconst T&
Prefer
- Initialization over assignment (especially for objects)
++ioveri++(unless postfix semantics needed)- Declaring single-argument constructors
explicit - Non-member non-friend functions over member functions for algorithms
- Empty base optimization over composition for policies
Code Patterns
Item 18: Make Interfaces Easy to Use Correctly
// BAD: Easy to use incorrectly
Date(int month, int day, int year); // Date(3, 30, 2024) or Date(30, 3, 2024)?
// GOOD: Type system prevents mistakes
class Month {
public:
static Month Jan() { return Month(1); }
static Month Feb() { return Month(2); }
// ...
private:
explicit Month(int m) : val_(m) {}
int val_;
};
class Day {
public:
explicit Day(int d) : val_(d) {}
int value() const { return val_; }
private:
int val_;
};
class Year {
public:
explicit Year(int y) : val_(y) {}
int value() const { return val_; }
private:
int val_;
};
Date(Month::Mar(), Day(30), Year(2024)); // Clear and type-safe
Item 11: Handle Self-Assignment
class Widget {
Bitmap* pb_;
public:
// BAD: Unsafe for self-assignment
Widget& operator=(const Widget& rhs) {
delete pb_; // What if this == &rhs?
pb_ = new Bitmap(*rhs.pb_); // rhs.pb_ already deleted!
return *this;
}
// GOOD: Copy-and-swap idiom (exception-safe + self-assignment safe)
Widget& operator=(Widget rhs) { // Note: pass by value
swap(*this, rhs); // Swap contents
return *this; // Old resources freed in rhs destructor
}
friend void swap(Widget& a, Widget& b) noexcept {
using std::swap;
swap(a.pb_, b.pb_);
}
};
Item 23: Prefer Non-Member Non-Friend Functions
class WebBrowser {
public:
void clearCache();
void clearHistory();
void removeCookies();
};
// BAD: Adding "convenience" member functions
class WebBrowser {
// ...
void clearEverything() { // Increases coupling, decreases encapsulation
clearCache();
clearHistory();
removeCookies();
}
};
// GOOD: Non-member function in same namespace
namespace WebBrowserStuff {
class WebBrowser { /* ... */ };
void clearBrowser(WebBrowser& browser) {
browser.clearCache();
browser.clearHistory();
browser.removeCookies();
}
}
// Doesn't increase class interface, found via ADL, can be in separate header
Item 31: Minimize Compilation Dependencies
// BAD: Heavy includes in header
// widget.h
#include <string>
#include <vector>
#include <memory>
#include "gadget.h"
#include "person.h"
class Widget {
std::string name_;
std::vector<Gadget> gadgets_;
Person owner_;
// ...
};
// GOOD: Pimpl idiom for compilation firewall
// widget.h
#include <memory>
class Widget {
public:
Widget();
~Widget();
// ... interface ...
private:
struct Impl;
std::unique_ptr<Impl> pImpl_;
};
// widget.cpp
#include "widget.h"
#include <string>
#include <vector>
#include "gadget.h"
#include "person.h"
struct Widget::Impl {
std::string name;
std::vector<Gadget> gadgets;
Person owner;
};
Widget::Widget() : pImpl_(std::make_unique<Impl>()) {}
Widget::~Widget() = default; // Must be in .cpp where Impl is complete
Mental Model
Meyers approaches C++ as a collection of gotchas that can be systematically avoided. For each situation, ask:
- What does C++ do by default here?
- What could go wrong?
- How do I make the right choice obvious?
- How do I make wrong choices fail to compile?
The "Effective" Method
When writing code:
- Know your defaults (what does the compiler generate?)
- Understand your types (value semantics vs reference semantics)
- Design for correctness first, then optimize
- Make invariants checkable at compile time when possible
Additional Resources
- For references (books, talks), see references.md
More from copyleftdev/sk1llz
google-material-design
Design interfaces following Google's Material Design system, the unified visual language bridging digital and physical worlds. Emphasizes bold graphic design, intentional motion, adaptive layouts, and the material metaphor. Use when building modern, accessible, delightful user interfaces across platforms.
117renaissance-statistical-arbitrage
Build trading systems in the style of Renaissance Technologies, the most successful quantitative hedge fund in history. Emphasizes statistical arbitrage, signal processing, and rigorous scientific methodology. Use when developing alpha research, signal extraction, or systematic trading strategies.
104aqr-factor-investing
Build investment systems in the style of AQR Capital Management, the quantitative investment firm pioneering factor investing. Emphasizes academic rigor, transparent methodology, and systematic factor exposure. Use when building factor models, conducting asset pricing research, or designing systematic portfolios.
103minervini-swing-trading
Trade swing setups in the style of Mark Minervini, 3x US Investing Champion with 220%+ annual returns. Emphasizes SEPA methodology, trend templates, volatility contraction patterns (VCP), and strict risk management. Use when swing trading momentum stocks, identifying breakout setups, or building systematic trend-following strategies.
84de-shaw-computational-finance
Build trading systems in the style of D.E. Shaw, the pioneering computational finance firm. Emphasizes systematic strategies, rigorous quantitative research, and world-class technology infrastructure. Use when building research platforms, systematic trading strategies, or quantitative finance infrastructure.
63jump-trading-fpga-hft
Build trading systems in the style of Jump Trading, the high-frequency trading firm pioneering FPGA-based trading. Emphasizes hardware acceleration, network optimization, and nanosecond-level execution. Use when building FPGA trading systems, network-optimized infrastructure, or ultra-low-latency order execution.
29