C++ Cheatsheet
Classes
class Foo {
public:
Foo(const Foo& arg); // copy constructor
Foo(Foo&& arg); // move constructor
Foo& operator=(const Foo& rhs); // copy assignment operator
Foo& operator=(Foo&& rhs); // move assignment operator
~Foo(); // destructor
}
Inheritance
// class A
// class B
class C: public A, public B {
// ...
};
enum class
enum class Color {
kRed = 0,
kBlue,
kOrange,
};
Interfaces
// interface = a class with only pure virtual methods
class Foo {
public:
virtual int bar(int a) = 0;
};
class FooImpl : public Foo {
// ...
}
if / else
if (a < 0) {
// ...
} else if (a == 0) {
// ...
} else {
// ...
}
Switch
switch(var) {
case 1:
do_somthing_1();
break;
case 2:
do_somthing_2();
break;
default:
do_somthing_else();
}
Lambda
#include <algorithm>
#include <cmath>
std::sort(x, x + n,
[](float a, float b) {
return (std::abs(a) < std::abs(b));
}
);
Smart Pointers
Smart pointers:
// memory freed when ptr_a goes out of scope
unique_ptr<char> ptr_a(new char('a'));
// reference counted pointer
shared_ptr<char> ptr_b(new char('b'));
// pointer that does not increase reference counts
weak_ptr<char> ptr_c = ptr_b;
// memory freed when ptr_d goes out of scope
// differs from unique_ptr in copy semantics
auto_ptr<char> ptr_d(new char('d'));
Attributes
[[deprecated]]
void Foo(int);
Conversions
auto foo_enum = static_cast<Foo>(foo_number);
Strings
std::string
is modifiable; no interning.
String constants
// Bad: std::string is not trivially destructible
constexpr std::string
// Good
constexpr absl::string_view
Strings as storage
class {
private:
// Good
std::string str;
// Bad: it has no control of the backing string.
absl::string_view;
}
Raw protobuf string literal
R"pb({
...
})pb";
Numbers
// max
int64_t max_int64_t = std::numeric_limits<int64_t>::max();
// infinity
double inf = std::numeric_limits<double>::infinity();
Loops
for (int i = 0; i < items_size; ++i) {
cout << items[i] << endl;
}
for (int i : items) {
cout << i << endl;
}
Use const reference:
std::string words[] = { "a", "b", "c", "d" };
for (const std::string& word : words) {
// ...
}
Loop through maps:
std::map<std::string, int> numbers = {{"a", 0}, {"b", 1}, {"c", 2}};
for (const auto& p : numbers) {
cout << p.first << ": " << p.second;
}
for (const auto& [key, value] : my_map) {
printf("%f\n", value);
}
Mutable repeated fields:
for (auto& message : *foo.mutable_values()) {
message.set_field(true);
}
The traditional while
loop, looks the same in C++ and Java.
while (condition) {
// ...
}
do {
// ...
} while (condition)
Includes
#include <utility>
forstd::move
#include <functional>
forstd::function
#include <string>
forstd::string
Transitive inclusions
Do not rely on transitive inclusions.
foo.cc
should include bar.h
even if foo.h
already includes bar.h
.
main
int main(int argc, char** argv) {
// ...
return 0;
}
Conding Conventions
Google C++ Style Guide https://google.github.io/styleguide/cppguide.html
Formatter: clang-format