C++ vector's insert & push_back difference - c++

I want to know what are difference(s) between vector's push_back and insert functions.
Is there a structural difference(s)?
Is there a really big performance difference(s)?

The biggest difference is their functionality. push_back always puts a new element at the end of the vector and insert allows you to select new element's position. This impacts the performance. vector elements are moved in the memory only when it's necessary to increase it's length because too little memory was allocated for it. On the other hand insert forces to move all elements after the selected position of a new element. You simply have to make a place for it. This is why insert might often be less efficient than push_back.

The functions have different purposes. vector::insert allows you to insert an object at a specified position in the vector, whereas vector::push_back will just stick the object on the end. See the following example:
using namespace std;
vector<int> v = {1, 3, 4};
v.insert(next(begin(v)), 2);
v.push_back(5);
// v now contains {1, 2, 3, 4, 5}
You can use insert to perform the same job as push_back with v.insert(v.end(), value).

Beside the fact, that push_back(x) does the same as insert(x, end()) (maybe with slightly better performance), there are several important thing to know about these functions:
push_back exists only on BackInsertionSequence containers - so, for example, it doesn't exist on set. It couldn't because push_back() grants you that it will always add at the end.
Some containers can also satisfy FrontInsertionSequence and they have push_front. This is satisfied by deque, but not by vector.
The insert(x, ITERATOR) is from InsertionSequence, which is common for set and vector. This way you can use either set or vector as a target for multiple insertions. However, set has additionally insert(x), which does practically the same thing (this first insert in set means only to speed up searching for appropriate place by starting from a different iterator - a feature not used in this case).
Note about the last case that if you are going to add elements in the loop, then doing container.push_back(x) and container.insert(x, container.end()) will do effectively the same thing. However this won't be true if you get this container.end() first and then use it in the whole loop.
For example, you could risk the following code:
auto pe = v.end();
for (auto& s: a)
v.insert(s, pe);
This will effectively copy whole a into v vector, in reverse order, and only if you are lucky enough to not get the vector reallocated for extension (you can prevent this by calling reserve() first); if you are not so lucky, you'll get so-called UndefinedBehavior(tm). Theoretically this isn't allowed because vector's iterators are considered invalidated every time a new element is added.
If you do it this way:
copy(a.begin(), a.end(), back_inserter(v);
it will copy a at the end of v in the original order, and this doesn't carry a risk of iterator invalidation.
[EDIT] I made previously this code look this way, and it was a mistake because inserter actually maintains the validity and advancement of the iterator:
copy(a.begin(), a.end(), inserter(v, v.end());
So this code will also add all elements in the original order without any risk.

I didn't see it in any of the comments above but it is important to know:
If we wish to add a new element to a given vector and the new size of the vector (including the new element) surpasses the current vector capacity it will cause an automatic reallocation of the allocated storage space.
And Beacuse memory allocation is an action we wish to minimize it will increase the capacity both in push_back and insert in the same way (for a vector with n elemeny will add about n/2).
So in terms of memory efficiency it is safe to say, use what ever you like best.
for example:
std::vector<int> test_Insert = { 1,2,3,4,5,6,7 };
std::vector<int> test_Push_Back = { 1,2,3,4,5,6,7 };
std::cout << test_Insert.capacity() << std::endl;
std::cout << test_Push_Back.capacity() << std::endl;
test_Insert.push_back(8);
test_Push_Back.insert(test_Push_Back.end(), 8);
std::cout << test_Insert.capacity() << std::endl;
std::cout << test_Push_Back.capacity() << std::endl;
This code will print:
7
7
10
10

Since there's no actual performance data, I reluctantly wrote some code to produce it. Keep in mind that I wrote this code because I wondered "Should I push_back multiple single elements, or use insert?".
#include <iostream>
#include <vector>
#include <cassert>
#include <chrono>
using namespace std;
vector<float> pushBackTest()
{
vector<float> v;
for(int i =0;i<10000000;i++)
{
// Using a for-loop took 200ms more (in the output)
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(6);
v.push_back(7);
v.push_back(8);
v.push_back(9);
}
return v;
}
vector<float> insertTest()
{
vector<float> v;
for(int i =0;i<10000000;i++)
{
v.insert(v.end(), {0,1,2,3,4,5,6,7,8,9});
}
return v;
}
int main()
{
std::chrono::steady_clock::time_point start = chrono::steady_clock::now();
vector<float> a = pushBackTest();
cout<<"pushBackTest: "<<chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count()<<"ms"<<endl;
start = std::chrono::steady_clock::now();
vector<float> b = insertTest();
cout<<"insertTest: "<<chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count()<<"ms"<<endl;
assert(a==b);
return 0;
}
Output:
pushBackTest: 5544ms
insertTest: 3402ms
Since curiosity killed my time, I run a similar test but adding a single number instead of multiple ones.
So, the two new functions are:
vector<float> pushBackTest()
{
vector<float> v;
for(int i =0;i<10000000;i++)
{
v.push_back(1);
}
return v;
}
vector<float> insertTest()
{
vector<float> v;
for(int i =0;i<10000000;i++)
{
v.insert(v.end(), 1);
}
return v;
}
Output:
pushBackTest: 452ms
insertTest: 615ms
So, if you wanna add batch of elements, insert is faster, otherwise push_back it is. Also, keep in mind that push_back can only push... back, yeah.

Related

Insert or push_back to end of a std::vector?

Is there any difference in performance between the two methods below to insert new elements to the end of a std::vector:
Method 1
std::vector<int> vec = { 1 };
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);
Method 2
std::vector<int> vec = { 1 };
int arr[] = { 2,3,4,5 };
vec.insert(std::end(vec), std::begin(arr), std::end(arr));
Personally, I like method 2 because it is nice and concise and inserts all the new elements from an array in one go. But
is there any difference in performance?
After all, they do the same thing. Don't they?
Update
The reason why I am not initializing the vector with all the elements, to begin with, is that in my program I am adding the remaining elements based on a condition.
After all, they do the same thing. Don't they?
No. They are different. The first method using std::vector::push_back will undergo several reallocations compared to std::vector::insert.
The insert will internally allocate memory, according to the current std::vector::capacity before copying the range. See the following discussion for more:
Does std::vector::insert reserve by definition?
But is there any difference in performance?
Due to the reason explained above, the second method would show slight performance improvement. For instance, see the quick benck-mark below, using http://quick-bench.com:
See online bench-mark
Or write a test program to measure the performance(as #Some programmer dude mentioned in the comments). Following is a sample test program:
#include <iostream>
#include <chrono>
#include <algorithm>
#include <vector>
using namespace std::chrono;
class Timer final
{
private:
time_point<high_resolution_clock> _startTime;
public:
Timer() noexcept
: _startTime{ high_resolution_clock::now() }
{}
~Timer() noexcept { Stop(); }
void Stop() noexcept
{
const auto endTime = high_resolution_clock::now();
const auto start = time_point_cast<microseconds>(_startTime).time_since_epoch();
const auto end = time_point_cast<microseconds>(endTime).time_since_epoch();
const auto durationTaken = end - start;
const auto duration_ms = durationTaken * 0.001;
std::cout << durationTaken.count() << "us (" << duration_ms.count() << "ms)\n";
}
};
// Method 1: push_back
void push_back()
{
std::cout << "push_backing: ";
Timer time{};
for (auto i{ 0ULL }; i < 1000'000; ++i)
{
std::vector<int> vec = { 1 };
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);
}
}
// Method 2: insert_range
void insert_range()
{
std::cout << "range-inserting: ";
Timer time{};
for (auto i{ 0ULL }; i < 1000'000; ++i)
{
std::vector<int> vec = { 1 };
int arr[] = { 2,3,4,5 };
vec.insert(std::end(vec), std::cbegin(arr), std::cend(arr));
}
}
int main()
{
push_back();
insert_range();
return 0;
}
release building with my system(MSVS2019:/Ox /std:c++17, AMD Ryzen 7 2700x(8-core, 3.70 Ghz), x64 Windows 10)
// Build - 1
push_backing: 285199us (285.199ms)
range-inserting: 103388us (103.388ms)
// Build - 2
push_backing: 280378us (280.378ms)
range-inserting: 104032us (104.032ms)
// Build - 3
push_backing: 281818us (281.818ms)
range-inserting: 102803us (102.803ms)
Which shows for the given scenario, std::vector::insert ing is about 2.7 times faster than std::vector::push_back.
See what other compilers(clang 8.0 and gcc 9.2) wants to say, according to their implementations: https://godbolt.org/z/DQrq51
There may be a difference between the two approaches if the vector needs to reallocate.
Your second method, calling the insert() member function once with an iterator range:
vec.insert(std::end(vec), std::begin(arr), std::end(arr));
would be able to provide the optimisation of allocating all the memory needed for the insertion of the elements in one blow since insert() is getting random access iterators, i.e., it takes constant time to know the size of the range, so the whole memory allocation can be done before copying the elements, and no reallocations during the call would follow.
Your first method, individual calls to the push_back() member function, may trigger several reallocations, depending on the number of elements to insert and the memory initially reserved for the vector.
Note that the optimisation explained above may not be available for forward or bidirectional iterators since it would take linear time in the size of the range to know the number of elements to be inserted. However, the time needed for multiple memory allocations likely dwarfs the time needed to calculate the length of the range for these cases, so probably they still implement this optimisation. For input iterators, this optimisation is not even possible since they are single-pass iterators.
The major contributing factor is going to be the re-allocations. vector has to make space for new elements.
Consider these 3 sinppets.
//pushback
std::vector<int> vec = {1};
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);
//insert
std::vector<int> vec = {1};
int arr[] = {2,3,4,5};
vec.insert(std::end(vec), std::begin(arr), std::end(arr));
//cosntruct
std::vector<int> vec = {1,2,3,4,5};
To confirm the reallocations coming into picture, after adding a vec.reserve(5) in pushback and insert versions, we get the below results.
push_back inserts a single element, hence in the worst case you may encounter multiple reallocations.
For the sake of the example, consider the case where the initial capacity is 2 and increases by a factor of 2 on each reallocation. Then
std::vector<int> vec = { 1 };
vec.push_back(2);
vec.push_back(3); // need to reallocate, capacity is 4
vec.push_back(4);
vec.push_back(5); // need to reallocate, capacity is 8
You can of course prevent unnecessary reallocations by calling
vec.reserve(num_elements_to_push);
Though, if you anyhow insert from an array, the more idomatic way is to use insert.

Erase elements from a vector of pointers and deallocate the dynamic memory previously allocated via new operator?

I want to show you this very simple example, the purpose is to sort some strings allocated dynamically and clean the duplicates resizing the vector and deallocating useless occupated memory.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
void print_v (vector<string *>& v)
{
cout << "----" << endl;
for (string*& str : v)
cout << *str << " ";
cout << endl << "----" << endl;
}
typedef string * string_ptr;
int main()
{
vector<string_ptr> v;
v.push_back(new string("aba"));
v.push_back(new string("baba"));
v.push_back(new string("saba"));
v.push_back(new string("aba"));
v.push_back(new string("naba"));
v.push_back(new string("aba"));
v.push_back(new string("saba"));
v.push_back(new string("laba"));
print_v(v);
sort(v.begin(), v.end(), [](const string_ptr &a, const string_ptr &b){
return a->compare(*b) < 0;
});
auto last = unique(v.begin(), v.end(), [](const string_ptr &a, const string_ptr &b) {
return a->compare(*b) == 0;
});
print_v(v);
for_each(last, v.end(), [](string_ptr &a){
delete a; //if I comment this line everything works "fine"
a = nullptr;
});
v.erase( find(v.begin(), v.end(), nullptr) , v.end() );
print_v(v);
}
Why this kind of stuff didn't work? If I comment the line with delete everything works fine but I have of course memory leaks. Another question: if in the signature of the lambda functions I use string* (instead of the typedef string_ptr) I get nasty compilation errors, why?
Sorry for my bad english, I hope the questions are clear enough.
As stated, the std::unique function basically makes those items that are placed on the right-side of the returned iterator zombie elements. They can be accessed, but they're useless. That's why your delete does not work correctly when you applied it to these items.
If your goal is to partition off the unique items, but at the same time keep their validity, the algorithm function you may want to use is std::stable_partition, with a usage of std::set. So in place of std::unique, you can do the following:
#include <algorithm>
#include <set>
//...
std::set<std::string> stringset;
auto last = std::stable_partition(v.begin(), v.end(), [&stringset](const string_ptr& a)
{
if ( stringset.count(*a) ) return false;
stringset.insert(*a); return true;
});
Basically, we use the std::set to store values we initially find. On subsequent calls to the lambda function, we check for duplicates by querying the set::count() function. If it returns 1, then the item already exists in the set, 0 otherwise. So to place the duplicate items to the right of the partition, we need to return false, and brand new items, we return true (and also we add the item to the set if it's a new item). So basically, we've written a non-destructive version of std::unique by using std::stable_partition.
Thus this results in the unique items not only being partitioned off to the right of the returned iterator of std::stable_partition, those items are perfectly valid and can be used for whatever purpose you see fit (in your case, you wanted to delete them).
Note that this works, as shown by this Live Example
Also, you could use std::partition, but this function does not preserve the relative order of the items. You may want to use std::partition instead, but I am assuming you want to keep the order of the elements.
The problem is that you're deleting elements which are still pointing to valid string (in your case, one of the unique strings). unique function gives the iterator to the element that is just after last element which is not removed. After calling unique, you are deleting everything from last -> v.end(). This is deleting some string which is in the unique part of the vector. To make things clear here is the output after sorting:
aba 0xca9c20 aba 0xca9d20 aba 0xca9cf0 baba 0xca9c70 laba 0xca9e00 naba 0xca9d50 saba 0xca9cc0 saba 0xca9dd0
And after calling unique:
aba 0xca9c20 baba 0xca9c70 laba 0xca9e00 naba 0xca9d50 saba 0xca9cc0 naba 0xca9d50 saba 0xca9cc0 saba 0xca9dd0
Note that I've modified the print_v function to also print the addresses of the strings. As you can see, the string naba is at a memory location 0xca9d50 and after the last unique element i.e. saba, the duplicate string naba is exactly the same as the one earlier, i.e. is stored at the same address. So when you're calling delete, you're invalidating the first string's address as well. So when you call print_v next it sees that the address is invalid and gives you a segfault.

Why adding to vector does not work while using iterator?

I have two code sample, which do exactly same thing. One is in C++03 and C++11.
C++ 11
int main()
{
vector<int> v = {1,2,3};
int count = 0;
for each (auto it in v)
{
cout << it<<endl;
if (count == 0)
{
count++;
v.push_back(4);//adding value to vector
}
}
return 0;
}
C++ 03
int main()
{
vector<int> v = {1,2,3};
int count = 0;
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it<<endl;
if (count == 0)
{
count++;
v.push_back(4);//adding value to vector
}
}
return 0;
}
Both the codes are giving following exception.
Now when I see vector::end() implementation,
iterator end() _NOEXCEPT
{
// return iterator for end of mutable sequence
return (iterator(this->_Mylast, this));
}
Here, inline function clearly takes _Mylast to calculate end. So, when I add, it pointer will be incremented to next location, like _Mylast++. Why I am getting this exception?
Thanks.
A vector stores its elements in contiguous memory. If that memory block needs to be reallocated, iterators become invalid.
If you need to modify the vector's size while iterating, iterate by index instead of iterator.
Another option is to use a different container with a different iterator behavior, for example a list will allow you to continue iterating as you insert items.
And finally, (dare I suggest this?) if you know the maximum size your vector will grow to, .reserve() it before iterating over it. This will ensure it doesn't get reallocated during your loop. I am not sure if this behavior is guaranteed by the standard though (maybe someone can chime in); I would definitely not do it, considering iterating by index is perfectly safe.
Your push_back is invalidating the iterator you're using in the for loop, because the vector is reallocating its memory, which invalidates all iterators to elements of the vector.
The idiomatic solution for this is to use an insert_iterator, like the one you get from calling std::back_insterter on the vector. Then you can do:
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> v;
auto inserter = std::back_inserter(v);
for(int i=0; i<100; ++i)
inserter = i;
for(const auto item : v)
std::cout << item << '\n';
}
And it will ensure its own validity even through reallocation calls of the underlying container.
Live demo here.

Iterate through a C++ Vector using a 'for' loop

I am new to the C++ language. I have been starting to use vectors, and have noticed that in all of the code I see to iterate though a vector via indices, the first parameter of the for loop is always something based on the vector. In Java I might do something like this with an ArrayList:
for(int i=0; i < vector.size(); i++){
vector[i].doSomething();
}
Is there a reason I don't see this in C++? Is it bad practice?
The reason why you don't see such practice is quite subjective and cannot have a definite answer, because I have seen many of the code which uses your mentioned way rather than iterator style code.
Following can be reasons of people not considering vector.size() way of looping:
Being paranoid about calling size() every time in the loop
condition. However either it's a non-issue or it can be trivially
fixed
Preferring std::for_each() over the for loop itself
Later changing the container from std::vector to other one (e.g.
map, list) will also demand the change of the looping mechanism,
because not every container support size() style of looping
C++11 provides a good facility to move through the containers. That is called "range based for loop" (or "enhanced for loop" in Java).
With little code you can traverse through the full (mandatory!) std::vector:
vector<int> vi;
...
for(int i : vi)
cout << "i = " << i << endl;
The cleanest way of iterating through a vector is via iterators:
for (auto it = begin (vector); it != end (vector); ++it) {
it->doSomething ();
}
or (equivalent to the above)
for (auto & element : vector) {
element.doSomething ();
}
Prior to C++0x, you have to replace auto by the iterator type and use member functions instead of global functions begin and end.
This probably is what you have seen. Compared to the approach you mention, the advantage is that you do not heavily depend on the type of vector. If you change vector to a different "collection-type" class, your code will probably still work. You can, however, do something similar in Java as well. There is not much difference conceptually; C++, however, uses templates to implement this (as compared to generics in Java); hence the approach will work for all types for which begin and end functions are defined, even for non-class types such as static arrays. See here: How does the range-based for work for plain arrays?
Is there any reason I don't see this in C++? Is it bad practice?
No. It is not a bad practice, but the following approach renders your code certain flexibility.
Usually, pre-C++11 the code for iterating over container elements uses iterators, something like:
std::vector<int>::iterator it = vector.begin();
This is because it makes the code more flexible.
All standard library containers support and provide iterators. If at a later point of development you need to switch to another container, then this code does not need to be changed.
Note: Writing code which works with every possible standard library container is not as easy as it might seem to be.
The right way to do that is:
for(std::vector<T>::iterator it = v.begin(); it != v.end(); ++it) {
it->doSomething();
}
Where T is the type of the class inside the vector. For example if the class was CActivity, just write CActivity instead of T.
This type of method will work on every STL (Not only vectors, which is a bit better).
If you still want to use indexes, the way is:
for(std::vector<T>::size_type i = 0; i != v.size(); i++) {
v[i].doSomething();
}
Using the auto operator really makes it easy to use as one does not have to worry about the data type and the size of the vector or any other data structure
Iterating vector using auto and for loop
vector<int> vec = {1,2,3,4,5}
for(auto itr : vec)
cout << itr << " ";
Output:
1 2 3 4 5
You can also use this method to iterate sets and list. Using auto automatically detects the data type used in the template and lets you use it.
So, even if we had a vector of string or char the same syntax will work just fine
A correct way of iterating over the vector and printing its values is as follows:
#include<vector>
// declare the vector of type int
vector<int> v;
// insert elements in the vector
for (unsigned int i = 0; i < 5; ++i){
v.push_back(i);
}
// print those elements
for (auto it = v.begin(); it != v.end(); ++it){
std::cout << *it << std::endl;
}
But at least in the present case it is nicer to use a range-based for loop:
for (auto x: v) std::cout << x << "\n";
(You may also add & after auto to make x a reference to the elements rather than a copy of them. It is then very similar to the above iterator-based approach, but easier to read and write.)
There's a couple of strong reasons to use iterators, some of which are mentioned here:
Switching containers later doesn't invalidate your code.
i.e., if you go from a std::vector to a std::list, or std::set, you can't use numerical indices to get at your contained value. Using an iterator is still valid.
Runtime catching of invalid iteration
If you modify your container in the middle of your loop, the next time you use your iterator it will throw an invalid iterator exception.
Here is a simpler way to iterate and print values in vector.
for(int x: A) // for integer x in vector A
cout<< x <<" ";
With STL, programmers use iterators for traversing through containers, since iterator is an abstract concept, implemented in all standard containers. For example, std::list has no operator [] at all.
I was surprised nobody mentioned that iterating through an array with an integer index makes it easy for you to write faulty code by subscripting an array with the wrong index. For example, if you have nested loops using i and j as indices, you might incorrectly subscript an array with j rather than i and thus introduce a fault into the program.
In contrast, the other forms listed here, namely the range based for loop, and iterators, are a lot less error prone. The language's semantics and the compiler's type checking mechanism will prevent you from accidentally accessing an array using the wrong index.
don't forget examples with const correctness - can the loop modify the elements. Many examples here do not, and should use cont iterators. Here we assume
class T {
public:
T (double d) : _d { d } {}
void doSomething () const { cout << _d << endl; return; }
void changeSomething () { ++_d; return; }
private:
double _d;
};
vector<T> v;
// ...
for (const auto iter = v.cbegin(); iter != v.cend(); ++iter) {
iter->doSomething();
}
Note also, that with the C++11 notation, the default is to copy the element. Use a reference to avoid this, and/or to allow for original elements to be modified:
vector<T> v;
// ...
for (auto t : v) {
t.changeSomething(); // changes local t, but not element of v
t.doSomething();
}
for (auto& t : v) { // reference avoids copying element
t.changeSomething(); // changes element of v
t.doSomething();
}
for (const auto& t : v) { // reference avoids copying element
t.doSomething(); // element can not be changed
}
//different declaration type
vector<int>v;
vector<int>v2(5,30); //size is 5 and fill up with 30
vector<int>v3={10,20,30};
//From C++11 and onwards
for(auto itr:v2)
cout<<"\n"<<itr;
//(pre c++11)
for(auto itr=v3.begin(); itr !=v3.end(); itr++)
cout<<"\n"<<*itr;
int main()
{
int n;
int input;
vector<int> p1;
vector<int> ::iterator it;
cout << "Enter the number of elements you want to insert" << endl;
cin >> n;
for (int i = 0;i < n;i++)
{
cin >> input;
p1.push_back(input);
}
for(it=p1.begin();it!=p1.end();it++)
{
cout << *it << endl;
}
//Iterating in vector through iterator it
return 0;
}
conventional form of iterator
If you use
std::vector<std::reference_wrapper<std::string>> names{ };
Do not forget, when you use auto in the for loop, to use also get, like this:
for (auto element in : names)
{
element.get()//do something
}

How to have valid .begin() and .end() without .resize() for std::vector?

I want to use a factory function for my vector and also use the iterators without calling resize which blows my previous values ?
Is it possible or am I missing a point in STL design ?
#include <vector>
#include <algorithm>
#include <iostream>
struct A
{
A():_x(42){}
A(double x):_x(x){}
double _x;
};
struct factory
{
A operator()()
{
return A(3.14);
}
};
int main()
{
std::vector<A> v;
int nbr = 3;
v.reserve(nbr);
std::generate_n(v.begin(), nbr, factory());
std::cout << "Good values" << std::endl;
for(int i = 0 ; i < nbr ; ++i)
std::cout << v[i]._x << std::endl;
v.resize(nbr); //How I can have the syntax below without the resize which blows my previous values ?
std::cout << "resize has been called so values are bad (i.e default ctor)" << std::endl;
for(std::vector<A>::iterator it = v.begin() ; it != v.end() ; ++it)
std::cout << (*it)._x << std::endl;
}
Thanks :)
Either I did not quite understand your concern, or else you have been mislead. resize() does not modify any of the existing elements in the container (other than those removed if you resize to a smaller size).
Now, your actual problem is that you have undefined behavior in your program. The vector has capacity() == nbr but size() == 0 when you call generate_n, and that is writting beyond the end of the container. There are two solutions for this, first you can resize before calling generate_n:
std::vector<A> v;
int nbr = 3;
v.resize(nbr);
std::generate_n(v.begin(), nbr, factory());
Or else you can change the type of the iterator:
std::vector<A> v;
int nbr = 3;
v.reserve(nbr);
std::generate_n(std::back_inserter(v), nbr, factory());
v.reserve(nbr);
std::generate_n(v.begin(), nbr, factory());
It`s error. Reserve != resize, reserve only allocate memory if we need it.
Why you use resize for print vector? Resize is function that resize vector, begin/end are not dependent on resize...
Your generate_n is not generating values into a vector properly. The size of the vector is 0 so while it may appear to work correctly, you're just getting luck when writing beyond the end of the vector. You really do need to use resize or similar. Alternately (and possibly more performant) you can use a back_inserter: std::generate_n(std::back_inserter(v), nbr, factory());
The first part of your code is already broken. In order to create vector elements you have to call resize, not reserve. reserve can only reserve future vector capacity by allocating raw memory, but it does not create (construct) real vector elements. You are generally not allowed to access vector elements that reside between vector's size and vector's capacity.
You called reserve and then you are tried to use your vector as if the elements have already been constructed: you assign values to them and you attempt to read and print these values. In general case this is illegal, it generally leads to undefined behavior. Meanwhile, the size of your vector remained 0, which is what you tried to compensate for by that strange call to resize later.
You need to call resize at the very beginning. Create a vector with the proper number of elements right from the start. (This can also be done by passing the initial size to vector's constructor).
For example, just do
int nbr = 3;
std::vector<A> v(nbr);
std::generate_n(v.begin(), nbr, factory());
or
std::vector<A> v;
int nbr = 3;
v.resize(nbr);
std::generate_n(v.begin(), nbr, factory());
and you are done. Forget about reserve - you don't need it in this case.