2016-09-25 5 views
1
template<typename T> 
static T *anydup(const T *src, size_t len) { 
    T *ptr = malloc(len * sizeof(T)); 
    memcpy(ptr, src, (len * sizeof(T))); 
    return ptr; 
} 

Действительно ли это? Могу ли я ожидать каких-либо ошибок от этого при использовании int, long и т. Д.? Я очень новичок в родовом программировании и стараюсь больше узнать.Шаблоны 'strdup()'?

+5

'memcpy' - недействительный способ создания объектов в целом. Так что нет, не делай этого. Попробуйте 'std :: vector ' вместо этого. –

+3

Ни один из 'malloc' не является допустимым способом создания объектов. –

+0

Правильный способ дублирования некоторых 'src' -' auto src2 {src}; '. – nwp

ответ

2

Нет, это не правильно! Если у вас есть malloc() в C++ код, вы должны стать очень подозрительным:

  • malloc() выделяет память, но не правильно создавать объекты. Единственный способ работать с такой памятью - использовать новое место размещения.
  • memcpy() не уважает семантику копии объектов C++. Это может работать только с тривиально-гибкими классами. Я затрудняюсь найти ошибки в другом месте (мелкие копии и другие ужасные вещи, которые приводят к UB).

Для базовых типов, таких как char, int, double, он будет работать. Но не для более сложных типов.


Альтернатива 1: адаптировать свой код, чтобы правильно создавать и копировать объекты

template<typename T> 
T *anydup (const T *src, size_t len) { 
    T *ptr = new T[len];      // requires that T has a default constructor 
    copy (src, src+len, ptr);     // requires that T is copyiable 
    return ptr; 
} 

Внимание: риск утечки памяти, если пользователь забыл удалить массив, или UB, если пользователь использовать doesnet delete[]! Чтобы этого избежать, вы можете выбрать для возврата unique_ptr<T[]>.


Альтернатива 2: избавиться от массивов и указателей и кошмаров памяти: использовать векторы!

template<typename T> 
vector<T> anydup (const vector<T> src) { 
    vector<T> v(len);      // requires that T has a default constructor 
    copy (src.cbegin(), src.cend(), v);  // requires that T is copyable 
    return v; 
} 

Вы могли бы рассмотреть возможность создания вектора, используя конструктор копирования, как предложено Remy Лебо и FDinoff в комментариях, либо в функции или непосредственно в использовании кода.

Если вы используете copy() непосредственно в использовании кода, вы скоро обнаружите, что есть также copy_if(), copy_backwards() и некоторые другие приятные <algorithms>, которые могут быть использованы в зависимости от обстоятельств.

+1

@ PhobosD'thorga приветствую вас! см. мое редактирование для альтернативных решений. Я не тестировал его, поэтому в нем могут быть опечатки. – Christophe

+0

Вау, спасибо! И примеры фантастические. Я действительно изучил кучу в отношении слияния двух миров C и C++ :) Если я могу задать еще одну вещь, что означает «UB»? –

+5

В альтернативе 2. Пожалуйста, просто используйте конструктор копирования и не создавайте метод anydup. – FDinoff