2015-11-21 2 views
0

Я был на Unity долгое время и вернулся, чтобы сделать некоторые C++ с использованием Visual Studio 2015 я наткнулся на этот класс определениястанд :: unique_ptr пытается ссылаться на удаленную функцию

class A 
{ 
public: 
    A(); 
    virtual ~A(); 
    A(const A&) = delete; 
    A& operator=(const A&) = delete; 

private: 
    … 
} 

Этот класс динамически распределяется так:

ObjPtr obj = ObjPtr(new A()); 

где ObjPtr является тип, определенный и выглядит следующим образом:

typedef std::unique_ptr<A> objPtr; 

и добавление этих созданных объектов с использованием std::vector<ObjPtr> с использованием std::move. В какой-то момент мне нужно пройти через список объектов, и если я найду что-то, удовлетворяющее моим критериям, сохраните его копию.

ObjPtr keep; 

for(auto& object : GetObjectList()) 
{ 
    if(/*check if its the object I want*/) 
    { 
    keep = object; 
    } 
} 

Где GetObjectList возвращает const std::vector<ObjPtr>&.

Но я получаю «попытку ссылки на удаленную функцию». Я сделал несколько поисковых запросов и попытался удалить часть = delete и даже прокомментировал 2 строки. Я даже пытался сделать

ObjPtr keep = std::move(object); 

Но я все еще получаю ошибку удаленной функции. Может ли кто-нибудь увидеть, что я делаю неправильно, или указать мне на некоторые ресурсы, которые могут помочь?

+2

Каков тип 'ObjectList'? – vsoftco

+0

@vsoftco Обновлено мое сообщение! – dwnenr

+1

Вы уверены, что 'ObjectList' не' const'? –

ответ

4

A std::unique_ptr не может быть скопирован. Даже если управляемый объект может (но ваш не может).

У вас есть несколько альтернатив здесь (все с различными эффектами):

  • Изменить тип keep к не владеющему сырому указателю (ака A *) и использовать keep = object.get();. Это безопасно тогда и только тогда, когда вы знаете, что вы не будете использовать keep дольше, чем ObjectList (или, точнее, объект, по которому вы берете адрес).

  • Переместить std::unique_ptr из контейнера, то есть использовать keep = std::move(object);. Конечно, теперь у вас есть пробел в ObjectList. (Я понимаю, что вы редактировали свой вопрос, чтобы сказать, что ObjectList является const, что означает, что вы не можете изменить, и, следовательно, не перемещать объекты из него.)

  • Измените тип ObjPtr к std::shared_ptr<A>, если вы хотите поделиться собственности семантику.

  • Если вы абсолютно хотите копию объекта, вы можете добавить функцию в virtual члены A, что клоны объекта полиморфно.

    class A 
    { 
    public: 
        virtual std::unique_ptr<A> clone() = 0; 
        … 
    }; 
    

    Вы затем реализовать эту функцию в каждом листе class, полученных от A. В вашем цикле вы затем используете keep = object->clone();. Для этого вы, вероятно, захотите сделать конструктор копирования protected, но не delete.

    Не используйте keep = std::make_unique<A>(*object);, потому что он не будет уважать действительный (динамический) тип объекта и всегда нарезать на A. (Так как ваш A не может быть скопирован, он все равно не будет работать.)

1

Что делает уникальный указатель «уникальным» в том, что существует только один такой указатель на объект. Если вы сделали копию уникального указателя, у вас было бы две вещи, каждая из которых принадлежала базовому объекту. Когда каждый из них был уничтожен, объект будет уничтожен, что приведет к двойному удалению.

Если вам нужно несколько владельцев, используйте shared_ptr. Если вам не нужна собственность в коде, который хранит копию, не храните копию, а вместо нее сохраняйте указатель или ссылку.

Смежные вопросы