basic
[[nodiscard]]
: mark a value so that user cannot ignore it without notice- remove while iterating
- erase() return iter to next element
- comp functor requires a strict weak ordering
- i.e. implement
<
rather than<=
- i.e. implement
preprocessor
# // stringizing
## // token pasting
Note: If an argument is stringized or concatenated, the prescan does not occur. i.e. macro argument is not marco-expanded before substitution.
#define xstr(s) str(s)
#define str(s) #s
#define foo 4
str (foo)
→ "foo"
xstr (foo)
→ xstr (4)
→ str (4)
→ "4"
[Reference])(https://gcc.gnu.org/onlinedocs/gcc-7.5.0/cpp/Argument-Prescan.html#Argument-Prescan)
static and const
static
means that variable will be shared, which can still be changed in runtime.- Thus, require a storage space and cannot be defined in a header file
- (c++17 has inline variable)
const
means that the value cannot change after creationstatic const
means that the value is a constant, which will evaluated during compilation- intergral constant has special rules called integral constant expressions
- for other type, we need specify
constexpr
in the typeconstexpr
implicitly make the type to beconst
constexpr
does not make sense on type withoutstatic
constexpr
only works on literal type or reference type- no object?
- When use
constexpr
in expression, programmer need to make sure that the expression can be evaluated at compile time
array type
There is an implicit conversion from lvalues and rvalues of array type to rvalues of pointer type: it constructs a pointer to the first element of an array. This conversion is used whenever arrays appear in context where arrays are not expected, but pointers are.
Note that when array-to-pointer decay is applied, a multidimensional array is converted to a pointer to its first element (e.g., a pointer to its first row or to its first plane): array-to-pointer decay is applied only once.
Notice that new []
always seems to decay once.
stdio
cin
stops at whitespace (w/o removing them)cin
ignores leading whitespace
getline
remove newline from streamcin.ignore()
to remove character from streamcin.ignore(80, 'b')
remove upto 80 char until b is also consumed
string
+stringstream
+std::getline
==split
getline
can use a single char as delim
// makes c and c++ io have independent buffer
ios_base::sync_with_stdio(false);
// normally, cin / cout flush before operation on the other stream
// untie it means manually flush
cin.tie(NULL);
incompleted type
A structure type whose members you have not yet specified. A union type whose members you have not yet specified. An array type whose dimension you have not yet specified.
- EXP57-CPP: do not delete pointers to incomplete classes
- For the following case, the compiler is forced to generate a deleter
- unique_ptr: zero-abstraction -> deleter always generated.
- ~P()
- move assignment
- reset()
- reset(A*)
- shared_ptr: deleter is needed to construct the control block
- P(A*)
- reset(A*)
virtual function
- virtual function should be accessed using pointer or reference
- function call might not be inlined because of vtable
- it is possible if the type can be determined
- implementation:
- each class has a static virtual table
- each virtual object holds a pointer to some virtual table
- at construction, replace parent’s pointer with child’s pointer
- type information & dynamic cast can be embedded in the virtual table
// simple dump function
// %zu for size_t, %p for void *
static void print_object(const char *name, void *this_, size_t size) {
void **ugly = reinterpret_cast<void**>(this_);
size_t i;
printf("created %s at address %p of size %zu\n", name, this_, size);
for(i = 0 ; i < size / sizeof(void*) ; i++) {
printf(" pointer[%zu] == %p\n", i, ugly[i]);
}
}
http://blog.httrack.com/blog/2014/05/09/a-basic-glance-at-the-virtual-table/
multi-threading
- use scoped_lock over lock_guard because it is a super set
- unique_lock has the state of not owning any mutex.
- Thus, it can be default constructed. (error-prune)
- condition_variable:
- needs to unlock so unique_lock is necessary
- w/o predicate, a cv can be notified before entering wait state (lost)
- with predicate, we can check and skip the wait
- w/o predicate, a cv can Spurious wakeup and escape the wait
- with predicate, we will re-enter wait
- predicate needs to be guarded with the same mutex
- otherwise, a sync is not guaranteed.
iterator
- when empty, then
begin() == end()
input iterator
,++r
requires r to be dereferencablebidirectional iterator
,--r
has the post condition that r is dereferenablebefore_begin
is only defined forforward_list
std::algorithm
find_if
,find_if_not
find_first_of
,find_last_of
instd::string
has apos
parameter
swap
,reverse
namespace
- anonymous namespace has internal linkage which is the same as
static
in file - inline namespace expose content to enclosing namespace
- inject information into the mangled name (ABI) without altering the API
- used for library versioning
- ADL does not follow
using
- default call accesses inline namespace
- but a fully qualified call can access any namespace
- old abi is retained
- as long as the type does not cross api boundary, a executable can use both namespaces at the same time
- inject information into the mangled name (ABI) without altering the API
inline keyword
- inline allow function to defined in multiple tranlation unit
- but we must make sure that all definition match
- since c++17, inline can also be used on variable
- that means
static
variable does not need a separated cpp file
- that means
exception
- prefere a separate
Init()
andDeInit()
- exception is the only way for constructor to fail
- but only allocation fail is reasonable for constructor
- deconstructor should not throw exception in any cases
- exception is the only way for constructor to fail
- all exceptions need to be exposed in abi
- otherwise, rtti cannot resolve the inheritance chain
- exceptions need to be inherited virtually such that it resolve to a single base class
noexcept
- when throwing a exception, the programm will call std::terminite
- noexcept on move constructor can improve performance
- conditional noexcept can be used in template class
reflection vs rtti
With rtti, program is able to work on a set of runtime types. The set is determined in compile time.
With reflection, program is expected to work on any runtime types by looking into the data structure during runtime
virtual function in cpp constructor / destructor [OOP50-CPP]
the function called is the final overrider in the constructor’s or destructor’s class and not one overriding it in a more-derived class.
During the construction process, the vtable pointer is changed when entering a child class scope. So, virtual function cannot resolve to correct function.
(Also, member variable does not exist at this point)
INT02-C
Integer types smaller than int are promoted when an operation is performed on them
If the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type is converted to the type of the operand with unsigned integer type.
Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
attribute
[[deprecated]]
gMock
- dependency injection
- differennt use case might require vastly different contruction parameter
- inject mock class when testing
- but virutal mock class create inheritance that should not exist
- static injection via template
- c++ 20 cocepts
- vs factory / delegation
- instead of inject object, let the class create it as needed
- factory allow more procedure calls than constructor
todo section
c++ module
https://vector-of-bool.github.io/2019/03/31/modules-2.html
c++ guide? https://developer.mozilla.org/en-US/docs/Mozilla/Using_CXX_in_Mozilla_code
c++ regex
vs rust regex?
some nice source
Guru of the Week Bartek’s coding blog cppinsights compiler explorer
C++ Core Guidelines Common Weakness List SEI CERT C++ MISRA Abseil Guide