Как переместить объект стека в std :: shared_pointer без создания экземпляров - PullRequest
1 голос
/ 02 мая 2020

Вопрос

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

class my_class {
private:
  my_class(my_class const&) = delete;

public:
  my_class(some_arg_t some_args);
  my_class(my_class&& move);
}

// later on

std::unordered_set<std::shared_ptr<my_class>> shared_pointers_container;

int foo() {
  my_class obj = getMyClassObject();
  shared_pointers_container.insert(// moving obj into heap memory and get the shared pointer to it)
}

Одним из "решений" может быть создание экземпляра объекта и его замена, как показано ниже

  std::shared_ptr<my_class> ptr = std::make_shared<my_class>(arguments_needed);
  *ptr.get() = std::move(obj);
  shared_pointers_container.insert(ptr);

, но это не очень хорошее решение (в случае, если конструктор делает некоторые изменения).

Возможно, способ std::make_shared переместить содержимое вновь созданного объекта от указанного объекта?

Ответы [ 2 ]

2 голосов
/ 03 мая 2020

На всякий случай, если вам это нужно по какой-то причине, вот трюк, который работает для класса, который не является ни подвижным, ни копируемым. Это ужасно; Я не рекомендовал бы это на практике.

class Wrapper {
    std::aligned_storage_t<sizeof(my_class), alignof(my_class)> data;
public:
    Wrapper() { new(&data) my_class{getMyClassObject()}; }
    ~Wrapper() { get()->~my_class(); }
    my_class* get() { return reinterpret_cast<my_class*>(&data); }
};

int main()
{
    auto wp = std::make_shared<Wrapper>();
    std::shared_ptr<my_class> p(wp, wp->get());
}

Демо .

Это основано на малоизвестной функции std::shared_ptr, где он может управлять одним объект, но выставить указатель на другой (обычно подобъект первого объекта).

2 голосов
/ 02 мая 2020

Это можно сделать. Трюки не нужны. Просто переместите объект:

shared_pointers_container.insert(std::make_shared<my_class>(getMyClassObject()));

// or if you need to start from `obj`:

my_class obj = getMyClassObject();
// work with obj
shared_pointers_container.insert(std::make_shared<my_class>(std::move(obj)););

На ваши замечания:

без фактического создания экземпляра класса?

(в случае, если конструктор делает некоторые изменения ).

Это совершенно неразумно. Если конструктор не делает то, что должен делать, класс глючит.

Чтобы быть более понятным: проблема, которую вы пытаетесь решить, заключается в следующем: у вас есть объект, заданный значением из внешнего библиотека. Этот объект только для перемещения. Вы хотите поместить этот объект в контейнер общих указателей. Это проблема. Решая эту проблему, вы думаете, что не можете использовать конструктор перемещения, но это определенно не тот случай. Решение состоит в том, чтобы использовать конструктор перемещения, как я показал.

...