#c #unique-ptr #move-constructor
#c #уникальный-ptr #переместить-конструктор
Вопрос:
Я пытаюсь создать объект, который может содержать указатель на его родительский элемент и вектор на его дочерние элементы.
Проблема в том, что когда я пытаюсь поместить объект с unique_back или push_back в дочерний вектор, я получаю
Error C2280 'Entity::Entity(const Entity amp;)': attempting to reference a deleted function
Из-за того, что у меня есть unique_ptr в сущности.
Я думал, что добавление конструктора перемещения решит эту проблему, но этого не произошло.
Я включил минимальный проверяемый пример, пригодный для выполнения, здесь ниже.
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
struct Entity
{
//////// data
unique_ptr<Entity> mParent;
std::vector<Entity> mChildren;
//////// ctors
// default
Entity() = default;
// move
Entity(Entity amp;amp; entity): mParent{std::move(entity.mParent)}{}
//////// functions
void add_child(Entity const amp;amp; entity)
{
mChildren.emplace_back(entity); // COMMENT OUT THIS LINE FOR FUNCTIONAL CODE
//Error C2280 'Entity::Entity(const Entity amp;)': attempting to reference a deleted function in... includexmemory0 881
};
};
int main()
{
Entity entity;
entity.add_child(Entity());
return 0;
}
Ответ №1:
Отбросьте const
:
void add_child(Entity amp;amp; entity)
и использовать:
mChildren.push_back(std::move(entity));
Применение этих двух изменений выше привело к компиляции для меня.
Объяснение: Вы хотите вызвать void push_back( Tamp;amp; value );
(или аналогично с emplace_back
) в vector<T>
, где T
находится Entity
. Другая перегрузка — это void push_back( const Tamp; value );
перегрузка, которая не компилируется, потому что ее реализация (тело метода) пытается вызвать конструктор копирования T
, а Entity
конструктора копирования нет. Реализация void push_back( Tamp;amp; value );
вызывает конструктор перемещения T
и Entity
имеет конструктор перемещения, поэтому он компилируется.
Чтобы убедиться, что это void push_back( Tamp;amp; value );
вызвано, вы хотите передать Entityamp;amp;
в push_back
. Для этого вам нужны оба изменения, описанные выше. Без любого из них entity
не может быть преобразован в Entityamp;amp;
.
Смотрите также https://en.cppreference.com/w/cpp/container/vector/push_back.
Комментарии:
1. @user4581301: Удаление
const
, но не добавлениеstd::move
, не привело к компиляции для меня.2. Да, вам нужно
std::move
. Ссылка на rvalue сама по себе является выражением lvalue.3. С моей стороны это полубредовая попытка. меня интересовало изменение с
emplace_back
наpush_back
.4. @user4581301 В этом случае они эквивалентны.
std::vector::push_back
имеетTamp;amp;
перегрузку, и оба будут создавать экземпляр на месте с использованием конструктора перемещения.5. Я знаю. Я уже взломал код запрашивающего, чтобы добавить в
std:: move
и забыл, что я это сделал. Все, что мне нужно было, чтобы заставить его работать в тот момент, это удалитьconst
. Когда я снова посмотрел на код запрашивающего, я заметил, что я сделал.