Screenplay: std::vector And std::copy()

std::vector<> Into C Array

#include <vector>
#include <iostream>
   
int main()
{
    std::vector<int> src = {100, 200, 300};
    int dst[3];

    std::copy(src.begin(), src.end(), dst);
    for (int i: dst)
        std::cout << i << std::endl;

    return 0;
}
  • The code above allocates a C array on the stack, of sufficient size

  • this is crucial!

Copying Into std::vector (Without Allocation)

  • Remember, std::vector<> is empty by default

  • This code will crash:

#include <vector>
#include <iostream>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnonnull"
   
int main()
{
    std::vector<int> src = {100, 200, 300};
    std::vector<int> dst;                             // <--- ATTENTION: empty!!

    std::copy(src.begin(), src.end(), dst.begin());   // <--- CRASH!
    for (int i: dst)
        std::cout << i << std::endl;

    return 0;
}

#pragma GCC diagnostic pop

Solution 1: Pre-allocate Destination

  • Using src.size()

  • Pre-initialization, allocating the destination just as big as needed

#include <vector>
#include <iostream>
   
int main()
{
    std::vector<int> src = {100, 200, 300};
    std::vector<int> dst(src.size());                 // <-- initialize dst to contain three default-constructed elements

    std::copy(src.begin(), src.end(), dst.begin());   // <--- those are overwritten here
    for (int i: dst)
        std::cout << i << std::endl;

    return 0;
}
  • Using .reserve() if destination’s memory is not known to be pre-allocated

#include <vector>
#include <iostream>
   
int main()
{
    std::vector<int> src = {100, 200, 300};
    std::vector<int> dst;

    dst.reserve(src.size());                        // <--- makes dst contain three default-constructed element

    std::copy(src.begin(), src.end(), dst.begin()); // <--- those are overwritten here
    for (int i: dst)
        std::cout << i << std::endl;

    return 0;
}

Solution 2: std::back_insert_iterator

  • Acts as if copied elements were appended with .push_back()

#include <vector>
#include <iostream>
   
int main()
{
    std::vector<int> src = {100, 200, 300};
    std::vector<int> dst;                             // <-- empty

    std::copy(src.begin(), src.end(),
              std::back_insert_iterator<std::vector<int>>(dst));

    for (int i: dst)
        std::cout << i << std::endl;

    return 0;
}