Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize new[] using copy constructor

Tags:

I believe this is a simple question with probably a not simple answer.

Here is the code:

template<typename T>
T* copy(T* original, int size) {
    T* result = new T[size];
    // At this point the default constructor of all new T objects have been called.

    for(int i = 0; i < size; ++i) {
        // This will call the assignment operator= on all new T objects
        result[i] = original[i];
    }
    return result;
}

Question:

Is there a way to initialize the newly allocated memory using the copy constructor of T instead of using default constructor followed by assignment operator?

The purpose is to copy each element to its analogous element in the new array using the copy constructor of T.

I imagine there could be a way to do that by allocating memory using malloc, then calling the copy constructor for each element but I don't know how.

Here is an example solution from my imagination. If this is correct or this is the best we can get, tell me. Or propose a better solution:

template<typename T>
T* copy(T* original, int size) {
    T* result = malloc(sizeof(T)*size);
    // At this point the default constructor of all new T objects have been called.

    for(int i = 0; i < size; ++i) {
        T t(original[i]);
        memcpy(result+i*sizeof(T), &t, sizeof(T));
    }
    return result;
}

Note: Raw pointers are being used for simplicity.

Note 2: I don't need a vector. This pattern will be used to copy the underlying data structure of more complicated objects.

like image 213
Meena Alfons Avatar asked May 16 '20 10:05

Meena Alfons


People also ask

How do you create a copy constructor for an array?

Array(const Array &) is an example of a copy constructor. In general the standard syntax for a copy constructor is X::X(X&) , where X is any class name. That is, it is the constructor of class X which takes as its argument a reference to an object of class X. The copy constructor makes a copy of an existing object.

Does copy constructor create new object?

A copy constructor is a member function that initializes an object using another object of the same class. In simple terms, a constructor which creates an object by initializing it with an object of the same class, which has been created previously is known as a copy constructor.

How do you initialize a constructor?

There are two ways to initialize a class object: Using a parenthesized expression list. The compiler calls the constructor of the class using this list as the constructor's argument list. Using a single initialization value and the = operator.

What is the use of copy constructor in C++?

What is a Copy Constructor? A constructor is used to initialize an object. A copy constructor is a member function of a class that initializes an object with an existing object of the same class. In other words, it creates a copy of an already existing object and stores it in a new object.


1 Answers

You will have to allocate memory by any other means, but keep in mind that size * sizeof(T) can overflow. std::allocator takes care of this.

Use std::uninitialized_copy/std::uninitialized_copy_n to perform the copy:

template<typename T>
T* copy(T* original, int size) {
    std::allocator<T> alloc;
    T* result = alloc.allocate(size);
    try {
        std::uninitialized_copy_n(original, size, result);
    } catch (...) {
        alloc.deallocate(result, size);
        throw;
    }
    return result;
}

Later you can use std::destroy/std::destroy_n to destroy them and deallocate memory:

template<typename T>
void destroy(T* ptr, int size)
{
    std::destroy_n(ptr, size);
    std::allocator<T>().deallocate(ptr, size);
}

This should work unless you need to be able to delete them with operator delete[] - in which case there is no solution for this.

If you are implementing a custom container, you can use template allocator like standard containers do:

template<typename T, typename Allocator = std::allocator<T>>
struct container
{
    [[no_unique_address]] Allocator allocator;
    ...
};
like image 69
StaceyGirl Avatar answered Sep 28 '22 09:09

StaceyGirl