diff --git a/README.adoc b/README.adoc index a89a8e9..9736020 100644 --- a/README.adoc +++ b/README.adoc @@ -2509,6 +2509,9 @@ Note that secondary cores in gem5 are kind of broken however: < v{0, 1};` and `std::initializer_list` -*** link:userland/cpp/most_vexing_parse.cpp[]: the most vexing parse is a famous constructor vs function declaration syntax gotcha! -**** https://en.wikipedia.org/wiki/Most_vexing_parse -**** http://stackoverflow.com/questions/180172/default-constructor-with-empty-brackets -** `virtual` and polymorphism -*** link:userland/cpp/virtual.cpp[] * iostream ** link:userland/cpp/copyfmt.cpp[]: `std::copyfmt` restores stream state, see also: https://stackoverflow.com/questions/12560291/set-back-default-floating-point-print-precision-in-c/53673686#53673686 * fstream @@ -20247,6 +20242,61 @@ Programs under link:userland/cpp/[] are examples of https://en.wikipedia.org/wik *** link:userland/cpp/multimap.cpp[]: `std::multimap` ** <> contains a benchmark comparison of different c++ containers +[[cpp-classes]] +==== C++ classes + +[[cpp-constructor]] +===== C++ constructor + +* link:userland/cpp/initializer_list_constructor.cpp[]: documents stuff like `std::vector v{0, 1};` and `std::initializer_list` +* link:userland/cpp/most_vexing_parse.cpp[]: the most vexing parse is a famous constructor vs function declaration syntax gotcha! +** https://en.wikipedia.org/wiki/Most_vexing_parse +** http://stackoverflow.com/questions/180172/default-constructor-with-empty-brackets +* `virtual` and polymorphism +** link:userland/cpp/virtual.cpp[] + +[[cpp-rule-of-five]] +====== C++ rule of five + +link:userland/cpp/rule_of_five.cpp[] + +Output Ubuntu 20.04 GCC 9.3: + +.... +constructor? +constructor + +copy? +constructor +copy + +copy assignment? +constructor +copy assignment +constructor +copy +move assignment +destructor + +move? +constructor + +move? +constructor +constructor +move assignment +destructor + +a bunch of destructors? +destructor +destructor +destructor +destructor +destructor +.... + +https://en.cppreference.com/w/cpp/language/rule_of_three + [[cpp-standards]] ==== C++ standards diff --git a/userland/cpp/rule_of_five.cpp b/userland/cpp/rule_of_five.cpp new file mode 100644 index 0000000..defea92 --- /dev/null +++ b/userland/cpp/rule_of_five.cpp @@ -0,0 +1,75 @@ +// https://cirosantilli.com/linux-kernel-module-cheat#cpp-rule-of-five +// Adapted from https://en.cppreference.com/w/cpp/language/rule_of_five + +#include +#include +#include +#include + +class rule_of_five +{ + char* cstring; + public: + rule_of_five(const char* s = "") + : cstring(nullptr) { + std::cout << "constructor" << std::endl; + if (s) { + std::size_t n = std::strlen(s) + 1; + cstring = new char[n]; + std::memcpy(cstring, s, n); + } + } + + ~rule_of_five() { + std::cout << "destructor" << std::endl; + delete[] cstring; + } + + rule_of_five(const rule_of_five& other) + : rule_of_five(other.cstring) { + std::cout << "copy" << std::endl; + } + + rule_of_five& operator=(const rule_of_five& other) { + std::cout << "copy assignment" << std::endl; + return *this = rule_of_five(other); + } + + rule_of_five(rule_of_five&& other) noexcept + : cstring(std::exchange(other.cstring, nullptr)) { + std::cout << "move" << std::endl; + } + + rule_of_five& operator=(rule_of_five&& other) noexcept { + std::cout << "move assignment" << std::endl; + std::swap(cstring, other.cstring); + return *this; + } +}; + +int main() +{ + std::cout << "constructor?" << std::endl; + rule_of_five o1{"aaa"}; + std::cout << std::endl; + + std::cout << "copy?" << std::endl; + auto o2{o1}; + std::cout << std::endl; + + std::cout << "copy assignment?" << std::endl; + rule_of_five o3("bbb"); + o3 = o2; + std::cout << std::endl; + + std::cout << "move?" << std::endl; + rule_of_five o4(rule_of_five("ccc")); + std::cout << std::endl; + + std::cout << "move?" << std::endl; + rule_of_five o5("ddd"); + o5 = rule_of_five("eee"); + std::cout << std::endl; + + std::cout << "a bunch of destructors?" << std::endl; +}