Search code examples
c++vectoriteratoradapter

How differ a pointer to first element of a vector vs back_inserter() of that vector?


I know back_inserter is a container "adapter", but what does it mean? If I take the example of function std::copy(), which takes as the third argument output iterator/pointer of vector TO copy, then I should give back_inserter instead of last iterator of that vector:

#include <vector>
#include <algorithm>
#include <stdio.h>

using namespace std;

int main(){
    vector<int> vec1 = {1,2};
    vector<int> vec2 = {3,4};
    copy(vec2.begin(), vec2.end(), back_inserter(vec1)); //back_inserter used to enhance memory allocation for 2 new elements?
    for(auto i:vec1){
        printf("%i\n", i);
    }
}

Works fine, however this version does not:

#include <vector>
#include <algorithm>
#include <stdio.h>

using namespace std;

int main(){
    vector<int> vec1 = {1,2};
    vector<int> vec2 = {3,4};
    copy(vec2.begin(), vec2.end(), vec1.end()); // the same pointer as gives back_inserter but without any fancy allocation and therefor crash?
    for(auto i:vec1){
        printf("%i\n", i);
    }
}

Now I just gave the last iterator/pointer of the vector TO copy. So what is the job of the back_inserter container adapter? As it seems for me now, it only does the job of allocation space for new elements, whereas "only" last pointer does not suffice. Can I do a manual job via malloc to enlarge that vector/container?


Solution

  • The STL is designed with 3 major concepts:

    • containers
      • hold element(s)
      • know about/create iterators
      • don't know about generic algorithms.
    • iterator
      • refers to an element (or end), and can modify the elements
      • don't know about algorithms
      • don't know about the container their elements are in* (and thus cannot modify the container in size or otherwise)
    • algorithms
      • generically work with iterators
      • do not know about containers

    A back-inserter, however, looks and behaves like an iterator, and as far as the algorithms are concerned, it is an iterator. But as a container adapter, it also has a reference to the container and can modify it (via "push_back") when you write into its iterator interface. This allows algorithms to opaquely write into it as an iterator and (without realizing it) also be able to modify the container too.

    (*) Occasionally a debugging implementation of iterators will know about containers but that's an internal implementation detail that is not usable by the ordinary public interface.