2

I need to fill a vector in with particular values. I find that the below code works, except in that a.size() fails to change from 0. Adding a resize call after I put in the elements takes almost twice as long. It seems there should be an O(1) way to update the size, since I don't need to change any elements. Is there? Should I just not bother?

#include <iostream>
#include <vector>
#include <math.h>

using namespace std;

int main()
{
  int n = 1e9;
  vector<float> a;
  a.reserve(n);
  for (int i=0; i<n; i++)
    a[i] = i;

  cout << a[2]; //successfully prints as 1
  cout << a.size(); //confusingly prints as 0
}

Edit: this is not a duplicate, as the linked question does not address benchmarking. It simply asks the difference in reserve and resize, which I am not asking about. This code works, and fast, but has the ugly side effect of leaving size() "incorrect."

David Lerner
  • 344
  • 3
  • 14
  • @Ven No, it is not accessing uninitialized memory. However, the container is not aware about that data has been validated outside. `std::vector`is a good choice, but it is not fully optimized for trivial types. – user877329 Jun 17 '19 at 17:40

1 Answers1

2

std::vector::reserve() is not for creating elements. To create elements, you can use std::vector::resize().

Try this:

#include <iostream>
#include <vector>
#include <math.h>

using namespace std;

int main()
{
  int n = 1e9;
  vector<float> a;
  a.resize(n);
  for (int i=0; i<n; i++)
    a[i] = i;

  cout << a[2];
  cout << a.size();
}
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • I understand that reserve does not create elements. It prevents repeated resizing as when one repeatedly push_backs. Your method has occurred to me, but I benchmark it at 5.45s instead of 3.78 on mine, to accomplish the same thing. A 50% penalty, where it seems this should be O(1)? – David Lerner Jun 09 '16 at 15:40
  • 2
    @DavidLerner 3.78 for *what* though? For broken code with undefined behaviour? – juanchopanza Jun 09 '16 at 15:46
  • @juanchopanza for code that accomplishes the same thing. I even checked the output by printing `a[2]`. – David Lerner Jun 09 '16 at 15:47
  • 1
    @DavidLerner So, broken code with undefined behaviour. Also, make sure you have optimizations switched on. – juanchopanza Jun 09 '16 at 15:48
  • Those benchmarks were without any optimization. With -O3, I get 1.29 for reserve + `a[i]=i`, 1.54 with reserve + push_back, 1.76 for resize + `a[i]=i`. What do you mean about the behavior being undefined? – David Lerner Jun 09 '16 at 15:50
  • 2
    @DavidLerner It means your code is illegal, broken, and all bets are off. You can't rely on it for anything or expect any particular outcome from running it. – juanchopanza Jun 09 '16 at 15:55
  • I'm sure with optimizations, it can even be faster, and the optimizer might remove all of your code. Then it's gonna be soooo damn fast! – Ven Jun 09 '16 at 16:29
  • 1
    Can someone provide a circumstance/compiler/OS in which my code crashes? Is there a set of compilers/OS where it is guaranteed to work? – David Lerner Jun 09 '16 at 16:42
  • You need to look up what Undefined Behaviour really means. Your code could do *anything* it has no meaning, the compiler is free to do whatever it likes. It's meaningless. Read these: http://en.cppreference.com/w/cpp/language/ub , http://blog.regehr.org/archives/213 , http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html , https://blogs.msdn.microsoft.com/oldnewthing/20140627-00/?p=633 – Jesper Juhl Jun 09 '16 at 17:21