Printing is expensive from a physics perspective
Solution (note: similar to N+1 problem)
std::endl flushes bufferstdout is buffered by default, stderr is unbuffered
CXX = g++
CXXFLAGS = -std=c++14 -Wall -g -MMD
EXEC = my_program
OBJECTS = main.o dependency.o
DEPENDS = ${OBJECTS:.o=.d}
${EXEC}: ${OBJECTS}
${CXX} -o ${OBJECTS} ${EXEC}
-include: ${DEPENDS}
.PHONY: not_a_filename
not_a_filename:
some_command
-MMD flag to generate dependencies
Transforms code before it reaches the compiler
#include "lib" inserts the contents of the file lib
#define VAR VALUE defines a symbol
g++ -DVAR=VALUE program.ccInclude Guard: Solve the double include problem
#ifndef FILE_H
#define FILE_H
... header file contents
#endif
Method called when object is first initialized
explicit keyword in front of a ctorMethod called when object is destroyed
struct Node {
int data;
Node *next;
~Node () { delete next; }
}
The following happens when an object is destructed:
Node &operator= (Node other) {
std::swap(this->data, other.data);
std::swap(this->next, other.next);
return *this;
}
other == lvalue ? copy ctor : move ctorAccessing internal data in an ADT without using public interface - invalidates invariants
private and public access modifiersstruct and class: struct default access is public, class is privateGives something access to my information - one-way. Useful for iterators in an ADT
friend class X, friend X::foo(int)Indicates something in program fucked up
noexcept (false) in function signature to prevent thisAllows for array-style initialization vector<int> v { 1, 2, 3 };
#include <initializer_list>
vector (std::initializer_list<T> init) :
n { init.size() }, cap { init.size() }, contents { new T[cap] } {
size_t i = 0;
for (auto &t: init) contents[i++] = t;
}
init is stored in contiguous memory; init.begin() returns a pointerinit) to build another (contents); 2 copies in memoryDifference between new and malloc: malloc returns NULL, new throws.
Regular new = operator new + placement new
Allocation: operator new(size_t n) (strong guarantee)
n bytes of uninitialized memoryoperator delete(thing)Initialization (Placement New): new (address) type
type object at address addraddrSame syntax and functionality as spread
template <typename T> class Vector {
template <typename ...Args>
void emplace_back (Args&& ...args, T&& example) {
new (contents + n) T(args...);
n++;
}
}
Args&& is a universal/forwarding reference (can point to either an rvalue or lvalue)
&& indicates a universal ref iff the type is ambiguous.emplace_back, Args is of an unknown type so Args&& is a universal reference. We already know T, so T&& is an rvalue.Type&&, cannot be const Type&& or somethingstd::forward<Args>(args)... preserves the rvalue/lvalue-ness of each argument
std::move if argument is an rvalue, else does nothingA function f can offer 3 different levels of safety once an exception has been handled:
f either succeeds completely, or not at all.std::move_if_noexcept: std::move(x) if move ctor is noexcept, else xInheritance allows you to do something like Book b = Manga { ... }.
auto bp = make_unique<Manga>(...)// assume same definitions as above
class Book {
...
public:
virtual bool isCool () const { return true; }
}
class Manga : public Book {
...
public:
bool isCool () const override { return hasAnime; }
}
Every class has a "virtual table", or vtable, which contains all of its virtual methods
isCoolEvery object (instance) has a vptr, a pointer to that table
book.isCool or manga.isCool are called, it performs the lookup using the vptr and runs the corresponding functionFor "transforming" types. dynamic_cast<T>(val) is the only one with a runtime effect; all others are compile time casts with O(0) runtime.