title: Using std:vector as low level buffer
body: <p>The usage here is the same as <a href="https://stackoverflow.com/questions/2780365/using-read-directly-into-a-c-stdvector">Using read() directly into a C++ std:vector</a>, but with an acount of reallocation.</p>
  <p>The size of input file is unknown, thus the buffer is reallocated by doubling size when file size exceeds buffer size. Here's my code:</p>
  <pre><code>#include &lt;vector&gt;
  #include &lt;fstream&gt;
  #include &lt;iostream&gt;
  
  int main()
  {
      const size_t initSize = 1;
      std::vector&lt;char&gt; buf(initSize); // sizes buf to initSize, so &amp;buf[0] below is valid
      std::ifstream ifile(&quot;D:\\Pictures\\input.jpg&quot;, std::ios_base::in|std::ios_base::binary);
      if (ifile)
      {
          size_t bufLen = 0;
          for (buf.reserve(1024); !ifile.eof(); buf.reserve(buf.capacity() &lt;&lt; 1))
          {
              std::cout &lt;&lt; buf.capacity() &lt;&lt; std::endl;
              ifile.read(&amp;buf[0] + bufLen, buf.capacity() - bufLen);
              bufLen += ifile.gcount();
          }
          std::ofstream ofile(&quot;rebuild.jpg&quot;, std::ios_base::out|std::ios_base::binary);
          if (ofile)
          {
              ofile.write(&amp;buf[0], bufLen);
          }
      }
  }
  </code></pre>
  <p>The program prints the vector capacity just as expected, and writes the output file just the same size as input, BUT, with only the same bytes as input before offset <code>initSize</code>, and all zeros afterward...</p>
  <p>Using <code>&amp;buf[bufLen]</code> in <code>read()</code> is definitly an undefined behavior, but <code>&amp;buf[0] + bufLen</code> gets the right postition to write because continuous allocation is guaranteed, isn't it? (provided <code>initSize != 0</code>. Note that <code>std::vector&lt;char&gt; buf(initSize);</code> sizes <code>buf</code> to <code>initSize</code>. And yes, if <code>initSize == 0</code>, a rumtime fatal error ocurrs in my environment.) Do I miss something? <strong>Is this also an UB? Does the standard say anything about this usage of std::vector?</strong></p>
  <p>Yes, I know we can calculate the file size first and allocate exactly the same buffer size, but in my project, it can be expected that the input files nearly ALWAYS be smaller than a certain <code>SIZE</code>, so I can set <code>initSize</code> to <code>SIZE</code> and expect no overhead (like file size calculation), and use reallocation just for &quot;exception handling&quot;. And yes, I know I can replace <code>reserve()</code> with <code>resize()</code> and <code>capacity()</code> with <code>size()</code>, then get things work with little overhead (zero the buffer in every resizing), but I still want to get rid of any redundent operation, just a kind of paranoid...</p>
  <p><strong>updated 1:</strong></p>
  <p>In fact, we can <em>logically deduce</em> from the standard that <code>&amp;buf[0] + bufLen</code> gets the right postition, consider:</p>
  <pre><code>std::vector&lt;char&gt; buf(128);
  buf.reserve(512);
  char* bufPtr0 = &amp;buf[0], *bufPtrOutofRange = &amp;buf[0] + 200;
  buf.resize(256); std::cout &lt;&lt; &quot;standard guarantees no reallocation&quot; &lt;&lt; std::endl;
  char* bufPtr1 = &amp;buf[0], *bufInRange = &amp;buf[200]; 
  if (bufPtr0 == bufPtr1)
      std::cout &lt;&lt; &quot;so bufPtr0 == bufPtr1&quot; &lt;&lt; std::endl;
  std::cout &lt;&lt; &quot;and 200 &lt; buf.size(), standard guarantees bufInRange == bufPtr1 + 200&quot; &lt;&lt; std::endl;
  if (bufInRange == bufPtrOutofRange)
      std::cout &lt;&lt; &quot;finally we have: bufInRange == bufPtrOutofRange&quot; &lt;&lt; std::endl;
  </code></pre>
  <p>output:</p>
  <pre><code>standard guarantees no reallocation
  so bufPtr0 == bufPtr1
  and 200 &lt; buf.size(), standard guarantees bufInRange == bufPtr1 + 200
  finally we have: bufInRange == bufPtrOutofRange
  </code></pre>
  <p>And here 200 can be replaced with every <code>buf.size() &lt;= i &lt; buf.capacity()</code> and the similar deduction holds.</p>
  <p><strong>updated 2:</strong></p>
  <p>Yes, I did miss something... But the problem is not continuity (see update 1), and even not failure to write memory (see my answer). Today I got some time to look into the problem, the program got the right address, wrote the right data into <em>reserved memory</em>, but in the next <code>reserve()</code>, <code>buf</code> is reallocated and with ONLY the elements in range <code>[0, buf.size())</code> copied to the new memory. So this's the answer to the whole riddle...</p>
  <p>Final note: <em>If you needn't reallocation after your buffer is filled with some data, you can definitely use <code>reserve()/capatity()</code> instead of <code>resize()/size()</code>, but if you need, use the latter.</em> Also, under all implementations available here (VC++, g++, ICC), the example works as expected:</p>
  <pre><code>const size_t initSize = 1;
  std::vector&lt;char&gt; buf(initSize);
  buf.reserve(1024*100); // assume the reserved space is enough for file reading
  std::ifstream ifile(&quot;D:\\Pictures\\input.jpg&quot;, std::ios_base::in|std::ios_base::binary);
  if (ifile)
  {
      ifile.read(&amp;buf[0], buf.capacity());  // ok. the whole file is read into buf
      std::ofstream ofile(&quot;rebuld.jpg&quot;, std::ios_base::out|std::ios_base::binary);
      if (ofile)
      {
          ofile.write(&amp;buf[0], ifile.gcount()); // rebuld.jpg just identical to input.jpg
      }
  }
  buf.reserve(1024*200); // horror! probably always lose all data in buf after offset initSize
  </code></pre>
  <p>And here's another example, quoted from 'TC++PL, 4e' pp 1041, note that the first line in the function uses <code>reserve()</code> rather than <code>resize()</code>:</p>
  <pre><code>void fill(istream&amp; in, string&amp; s, int max)
  // use s as target for low-level input (simplified)
  {
      s.reserve(max); // make sure there is enough allocated space
      in.read(&amp;s[0],max);
      const int n = in.gcount(); // number of characters read
      s.resize(n);
      s.shrink_to_fit();  // discard excess capacity
  }
  </code></pre>
  <p><strong>Update 3</strong> (after 8 years): Many things happened during these years, I did not use C++ as my working language for nearly 6 years, and now I am a PhD student! Also, though many think there are UBs, the reasons they gave are quite different (and some were already shown to be not UBs), indicating this is a complex case. So, <em>before casting votes and write answers, it is highly recommended to read and be involved in comments</em>.</p>
  <p>Another thing is that, with the PhD training, I can now dive into the C++ standard with relative ease, which I dared not years ago. <strong>I believe I showed in my own answer that, based on the standard, the above two code blocks <em>should</em> work.</strong> (The <code>string</code> example requires C++11.) Since my answer is still contentious (but not falsified, I believe), I do not accept it, but rather am open to critical reviews and other answers.</p>