Arhn - архитектура программирования

Копирование конструкторов

У меня есть древовидный класс, в котором объявлены и определены конструкторы перемещения и операторы присваивания перемещения.

Зачем компилятору чувствовать необходимость синтезировать конструктор копирования, а затем жаловаться, что std::unique_ptr имеет закрытые члены?

Это кажется контрпродуктивным. Должен ли компилятор не знать, что скрытая копия и присваивание без тела или просто не определены, чтобы предотвратить попытку скопировать std::unique_ptr?

И почему объявление и определение конструкторов копирования и операторов присваивания с пустым телом делает компилятор счастливым?

Будет ли это поводом для беспокойства, если я продолжу писать и создавать код с использованием этого класса?

Дополнения:

  1. Исходного кода нет, потому что нет ошибок в исходном коде... это вопрос
    , который не требует наличия исходного кода.

  2. Компилятор жаловался, когда конструкторы копирования были закрытыми, поэтому я сделал их общедоступными; снова сделает приватным и проверит, есть ли сбои компилятора.

  3. Я использую Visual Studio 2012 Professional IDE и связанные с ней компиляторы.

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

Дополнительный вопрос:

Ну, похоже, Visual Studio 2012 не поддерживает объявления = delete в конструкторах или операторах присваивания, и сокрытие моих объявлений заставляет компилятор плакать по всему моему коду. Что мне теперь делать? Я согласен (ниже), что объявление конструкторов копирования бездействия — плохая идея, так какие еще варианты у меня есть?

Если вам действительно нужен небольшой пример, вот он. Мой компилятор не поддерживает = удалить

class Tree{
    class TreeNode{
         "declaration of unique_ptr, cstrs, move cstrs, hidden copy cstrs"
    };
public:
     "declaration of unique_ptrs, cstrs, move cstrs, copy cstrs <----- compiler 
      complains if hidden"
};

Использование boost::variant с этим


  • Пожалуйста, покажите исходный код C++ (или небольшой эквивалентный ему пример) 28.03.2013
  • Компилятор будет жаловаться, только если вы действительно попытаетесь скопировать или скопировать assign, что вполне разумно. 28.03.2013
  • Если вы хотите убедиться, что никто не использует конструкторы копирования и операторы присваивания, вы можете определить их приватными или (= удалить в С++ 11) 28.03.2013
  • Также укажите, какой компилятор вы используете. Создание пустого конструктора копирования, который ничего не делает, почти наверняка плохая идея (особенно в C++11). 28.03.2013

Ответы:


1

Если конструктора копирования нет, компилятор попытается его сгенерировать. Конструктор копирования по умолчанию довольно тупой, поэтому неудивительно, что он спотыкается о биты вашего класса.

Определение пустого дает вам конструктор копирования, который ничего не делает, и он заменяет тот, который в противном случае был бы сгенерирован компилятором, что позволяет избежать проблемы.

