2014-01-14 2 views
6

У меня есть код, который я бы хотел переключить с C++ 03 на C++ 11.Перенос кода с C++ 03 на C++ 11: Должен ли я быть осторожным относительно неявного конструктора перемещения по умолчанию?

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

В одном примере у меня есть класс, который обертывает ручку iconv_t от libiconv для использования RAII.

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

class iconv_wrapper 
{ 
    public: 
    iconv_wrapper() : m_iconv(iconv_open()) {} 
    ~iconv_wrapper() { iconv_close(m_iconv); } 
    private: 
    // Not implemented: non copyable. Should probably be = delete; in C++11. 
    iconv_wrapper(const iconv_wrapper&); 
    iconv_wrapper& operator=(const iconv_wrapper&); 

    iconv_t m_iconv; 
}; 

Моего беспокойство: если экземпляр этого класса случился быть перемещен, это приведет к двойному вызову iconv_close(). Поскольку iconv_t является «немым» интегральным типом, я не ожидаю, что реализация по умолчанию iconv_wrapper(iconv_wrapper&&) приведет к аннулированию члена R. Даже если бы это было так, деструктор не был реализован, чтобы справиться с этим должным образом.

Так что мои вопросы:

  • ли мои опасения законным? Правильно ли, что движимый конструктор/оператор по умолчанию = будет некорректным в таком случае?
  • Какие изменения я могу внести, чтобы хорошо переносить этот код на C++ 11? (Я предложил std::unique_ptr, но я не мог сделать эту работу хорошо, как он ожидает, что указатель, а не какой-то непрозрачный тип)
+0

Я не думаю, что у этих классов были бы неявные конструкторы копирования или операторы присваивания, так как они объявляют пользовательский конструктор копирования и оператор присваивания. – juanchopanza

+0

Имеет ли значение 'iconv_t' значение« null »? – woolstar

+0

@ woolstar: [documentation] (http://pubs.opengroup.org/onlinepubs/7908799/xsh/iconv_open.html) говорит, что 'iconv_open()' возвращает '(iconv_t) -1' в случае сбоя. Поэтому я думаю, что мы можем предположить, что это значение «NULL». – ereOn

ответ

9

Он не будет перемещен. Поскольку у вас есть объявленный конструктор копирования, оператор присваивания копий и деструктор, конструктор перемещения и оператор назначения перемещения не будут сгенерированы. Фактически, любой из этих трех объявил бы подавить автоматическую генерацию конструктора перемещения и оператора назначения перемещения.

Если вы хотите, чтобы сделать его более C++ 11 дружеский, можно добавить конструктор перемещения и перемещения оператора присваивания, как в (предупреждение: никогда не компилируется или испытания):

class iconv_wrapper 
{ 
    public: 
    iconv_wrapper() : m_iconv(iconv_open()) {} 
    ~iconv_wrapper() { if ((iconv_t)-1 != m_iconv) iconv_close(m_iconv); } 
    iconv_wrapper(iconv_wrapper&& that) noexcept { std::swap(m_iconv, that.m_iconv); } 
    iconv_wrapper& operator=(iconv_wrapper&& that) noexcept { std::swap(m_iconv, that.m_iconv); return *this; } 

    private: 
    iconv_t m_iconv = (icontv_t)-1; 
}; 

причина, вы, возможно, захотите сделать это, чтобы вы могли хранить эти объекты (или другие типы, содержащие эти объекты) в векторе.

+0

+1 и, IIRC, на самом деле, любой из них подавляет поколение остальных? см. RuleOfFive/RuleOfNone, если я не испортил его полностью;) – quetzalcoatl

+0

Спасибо, это заставляет меня чувствовать себя более уверенно в миграции. Любой намек на то, как я мог бы сделать этот класс подвижным? Кажется, это очень хороший кандидат. – ereOn

+0

Удивительный ответ: полный и точный. Большое спасибо. – ereOn

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