2017-02-16 11 views
0

У меня есть следующее определение класса:REFERENCING удалены функции при использовании unique_ptr

class InterpolatedSpreadConnector 
{ 
public: 
    ~InterpolatedSpreadConnector() = default; 
    GPUImage* operator()() override; 

    GPUImage* AncestorReducedConnectivity = nullptr; 
    GPUImage* OffspringReducedConnectivity = nullptr; 
}; 

, который при использовании в декларации auto connector = InterpolatedSpreadConnector(); работает просто отлично. Однако я хочу изменить эти исходные указатели на unique_ptr.

Включая memory и замены сырья указателей с std::unique_ptr<GPUImage> членами в определении дает мне attempting to reference deleted function ошибку на конструкторе InterpolatedSpreadConnector копирования. Как ни странно, ошибка исчезает, если я заменю unique_ptr на shared_ptr.

Может ли кто-нибудь объяснить, почему это происходит?

+2

'unique' означает, что он не может быть скопирован или назначен. Но лучше поставите [mcve]. – juanchopanza

+0

Прочтите это: http://en.cppreference.com/w/cpp/language/copy_initialization – Nim

+0

Я думал, что есть что-то вроде копирования elision (?), Который автоматически пропускал построение копии и предполагал нормальную конструкцию в таких случаях , –

ответ

4

Чтобы этот код работал до C++ 17, вам необходимо определить конструктор move для вашего класса. Это может быть столь же просто, как:

InterpolatedSpreadConnector(InterpolatedSpreadConnector &&) = default; 

Вашего определенного пользователем деструктор означает, что неявное поколение Move-конструктор подавляется.

И без конструктора перемещения операция копирования/перемещения возвращается к конструктору копирования, что вызывает ошибку компиляции, так как неявно сгенерированный конструктор-копир удален, поскольку unique_ptr имеет удаленный экземпляр-конструктор.


В C++ 14 и ранее, auto x = X(); концептуально означает, что мы создаем временную X, а затем копировать/перемещать, построить x от временного и уничтожить временный. Компилятору разрешено использовать elide, но правильные конструкторы для этой процедуры все еще должны существовать.

Однако в C++ 17, auto x = X(); будет обозначаться так же, как X x{};.

Таким образом, ваш код будет работать на C++ 17, хотя в любом случае полезно определить конструктор move-constructor; или предпочтительно удалить определение деструктора (см. Rule of zero).

+0

Я вижу. Я думал, что копия elision автоматически пропустила построение копии и предположила нормальную конструкцию в таких случаях. –

+1

@ KristianD'Amato Это так, но конструкторы, которые будут использоваться, если бы исключение копирования не произошло, должны существовать и быть доступными. Обоснование заключается в том, что если компилятор решает сделать или не выполнять копирование, программа не должна внезапно не компилироваться в зависимости от этого выбора. –

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

  • Нет связанных вопросов^_^