28.03.2013
  • Это не совсем предотвращение проблемы, если конструктор копирования не создает копию. Вы просто обмениваете это на другую проблему. 28.03.2013
  • Вам не нужен пустой конструктор копирования, который можно вызвать: это может привести к довольно неожиданному поведению. Скрыть или удалить... 28.03.2013
  • @Yakk: Или просто позвольте компилятору неявно удалить его. Это произойдет, если есть конструктор перемещения или некопируемый член, оба из которых здесь имеют место. 28.03.2013
  • @MikeSeymour да, поэтому создание пустого конструктора копирования часто бывает неправильным. Если компилятор жалуется на отсутствие конструктора копирования, возможно, это связано с тем, что вы пытались его вызвать. И если вы сейчас сделаете пустой, и он решит проблему, теперь ваш код попытался его скопировать, он находит пустой конструктор копирования, он делает неправильную вещь (может быть, даже пропуская пустой конструктор копирования, так что даже не ничего), и затем молча продолжает. Вы ничего не решили. 28.03.2013
  • @Yakk: Действительно; Я просто говорил, что нет необходимости явно скрывать или удалять его, как вы, кажется, предлагали; просто оставьте его удаленным. 28.03.2013
  • Всем спасибо за комментарии...очень познавательно 28.03.2013
  • @Yakk Проблема в том, что это скрывает. VS 2012 не поддерживает = 0 или = удалить, и его сокрытие вызывает проблемы, потому что boost:: variant требует копию; требует копию, заставляя набор конструкторов копирования ничего не делать, в противном случае код отказывается компилироваться и кричит о последней строке в моем коде, используя unique_ptr и частные объявления внутри нее ... bleh. 28.03.2013
  • @Mushy Если что-то хочет копию, и вы даете ему конструктор копирования, который он хочет, в пустой форме, когда ваш тип предназначен только для перемещения, вы просто сломали свой код. Возможно, boost::variant не может содержать unique_ptr содержащих классы. 28.03.2013
  • @Yakk Мне нужно раскрыть секрет в новом вопросе, потому что это ломает игру. 28.03.2013
  • @Mushy boost::variant написан с учетом движения? Если это не так, использование его с типами только для перемещения кажется плохой идеей. Что вам нужно сделать, так это написать короткий, автономный, правильный, компилирующий (почти) пример, который точно демонстрирует вашу проблему и то, как она возникает. Вполне возможно, вы делаете что-то не так, или, может быть, boost::variant принципиально неприменим с unique_ptrs. 28.03.2013

  • 2

    Зачем компилятору чувствовать необходимость синтезировать конструктор копирования, а затем жаловаться, что std::unique_ptr имеет закрытые члены?

    Этого не должно быть, если ваша стандартная библиотека не соответствует требованиям и объявляет закрытый, а не удаленный конструктор копирования для unique_ptr; даже в этом случае его следует синтезировать только в том случае, если вы не объявили конструктор перемещения.

    Если в вашем классе unique_ptr членов или если вы объявляете конструктор перемещения, он должен сообщить, что конструктор копирования удален; и то только в том случае, если вы пишете код, который пытается его скопировать.

    Должен ли компилятор не знать, что скрытая копия и присваивание без тела или просто не определены, чтобы предотвратить попытку скопировать std::unique_ptr?

    Вот так; за исключением того, что синтезированный конструктор копирования и присваивание удаляются, а не определяются.

    И почему объявление и определение конструкторов копирования и операторов присваивания с пустым телом делает компилятор счастливым?

    Потому что вы явно говорите, что хотите, чтобы он использовал этот (пустой) код для копирования, а не любой код, который он может (или не может) генерировать неявно. Хотя это плохая идея; если ваш класс не может быть скопирован, то вы хотите попытаться скопировать его, чтобы сгенерировать ошибку, а не неправильное поведение во время выполнения.

    28.03.2013
  • Не препятствует ли наличие конструктора перемещения автоматически генерировать конструктор копирования? 28.03.2013
  • @DavidRodríguez-dribeas: Почти; он будет объявлен, но удален. Я обновлю свой ответ... 28.03.2013
  • @MikeSeymour Да ... = delete и синтаксис, насколько я помню, MyCopyConstructor(const MyCopyCOnstructor &other) = delete. Это правильно? 28.03.2013
  • @Mushy: Если вы хотите удалить его самостоятельно, то это синтаксис. Но в этом нет необходимости, так как он должен автоматически удаляться, если вы сами его не объявите. 28.03.2013
  • @MikeSeymour Проблема в том, что если я не объявлю конструктор удаленной копии, компилятор попытается сам синтезировать тот, который не удален, а затем вырвет весь мой код. 28.03.2013
  • @Mushy: Тогда либо ваш компилятор неисправен, либо вы не объявили конструктор перемещения. Я понятия не имею, в чем дело, поскольку вы не разместили никакого кода для демонстрации проблемы. 28.03.2013
  • @MikeSeymour Я не уверен, что происходит, но я объявил копию = удалить. 28.03.2013
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..