Advertisement
AlexDanilin

Урок 2.1 Умный указатель unique_ptr

Nov 13th, 2023 (edited)
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.18 KB | None | 0 0
  1. #include <cassert>
  2. #include <iostream>
  3. #include <memory>
  4. #include <string>
  5.  
  6. using namespace std;
  7.  
  8. struct Cat {
  9.     Cat(const string& name, int age)
  10.             : name_(name)
  11.             , age_(age)  //
  12.     {
  13.     }
  14.     const string& GetName() const noexcept {
  15.         return name_;
  16.     }
  17.     int GetAge() const noexcept {
  18.         return age_;
  19.     }
  20.     ~Cat() {
  21.     }
  22.     void Speak() const {
  23.         cout << "Meow!"s << endl;
  24.     }
  25.  
  26. private:
  27.     string name_;
  28.     int age_;
  29. };
  30.  
  31. // Функция создаёт двухлетних котов
  32. unique_ptr<Cat> CreateCat(const string& name) {
  33.     return make_unique<Cat>(name, 2);
  34. }
  35.  
  36. class Witch {
  37. public:
  38.     explicit Witch(const string& name)
  39.             : name_(name) {
  40.     }
  41.  
  42.     Witch(const Witch& other)
  43.             : name_(other.name_)
  44.             , cat_(make_unique<Cat>(*other.cat_)) // Создаем копию кота
  45.     {
  46.     }
  47.  
  48.     Witch& operator=(const Witch& rhs) {
  49.         if (this != &rhs) {
  50.             name_ = rhs.name_;
  51.             cat_ = make_unique<Cat>(*rhs.cat_); // Создаём копию кота
  52.         }
  53.         return *this;
  54.     }
  55.  
  56.     // При явном объявлении конструктора копирования и копирующего оператора присваивания
  57.     // компилятор не будет генерировать перемещающий конструктор и перемещающий оператор присваивания
  58.     // Поэтому явно просим компилятор сгенерировать их
  59.     Witch(Witch&&) = default;
  60.     Witch& operator=(Witch&&) = default;
  61.  
  62.     void SetCat(unique_ptr<Cat>&& cat) noexcept {
  63.         cat_ = std::move(cat);
  64.     }
  65.     unique_ptr<Cat> ReleaseCat() noexcept {
  66.         return std::move(cat_);
  67.     }
  68.  
  69. private:
  70.     string name_;
  71.     unique_ptr<Cat> cat_;
  72. };
  73.  
  74. void Test() {
  75.     // Объекты Witch можно перемещать
  76.     {
  77.         Witch witch("Hermione"s);
  78.         auto cat = CreateCat("Crookshanks"s);
  79.         Cat* raw_cat = cat.get();
  80.         assert(raw_cat);
  81.         witch.SetCat(move(cat));
  82.  
  83.         Witch moved_witch(std::move(witch));
  84.         auto released_cat = moved_witch.ReleaseCat();
  85.         assert(released_cat.get() == raw_cat);  // Кот переместился от witch к moved_witch
  86.     }
  87.  
  88.     // Можно использовать перемещающий оператор присваивания
  89.     {
  90.         Witch witch("Hermione"s);
  91.         auto cat = CreateCat("Crookshanks"s);
  92.         Cat* raw_cat = cat.get();
  93.         witch.SetCat(move(cat));
  94.  
  95.         Witch witch2("Minerva McGonagall");
  96.         witch2 = move(witch);
  97.         auto released_cat = witch.ReleaseCat();
  98.         assert(!released_cat);
  99.         released_cat = witch2.ReleaseCat();
  100.         assert(released_cat.get() == raw_cat);
  101.     }
  102.  
  103.     // Можно копировать волшебниц
  104.     {
  105.         Witch witch("Hermione");
  106.         auto cat = CreateCat("Crookshanks"s);
  107.         witch.SetCat(move(cat));
  108.  
  109.         Witch witch_copy(witch);
  110.         assert(!cat);
  111.         cat = witch.ReleaseCat();
  112.         assert(cat);  // У первой волшебницы кот никуда не делся
  113.  
  114.         auto cat_copy = witch_copy.ReleaseCat();
  115.         assert(cat_copy != nullptr && cat_copy != cat);
  116.         assert(cat_copy->GetName() == cat->GetName());  // Копия волшебницы содержит копию кота
  117.     }
  118.  
  119.     // Работает копирующее присваивание волшебниц
  120.     {
  121.         Witch witch("Hermione"s);
  122.         auto cat = CreateCat("Crookshanks"s);
  123.         witch.SetCat(move(cat));
  124.  
  125.         Witch witch2("Minerva McGonagall"s);
  126.         witch2 = witch;
  127.  
  128.         assert(!cat);
  129.         cat = witch.ReleaseCat();
  130.         assert(cat);  // У первой волшебницы кот никуда не делся
  131.  
  132.         auto cat_copy = witch2.ReleaseCat();
  133.         assert(cat_copy != nullptr && cat_copy != cat);
  134.         assert(cat_copy->GetName() == cat->GetName());  // При присваивании скопировался кот
  135.     }
  136. }
  137.  
  138. int main() {
  139.     Test();
  140. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement