Difference between std :: uninitialized_copy and std :: copy?


I'm trying both and they always return the same to me. Is there a specific case where only one of the two can be used?

// Example 1:

std::allocator<int> alloc;
int arr[5]{7,7,7,7,7 };
int *arr2 = new int[5]{5,5,5,5,5};

std::uninitialized_copy(arr, arr + 5, arr2);
//std::copy(arr, arr + 5, arr2);

for (std::size_t i{ 0 }; i < 5;++i)
    std::cout << *(arr2+i) << " ";*/
//output de ambos algoritmos: 7 7 7 7 7;

// Example 2:

std::allocator<int> alloc;
int *arr{ alloc.allocate(5) };
int *arr2 = new int[5]{5,5,5,5,5};

//std::uninitialized_copy(arr, arr + 5, arr2);
std::copy(arr, arr + 5, arr2);

for (std::size_t i{ 0 }; i < 5;++i)
    std::cout << *(arr2+i) << " ";
//output para ambos algoritmos: -842150451 -842150451 -842150451 -842150451 -842150451*/
asked by Arkadiusz 14.12.2018 в 15:09

1 answer


std::unitialized_copy is used when arr2 only points to an uninitialized memory region. For example, if you used malloc . In this way std::uninitialized_copy is responsible, first, to initialize the container that will host the elements and then make the copy.

On the other hand, std::copy is limited to copying the elements.

And what is an uninitialized memory region?

Uninitialized memory means that which has been reserved with, for example, malloc . A function inherited from C that only reserves memory, that is, does not invoke any constructor implicitly.

If we talk about native types (pointer to int , for example), there is no difference. But if we talk about objects then the thing changes since an uninitialized object is not safe to use since it does not have a valid state.

An example:

void* memoria = malloc(1000);
std::string * str = reinterpret_cast<std::string*>(memoria);

*str = "abcdef"; // Más que probable error en ejecución.

So, when can not can std::copy be used?

Basically when we have a memory region not initialized .

A silly example taken from the documentation . when replacing std::uninitialized_copy with std::copy we get a nice segmentation error:

int main()
    const char *v[] = {"This", "is", "an", "example"};

    auto sz = std::size(v);

    if(void *pbuf = std::aligned_alloc(alignof(std::string), sizeof(std::string) * sz))
            auto first = static_cast<std::string*>(pbuf);
            auto last = std::copy(std::begin(v), std::end(v), first);

            for (auto it = first; it != last; ++it)
                std::cout << *it << '_';

            std::destroy(first, last);
        catch(...) {}

On the other hand, using std::uninitialized_copy when we already have the initialized memory could create memory leaks, since we will not try to destroy what already exists in the memory. When the memory is initialized, the corresponding constructor will be invoked and that could cause pointers to be lost to regions of memory reserved by the object that existed in that region of memory.

answered by 14.12.2018 в 15:28