Phobos D'thorga Phobos D'thorga - 1 year ago 48
C++ Question

A templated 'strdup()'?

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;

Is this proper? Can I expect any errors from this when using an int, long, etc.? I'm very new to generic programming and am trying to learn more.

Answer Source

No this is not proper ! When you have a malloc() in C++ code, you should become very suspicious:

  • malloc() allocates memory, but doesn't properly create objects. The only way to work with such memory would be to use a placement new.
  • memcpy() doesn't respect the copy semantic of C++ objects. This could only work with trivially copiable classes. I would cause hard to find bugs elsewhere (shallow copies, and other awful things that lead to UB).

For basic types like char, int, double, it would work. But not for more complex types.

Alternative 1: adapt your code to properly create and copy objects

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;

Attention: risk of memory leakage if user forget to delete the array, or UB if user doesnet use delete[] ! To avoid this you could opt for returning unique_ptr<T[]>.

Alternative 2: Get rid of arrays and pointers and memory nightmares: use vectors !

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;

And this is so trivial that you could consider creating the vector and use copy() directly in the using code: You'll soon discover that there are also copy_if(), copy_backwards() and some other nice <algorithms> that could be used depending on circumstances.