Исправление назначения членов указателя объекта с помощью умных указателей - PullRequest
0 голосов
/ 24 июня 2018

Я узнаю больше о интеллектуальных указателях в C ++ 14.

Рассмотрим следующую MWC:

#include <iostream>
#include <string>
#include <memory>

class House {
 public:
  House &operator=(const House &house) = default;
  House(const House &house) = default;
  House(): id_habitants_(nullptr), num_habitants_() {}
  explicit House(size_t num_habitants) {
    if (num_habitants > 0) {
      num_habitants_ = num_habitants;
      id_habitants_ = new int[num_habitants_];
      if (id_habitants_ != nullptr) {
        for (size_t id = 0; id < num_habitants_; ++id) {
          id_habitants_[id] = 1;
        }
      }
    }
  }
  void Print() {
    if (id_habitants_ != nullptr) {
      for (size_t id = 0; id < num_habitants_; ++id) {
        std::cout << id_habitants_[id] << ' ';
      }
      std::cout << std::endl;
    } else {
      std::cout << "<empty>" << std::endl;
    }
  }
  ~House() {
    if (id_habitants_ != nullptr) {
      delete [] id_habitants_;
    }
    num_habitants_ = 0;
  }
 private:
  int *id_habitants_;
  size_t num_habitants_;
};

int main() {
  std::cout << "Testing unique_ptr.\n" << std::endl;

  std::cout << "Using a dumb House class..." << std::endl;
  std::cout << "Creating House h1 with 3 habitants..." << std::endl;
  House h1(3);
  std::cout << "IDs of h1's 3 habitants:" << std::endl;
  h1.Print();
  std::cout << "Creating House h2 with 0 habitants..." << std::endl;
  House h2;
  std::cout << "IDs of h2's 0 habitants:" << std::endl;
  h2.Print();
  std::cout << "Default-assigning h1 to h2..." << std::endl;
  h2 = h1;
  std::cout << "IDs of h2's new 3 habitants:" << std::endl;
  h2.Print();
  std::cout << "Destroying h1..." << std::endl;
  h1.~House();
  std::cout << "IDs of h2's new 3 habitants:" << std::endl;
  h2.Print();
}

Без изменения конструктора копирования по умолчанию и оператора назначения по умолчанию для классаHouse, как я могу обеспечить правильное поведение указателя во время назначения с помощью интеллектуальных указателей?

С первой попытки кажется, что использование std::unique_ptr было бы правильным решением.Я мог бы создать новый класс:

class SmartHouse {
 public:
  SmartHouse &operator=(const SmartHouse &shouse) = default;
  SmartHouse(const SmartHouse &shouse) = default;
  SmartHouse(): id_habitants_(nullptr), num_habitants_() {}

  explicit SmartHouse(size_t num_habitants) {
    if (num_habitants > 0) {
      num_habitants_ = num_habitants;
      id_habitants_ = std::unique_ptr<int[]>(new int[num_habitants_]);
      if (id_habitants_) {
        for (size_t id = 0; id < num_habitants_; ++id) {
          id_habitants_[id] = 1;
        }
      }
    }
  }
  void Print() {
    if (id_habitants_) {
      for (size_t id = 0; id < num_habitants_; ++id) {
        std::cout << id_habitants_[id] << ' ';
      }
      std::cout << std::endl;
    } else {
      std::cout << "<empty>" << std::endl;
    }
  }
  ~SmartHouse() {
    num_habitants_ = 0;
  }
 private:
  std::unique_ptr<int[]> id_habitants_;
  size_t num_habitants_;
};

Согласно this , я не могу действительно скопировать один уникальный указатель на другой.Имеет смысл, верно?Это своего рода побеждает цель быть уникальным.Т.е. это не скомпилирует:

SmartHouse sh1(3);
SmartHouse sh2;
sh2 = sh1;

Но я мог бы указать оператор присваивания перемещения и переместить элемент unique_ptr<int[]> при назначении, передавая таким образом владение указанными данными левому объекту при назначении:

class SmartHouse {
  SmartHouse &operator=(SmartHouse &&SmartHouse) = default;
}
...
SmartHouse sh1(3);
SmartHouse sh2;
sh2 = std::move(sh1);
sh1.~SmartHouse();
sh2.Print();

Основной вопрос : Имеет ли это смысл вообще?Существуют ли более эффективные способы улучшения назначения переменных-указателей?

Полный MWE .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...