Использование 'new' в шаблонном классе безопасно для типов? - PullRequest
0 голосов
/ 25 мая 2018

Я работаю над своей собственной векторной реализацией, и один из парней сказал по IRC, что использование 'new' для выделения памяти в шаблонном классе небезопасно.Например, в этом коде:

// resize array when needed
template <class T>
void myVector<T>::resize()
{
    vCapacity += 5;
    T* temp = new T[vCapacity]();

    for (unsigned i = 0; i < vCapacity; i++) temp[i] = vArray[i];

    delete [] vArray;
    vArray = temp;
    temp = nullptr;
}

Это правда?Когда я изучал C ++, никто не упомянул об этом, и, если я не ошибаюсь, когда компилятор компилирует шаблонный класс / функцию, он заменит 'T' правильными типами.

Ответы [ 2 ]

0 голосов
/ 25 мая 2018

Компилятор сгенерирует некоторую временную функцию, подобную этой, если вы вызовете ее для вектора типа int:

void myVector_int::resize()
{
  vCapacity += 5;
  int* temp = new int[vCapacity]();

  for (unsigned i = 0; i < vCapacity; i++) temp[i] = vArray[i];

  delete [] vArray;
  vArray = temp;
  temp = nullptr;
}

, и, таким образом, это фактически «нормальная» функция с «нормальным» типом, которая делаетэто совершенно безопасно.Таким образом, вы совершенно правы, что компилятор заменяет T фактическим типом.

0 голосов
/ 25 мая 2018

Это не правильно.new возвращает "правильно введенный указатель" , то есть T* в выделенную память.Он так же безопасен, как и запись new int.

Однако, более неясный ::operator new (который не совпадает с new) возвращает void*, но может быть статически приведен к T*.Даже это типобезопасно, если вы позволите ему быть типобезопасным (не пытаясь сделать что-то потенциально опасное, например, reinterpret_cast с помощью указателя).

Кроме того, когда вы создаете экземпляр template <class T> vector с помощью T ипоследовательно используйте T в vector (выделение, освобождение, арифметика указателей, ...), когда-либо задействован только один тип - T.Это так же безопасно, как написать целое vector с явным типом (неуниверсальным вектором).

Это также верно для delete и operator delete.


Вы имелидополнительный вопрос

когда компилятор скомпилирует этот код, «новый» ли выделит пространство памяти для правильного типа?

Да.Он выделит память для типа, который вы предоставляете.Если вы попросите память для хранения 10x 32-битных int с, вы получите int* для первых int из 320 бит памяти.Если вы попросите 10x n-битных MyClass es, вы получите MyClass* для первых MyClass в 10n битах памяти.Это хорошая рабочая модель.

sidenote: type - языковая конструкция.Это не существует в памяти.Наиболее близким является утверждение о том, что типы существуют неявно при использовании различных инструкций (iadd, idivq, fadd, fdiv, ...).Но это не совсем понятно (если вам интересно - взгляните на язык ассемблера и дизайн процессора).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...