From f941e992bfb4d8290e8657dde7bfafc1921f862c Mon Sep 17 00:00:00 2001 From: YdrMaster Date: Wed, 10 Jul 2024 18:06:59 +0800 Subject: [PATCH] =?UTF-8?q?update:=20=E5=AE=8C=E6=88=90=2014=20=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: YdrMaster --- exercises/06_loop/main.cpp | 6 +- exercises/08_trivial/main.cpp | 6 +- exercises/09_method/main.cpp | 6 +- exercises/11_class/main.cpp | 30 +++++++--- exercises/11_class_clone/main.cpp | 33 ----------- exercises/11_class_drop/main.cpp | 26 --------- exercises/12_class_deconstruct/main.cpp | 32 +++++++++++ exercises/12_class_move/main.cpp | 43 --------------- exercises/13_class_clone/main.cpp | 45 +++++++++++++++ exercises/14_class_move/main.cpp | 55 +++++++++++++++++++ .../{13_std_array => 15_std_array}/main.cpp | 0 .../{14_std_vector => 15_std_vector}/main.cpp | 0 exercises/xmake.lua | 16 ++++++ learn/summary.cpp | 2 +- 14 files changed, 179 insertions(+), 121 deletions(-) delete mode 100644 exercises/11_class_clone/main.cpp delete mode 100644 exercises/11_class_drop/main.cpp create mode 100644 exercises/12_class_deconstruct/main.cpp delete mode 100644 exercises/12_class_move/main.cpp create mode 100644 exercises/13_class_clone/main.cpp create mode 100644 exercises/14_class_move/main.cpp rename exercises/{13_std_array => 15_std_array}/main.cpp (100%) rename exercises/{14_std_vector => 15_std_vector}/main.cpp (100%) diff --git a/exercises/06_loop/main.cpp b/exercises/06_loop/main.cpp index b2610ae6..0b01455a 100644 --- a/exercises/06_loop/main.cpp +++ b/exercises/06_loop/main.cpp @@ -3,10 +3,10 @@ // TODO: 改正函数实现,实现正确的缓存优化斐波那契计算 static unsigned long long fibonacci(int i) { // TODO: 为缓存设置正确的初始值 - static unsigned long long cache[128], next = 2; + static unsigned long long cache[128], cached = 2; // TODO: 设置正确的循环条件 - for (; false; ++next) { - cache[next] = cache[next - 1] + cache[next - 2]; + for (; false; ++cached) { + cache[cached] = cache[cached - 1] + cache[cached - 2]; } return cache[i]; } diff --git a/exercises/08_trivial/main.cpp b/exercises/08_trivial/main.cpp index de0d3214..92704d64 100644 --- a/exercises/08_trivial/main.cpp +++ b/exercises/08_trivial/main.cpp @@ -3,13 +3,13 @@ // READ: Trivial type struct FibonacciCache { unsigned long long cache[16]; - int next; + int cached; }; // TODO: 实现正确的缓存优化斐波那契计算 static unsigned long long fibonacci(FibonacciCache &cache, int i) { - for (;; ++next) { - cache[next] = cache[next - 1] + cache[next - 2]; + for (;; ++cached) { + cache[cached] = cache[cached - 1] + cache[cached - 2]; } return cache.cache[i]; } diff --git a/exercises/09_method/main.cpp b/exercises/09_method/main.cpp index b1e2df4c..0e08e0a3 100644 --- a/exercises/09_method/main.cpp +++ b/exercises/09_method/main.cpp @@ -2,12 +2,12 @@ struct Fibonacci { unsigned long long cache[128]; - int next; + int cached; // TODO: 实现正确的缓存优化斐波那契计算 unsigned long long get(int i) { - for (; false; ++next) { - cache[next] = cache[next - 1] + cache[next - 2]; + for (; false; ++cached) { + cache[cached] = cache[cached - 1] + cache[cached - 2]; } return cache[i]; } diff --git a/exercises/11_class/main.cpp b/exercises/11_class/main.cpp index 9090ea53..9afa98c5 100644 --- a/exercises/11_class/main.cpp +++ b/exercises/11_class/main.cpp @@ -1,23 +1,35 @@ #include "../exercise.h" +// C++ 中,`class` 和 `struct` 之间的**唯一区别**是 +// `class` 默认访问控制符是 `private`, +// `struct` 默认访问控制符是 `public`。 +// READ: 访问说明符 + +// 这个 class 中的字段被 private 修饰,只能在 class 内部访问。 +// 因此必须提供构造器来初始化字段。 +// READ: 构造器 class Fibonacci { - size_t cache[128]; - int next = 2; + size_t cache[16]; + int cached; public: - Fibonacci() : cache{0, 1}, next(2) {} + // TODO: 实现构造器 + // Fibonacci() - size_t operator[](int i) { - for (; next <= i; ++next) { - cache[next] = cache[next - 1] + cache[next - 2]; + // TODO: 实现正确的缓存优化斐波那契计算 + size_t get(int i) { + for (; false; ++cached) { + cache[cached] = cache[cached - 1] + cache[cached - 2]; } return cache[i]; } }; int main(int argc, char **argv) { - Fibonacci fib0, fib1; - std::cout << "fibonacci(10) = " << fib0[10] << std::endl; - std::cout << "fibonacci(100) = " << fib1[100] << std::endl; + // 现在类型拥有无参构造器,声明时会直接调用。 + // 这个写法不再是未定义行为了。 + Fibonacci fib; + ASSERT(fib.get(10) == 55, "fibonacci(10) should be 55"); + std::cout << "fibonacci(10) = " << fib.get(10) << std::endl; return 0; } diff --git a/exercises/11_class_clone/main.cpp b/exercises/11_class_clone/main.cpp deleted file mode 100644 index b005006f..00000000 --- a/exercises/11_class_clone/main.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "../exercise.h" - -class BoxedFibonacci { - size_t *cache; - int next = 2; - -public: - BoxedFibonacci() - : cache(new size_t[128]{0, 1}), next(2) {} - BoxedFibonacci(BoxedFibonacci const &other) - : cache(new size_t[128]), next(other.next) { - std::cout << "Clone Fibonacci with next = " << next << std::endl; - std::memcpy(cache, other.cache, sizeof(size_t) * next); - } - ~BoxedFibonacci() { - std::cout << "Drop Fibonacci with next = " << next << std::endl; - delete[] cache; - } - - size_t operator[](int i) { - for (; next <= i; ++next) { - cache[next] = cache[next - 1] + cache[next - 2]; - } - return cache[i]; - } -}; - -int main(int argc, char **argv) { - BoxedFibonacci fib0, fib1; - std::cout << "fibonacci(10) = " << fib0[10] << std::endl; - std::cout << "fibonacci(100) = " << fib1[100] << std::endl; - return 0; -} diff --git a/exercises/11_class_drop/main.cpp b/exercises/11_class_drop/main.cpp deleted file mode 100644 index ae3021be..00000000 --- a/exercises/11_class_drop/main.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "../exercise.h" - -class BoxedFibonacci { - size_t *cache; - int next = 2; - -public: - BoxedFibonacci() : cache(new size_t[128]{0, 1}), next(2) {} - ~BoxedFibonacci() { - std::cout << "Drop Fibonacci with next = " << next << std::endl; - delete[] cache; - } - - size_t operator[](int i) { - for (; next <= i; ++next) { - cache[next] = cache[next - 1] + cache[next - 2]; - } - return cache[i]; - } -}; - -int main(int argc, char **argv) { - BoxedFibonacci fib; - std::cout << "fibonacci(10) = " << fib[10] << std::endl; - return 0; -} diff --git a/exercises/12_class_deconstruct/main.cpp b/exercises/12_class_deconstruct/main.cpp new file mode 100644 index 00000000..9e47576b --- /dev/null +++ b/exercises/12_class_deconstruct/main.cpp @@ -0,0 +1,32 @@ +#include "../exercise.h" + +// READ: 析构函数 + +/// @brief 任意缓存容量的斐波那契类型。 +/// @details 可以在构造时传入缓存容量,因此需要动态分配缓存空间。 +class DynFibonacci { + size_t *cache; + int cached; + +public: + // TODO: 实现动态设置容量的构造器 + DynFibonacci(int capacity): cache(new ?), cached(?) {} + + // TODO: 实现析构器,释放缓存空间 + ~DynFibonacci(); + + // TODO: 实现正确的缓存优化斐波那契计算 + size_t get(int i) { + for (; false; ++cached) { + cache[cached] = cache[cached - 1] + cache[cached - 2]; + } + return cache[i]; + } +}; + +int main(int argc, char **argv) { + DynFibonacci fib(12); + ASSERT(fib.get(10) == 55, "fibonacci(10) should be 55"); + std::cout << "fibonacci(10) = " << fib.get(10) << std::endl; + return 0; +} diff --git a/exercises/12_class_move/main.cpp b/exercises/12_class_move/main.cpp deleted file mode 100644 index 938e9d2e..00000000 --- a/exercises/12_class_move/main.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "../exercise.h" -#include - -class BoxedFibonacci { - size_t *cache; - int next = 2; - -public: - BoxedFibonacci() - : cache(new size_t[128]{0, 1}), next(2) {} - BoxedFibonacci(BoxedFibonacci &&other) noexcept - : cache(std::exchange(other.cache, nullptr)), - next(std::exchange(other.next, 0)) { - std::cout << "Move Fibonacci with next = " << next << std::endl; - } - ~BoxedFibonacci() { - std::cout << "Drop Fibonacci with next = " << next << std::endl; - delete[] cache; - } - - size_t operator[](int i) { - for (; next <= i; ++next) { - cache[next] = cache[next - 1] + cache[next - 2]; - } - return cache[i]; - } - - bool is_available() const { - return cache; - } -}; - -int main(int argc, char **argv) { - BoxedFibonacci fib; - std::cout << "fibonacci(10) = " << fib[10] << std::endl; - - auto fib_ = std::move(fib); - assert(!fib.is_available()); - assert(fib_.is_available()); - std::cout << "fibonacci(12) = " << fib_[12] << std::endl; - - return 0; -} diff --git a/exercises/13_class_clone/main.cpp b/exercises/13_class_clone/main.cpp new file mode 100644 index 00000000..49222ba9 --- /dev/null +++ b/exercises/13_class_clone/main.cpp @@ -0,0 +1,45 @@ +#include "../exercise.h" + +// READ: 复制构造函数 + +class DynFibonacci { + size_t *cache; + int cached; + +public: + // TODO: 实现动态设置容量的构造器 + DynFibonacci(int capacity): cache(new ?), cached(?) {} + + // TODO: 实现复制构造器 + DynFibonacci(DynFibonacci const &other) = delete; + + // TODO: 实现析构器,释放缓存空间 + ~DynFibonacci(); + + // TODO: 实现正确的缓存优化斐波那契计算 + size_t get(int i) { + for (; false; ++cached) { + cache[cached] = cache[cached - 1] + cache[cached - 2]; + } + return cache[i]; + } + + // NOTICE: 不要修改这个方法 + // NOTICE: 名字相同参数也相同,但 const 修饰不同的方法是一对重载方法,可以同时存在 + // 本质上,方法是隐藏了 this 参数的函数 + // const 修饰作用在 this 上,因此它们实际上参数不同 + size_t get(int i) const { + if (i <= cached) { + return cache[i]; + } + ASSERT(false, "i out of range"); + } +}; + +int main(int argc, char **argv) { + DynFibonacci fib(12); + ASSERT(fib.get(10) == 55, "fibonacci(10) should be 55"); + DynFibonacci const fib_ = fib; + ASSERT(fib_.get(10) == fib.get(10), "Object cloned"); + return 0; +} diff --git a/exercises/14_class_move/main.cpp b/exercises/14_class_move/main.cpp new file mode 100644 index 00000000..2257252f --- /dev/null +++ b/exercises/14_class_move/main.cpp @@ -0,0 +1,55 @@ +#include "../exercise.h" + +// READ: 移动构造函数 +// READ: 移动赋值 +// READ: 运算符重载 + +class DynFibonacci { + size_t *cache; + int cached; + +public: + // TODO: 实现动态设置容量的构造器 + DynFibonacci(int capacity): cache(new ?), cached(?) {} + + // TODO: 实现移动构造器 + DynFibonacci(DynFibonacci &&other) noexcept = delete; + + // TODO: 实现移动赋值 + // NOTICE: ⚠ 注意移动到自身问题 ⚠ + DynFibonacci &operator=(DynFibonacci &&other) noexcept = delete; + + // TODO: 实现析构器,释放缓存空间 + ~DynFibonacci(); + + // TODO: 实现正确的缓存优化斐波那契计算 + size_t operator[](int i) { + for (; false; ++cached) { + cache[cached] = cache[cached - 1] + cache[cached - 2]; + } + return cache[i]; + } + + // NOTICE: 不要修改这个方法 + bool is_alive() const { + return cache; + } +}; + +int main(int argc, char **argv) { + DynFibonacci fib(12); + ASSERT(fib[10] == 55, "fibonacci(10) should be 55"); + + DynFibonacci const fib_ = std::move(fib); + ASSERT(!fib.is_alive(), "Object moved"); + ASSERT(fib_[10] == 55, "fibonacci(10) should be 55"); + + DynFibonacci fib0(6); + DynFibonacci fib1(12); + + fib0 = std::move(fib1); + fib0 = std::move(fib0); + ASSERT(fib0[10] == 55, "fibonacci(10) should be 55"); + + return 0; +} diff --git a/exercises/13_std_array/main.cpp b/exercises/15_std_array/main.cpp similarity index 100% rename from exercises/13_std_array/main.cpp rename to exercises/15_std_array/main.cpp diff --git a/exercises/14_std_vector/main.cpp b/exercises/15_std_vector/main.cpp similarity index 100% rename from exercises/14_std_vector/main.cpp rename to exercises/15_std_vector/main.cpp diff --git a/exercises/xmake.lua b/exercises/xmake.lua index 9d42f579..9843688b 100644 --- a/exercises/xmake.lua +++ b/exercises/xmake.lua @@ -44,3 +44,19 @@ target("exercise09") target("exercise10") set_kind("binary") add_files("10_method_const/main.cpp") + +target("exercise11") + set_kind("binary") + add_files("11_class/main.cpp") + +target("exercise12") + set_kind("binary") + add_files("12_class_deconstruct/main.cpp") + +target("exercise13") + set_kind("binary") + add_files("13_class_clone/main.cpp") + +target("exercise14") + set_kind("binary") + add_files("14_class_move/main.cpp") diff --git a/learn/summary.cpp b/learn/summary.cpp index 4f109cb2..edcaf346 100644 --- a/learn/summary.cpp +++ b/learn/summary.cpp @@ -5,7 +5,7 @@ #include #include -constexpr auto MAX_EXERCISE = 10; +constexpr auto MAX_EXERCISE = 14; int main(int argc, char **argv) { if (argc == 1) {