Modules (C++20)
“Modules are othogonal to namespaces.”
lvalues and rvalues
An lvalue refers to an object that persists beyond a single expression. You can think of an lvalue as an object that has a name. All variables, including nonmodifiable (const) variables, are lvalues. An rvalue is a temporary value that does not persist beyond the expression that uses it.
A function call can be an lvalue if and only if the return value is a reference.
Boost versus STL
Casts – static_cast reinterpret_cast dynamic_cast const_cast
Arrays can be implicitly converted to pointers without casting - there is no
implicit conversion from pointers to arrays. int*
can be implicity converted
to int const*
: there is no implicit conversion from int const*
to int*
.
You can static cast a derived class pointer to a base class pointer but not the other way around.
Rule of three/five
If you declare any of copy, copy assignment or destructor then you should declare them all. Similarly for C++11 onwards: rule of 5.
See wiki/Rule of three.
- C++: Understand how rule of 5 (rule of 3 in pre-C++11) is the best way to write exception-safe classes. Understand why it’s a good idea even without exceptions.
- Function local variables are NOT accessible in the try handler.
class base_of_five_defaults
{
public:
base_of_five_defaults(const base_of_five_defaults&) = default;
base_of_five_defaults(base_of_five_defaults&&) = default;
base_of_five_defaults& operator=(const base_of_five_defaults&) = default;
base_of_five_defaults& operator=(base_of_five_defaults&&) = default;
virtual ~base_of_five_defaults() = default;
};
Classes and structures
The difference between a class
and a struct
is only the default accesses specifier: public:
for struct
and private:
for class
.
Virtual
#include <iostream>
class a {
public:
a() { std::cout << "a ctor" << std::endl; }
virtual ~a() { std::cout << "\ta dtor" << std::endl; }
};
class b : public a {
public:
b() { std::cout << "b ctor" << std::endl; }
virtual ~b() { std::cout << "\tb dtor" << std::endl; }
};
int main() {
std::cout << std::endl;
{
a* _b = new b;
// If the base class destructor weren't virtual only ~a would be called
delete _b;
}
std::cout << std::endl;
{
a* _b = new b[3];
// Still doesn't work for this
delete [] _b;
}
return 0;
}
noexcept
- Make destructors noexcept
- Mark move constructor noexcept
Linkage
If an object or function inside such a translation unit has internal linkage, then that specific symbol is only visible to the linker within that translation unit. If an object or function has external linkage, the linker can also see it when processing other translation units. The static keyword, when used in the global namespace, forces a symbol to have internal linkage. The extern keyword results in a symbol having external linkage.
- Non-const global variables have external linkage by default
- Const global variables have internal linkage by default
- Functions have external linkage by default
Dynamic Storage Duration
Automatic Storage Duration
Anonymous namepsaces
Use to declare many things with internal linkage.
namespace { int variable = 0; }
See linkage.