Вопрос по visual-studio-2012, visual-c++, compatibility – Почему bad_alloc (const char *) стал закрытым в Visual C ++ 2012?

7

Я просто пытаюсь скомпилировать немного больший проект с использованием кандидата на выпуск Visual Studio 2012, C ++. Проект был / скомпилирован с использованием VS2010 сейчас. (Я просто жадный, чтобы получить вещи C ++ 11, поэтому я попытался. :)

Помимо вещей, которые я могу объяснить сам, в проекте используется такой код:

ostringstream ostr;
ostr << "The " __FUNCTION__ "() failed to malloc(" << i << ").";
throw bad_alloc(ostr.str().c_str());

Компилятор сейчас жалуется

error C2248: 'std::bad_alloc::bad_alloc' : cannot access private member declared 
    in class 'std::bad_alloc'

... что является правдой. Эта версия конструктора теперь приватная.

По какой причине эта версия конструктора была закрытой? Стандарт C ++ 11 рекомендует не использовать этот конструктор с аргументом?

(Я могу себе представить, что если распределение не удалось, это может вызвать больше проблем, чтобы попытаться создать что-то новое. Однако это только мое предположение.)

Спасибо,     Petr

Ваш Ответ

2   ответа
1

: bad_alloc, подходящим методом будет определение внутреннего класса, производного от std :: bad_alloc, и переопределение & # x2018; what & # x2019; предоставить соответствующее сообщение.

Вы можете сделать класс общедоступным и напрямую вызвать конструктор присваивания или создать вспомогательную функцию, например throw_bad_alloc, которая принимает параметры (и дополнительную скалярную информацию) и сохраняет их во внутреннем классе.

Сообщение не отформатировано до & # x2018; what & # x2019; называется. Таким образом, разматывание стека могло освободить часть памяти, поэтому сообщение можно отформатировать с фактической причиной (исчерпание памяти, неправильный размер запроса, повреждение кучи и т. Д.) На узле перехвата. Если форматирование не удается, просто назначьте и верните статическое сообщение.

Урезанный пример:

(Совет: конструктор копирования может просто назначить _Message для nullptr, а не копировать сообщение, поскольку сообщение форматируется по требованию. Конструктор перемещения, конечно, может просто конфисковать его :-).

class internal_bad_alloc: public std::bad_alloc
   {
   public:
      // Default, copy and move constructors....

      // Assignment constructor...
      explicit internal_bad_alloc(int errno, size_t size, etc...) noexcept:
         std::bad_alloc()
         {
         // Assign data members...
         }

      virtual ~internal_bad_alloc(void) noexcept
         {
         // Free _Message data member (if allocated).
         }

      // Override to format and return the reason:
      virtual const char* what(void) const noexcept
         {
         if (_Message == nullptr)
            {
            // Format and assign _Message.  Assign the default if the
            // format fails...
            }
         return _Message;
         }

   private:
      // Additional scalar data (error code, size, etc.) pass into the
      // constructor and used when the message is formatted by 'what'...
      mutable char* _Message;
      static  char  _Default[];
   }
};

//
// Throw helper(s)...
//
extern void throw_bad_alloc(int errno, size_t size, etc...)
   {
   throw internal_bad_alloc(errno, size, etc...);
   }
14

bad_alloc как таковой (18.6.2.1):

class bad_alloc : public exception {
public:
    bad_alloc() noexcept;
    bad_alloc(const bad_alloc&) noexcept;
    bad_alloc& operator=(const bad_alloc&) noexcept;
    virtual const char* what() const noexcept;
};

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

Стандарт C ++ 03 определяет аналогичный набор конструкторов, поэтому VS не следовал этой части стандарта даже до C ++ 11. MS действительно пытается сделать VS как можно более совместимым со стандартом, поэтому они, вероятно, просто воспользовались случаем (новый VS, новый стандарт), чтобы исправить несовместимость.

Edit: Теперь, когда я видел код VS2012, также стало ясно, почему упомянутый конструктор остается закрытым, а не полностью удаляется: кажется, что этот конструктор используется только один раз, вbad_array_new_length учебный класс. Такbad_array_new_length объявленfriend в bad_alloc, и поэтому может использовать этот закрытый конструктор. Этой зависимости можно было бы избежать, если быbad_array_new_length просто сохранил сообщение в указателе, используемомwhat(), но в любом случае кода не так много.

Большое спасибо за подробный ответ. pepr

Похожие вопросы