0

How do I create an array on the heap and initialize it at construction time from another array?

template <typename T>
T* Copy(T* myOriginalArray, size_t myOriginalArraySize)
{
    T* copy = new T[myOriginalArraySize]; // copy data from myOriginalArray here too
    return copy;
}

I could create the array and then use std::copy, but this would require the array contents to have an empty constructor. You can assume the object has a copy and move constructor. I have access to C++17.

10
  • 3
    You should not return raw pointer to dynamically allocated memory from a function unless you love to debug memory leaks Commented May 10, 2017 at 14:31
  • Use std::array. It has a proper copy constructor already. Commented May 10, 2017 at 14:31
  • 1
    Then use std::vector Commented May 10, 2017 at 14:34
  • 1
    Arrays are C stuff, I doubt you could properly use move semantics with them. Commented May 10, 2017 at 14:53
  • 1
    I think this can be done with placement new, alignof and some casting, but it would be hideously complicated to avoid undefined behavior. Commented May 10, 2017 at 15:04

2 Answers 2

2

You use ::operator new and std::uninitialized_copy

#include<memory>
#include<new>

template<typename T>
T* Copy(T* src, size_t sz)
{
    auto buf = static_cast<T*>(::operator new(sizeof(T) * sz));
    std::uninitialized_copy(src, src + sz, buf);
    return buf;    
}

And possibly move, with a bit more hassle.

#include<utility>

template<typename T>
T* Move(T* src, size_t sz)
{
    auto buf = static_cast<T*>(::operator new(sizeof(T) * sz));
    for(size_t i = 0; i < sz; i++)
        new (buf + i) T(std::move(src[i]));
    return buf;
}

This is not really a great idea, considering then you have to deallocate with some crazy code

template<typename T>
void Delete(T* src, size_t sz)
{
    for(size_t i = 0; i < sz; i++)
        src[i].~T();
    ::operator delete(src);
}

Do consider using std::vector instead.

Side note

Q: Why index with size_t instead of using T*?
A: As it turns out, it is currently slightly faster with indexing.

Sign up to request clarification or add additional context in comments.

1 Comment

This what I am looking for(the same as jdehesa's answer but more complete). Concern about destroying is righteous. Goal about question for me is learning how stuff like std::vector works internally.
0

Not sure if this is what you are asking, but you can just allocate the memory first and then use placement new (which is basically what preallocating STL containers do anyway).

template <typename T>
T* Copy(T* myOriginalArray, size_t myOriginalArraySize)
{
    auto t_size = sizeof(T);
    T* copy = (T *) new char[myOriginalArraySize * t_size];
    for (size_t i = 0; i < myOriginalArraySize; i++)
    {
        new (copy + i) T(*(myOriginalArray + i));
    }
    return copy;
}

3 Comments

I do not, that the problem I tried to explain to OP
Actually I do think its possibly with some ugliness involved
The move thing confuses me. As far as I can see there is no moving involved. Array of objects is allocated without actual construction. Objects are constructed in place one by one using their copy constructor. Pointer to heap array is returned. Explanation of where move semantics are missing would be appreciated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.