Гарантия Уникальных объектов на фабрике с использованием unique_ptr - PullRequest
0 голосов
/ 29 октября 2018

Я наткнулся на следующий код для фабрики.

  • T::create(std::forward<Args>(args)...) возвращает указатель на объект, созданный динамически. Таким образом, если два объекта имеют один и тот же адрес, то они одинаковы.
  • unique_ptr гарантирует, что один контейнер unique_ptr владеет указателем. Это означает, что вы не можете делать копии unique_ptr.

#pragma once

#include <memory>
#include <vector>

template <typename T>
class PoolFactory {
 public:
  template <typename... Args>
  T *getInstance(Args... args) {
    _createdItems.push_back(
        std::unique_ptr<T>(T::create(std::forward<Args>(args)...)));
    return _createdItems.back().get();
  }
  ~PoolFactory() = default;

 public:
  std::vector<std::unique_ptr<T>> _createdItems;
};

Вопрос

Предположим, мы пытаемся вставить объект, который уже существует в векторе. Поскольку мы используем фабрику и IF объект уже существует, мы просто хотим получить его. Как эта архитектура, содержащая семантику перемещения, гарантирует такое поведение?

Ответы [ 2 ]

0 голосов
/ 29 октября 2018

Вы получили «уникальность» std::unique_ptr<T> в обратном направлении. Не существует такого волшебного механизма, чтобы при создании std::unique_ptr<T> он каким-то образом проверял все существующие в настоящее время std::unique_ptr<T> и делал что-то другое, если ему принадлежат одинаковые значения указателя.

Вместо этого предполагается, что вы ранее new редактировали T * и строили из него std::unique_ptr<T> или вызывали std::make_unique<T> на new a T и заключали его в unique_ptr<T> для тебя. Если это предположение не соответствует действительности, и std::unique_ptr<T> уничтожен, поведение вашей программы не определено.

Запрет на копирование гарантирует, что delete называется ровно один раз , и часто без каких-либо дополнительных усилий с вашей стороны (т. Е. Время жизни получателя точно совпадает с временем жизни указателя)

0 голосов
/ 29 октября 2018

Интерпретируя этот код, на этой фабрике ваши объекты идентифицируются с помощью getInstance аргументов. Интерфейс также предполагает, что вызывающие абоненты знают как T, так и его аргументы конструктора, чтобы они могли сами создавать T.

Единственное использование для этой фабрики - сделать каждый объект одиночным.

Вам нужно отображение (args...) -> object, а не массив, чтобы сначала вы искали существующий объект с помощью args... и создавали объект, если он еще не существует.

...