1

I am new so I more than likely missing something key.

I am using std::vector to store data from a ReadFile operation.

Currently I have a structure called READBUFF that contains a vector of byte. READBUFF is then instantiated via a private type in a class called Reader.

class Reader{
public:
void Read();
typedef struct {
std::vector<byte> buffer;
} READBUFF;

private:
READBUFF readBuffer;
}

Within Read() I currently resize the array to my desired size as the default allocator creates a really large vector [4292060576]

void Reader::Read()
{
readBuffer.buffer.resize(8192);
}

This all works fine, but then I got to thinking I'd rather dynamically NEW the vector inline so I control the allocation management of the pointer. I changed buffer to be: std::vector* buffer. When I try to do the following buffer is not set to a new buffer. It's clear from the debugger that it is not initialized.

void Reader::Read()
{
 key.buffer =  new std::vector<byte>(bufferSize);
}

So then I tried, but this behaves the same as above.

void Reader::Read()
{
std::vector<byte> *pvector = new std::vector<byte>(8192);
key.buffer = pvector;
}

Main first question is why doesn't this work? Why can't I assign the buffer pointer to valid pointer? Also how do I define the size of the inline allocation vs. having to resize?

My ultimate goal is to "new up" buffers and then store them in a deque. Right now I am doing this to reuse the above buffer, but I am in essence copying the buffer into another new buffer when all I want is to store a pointer to the original buffer that was created.

 std::vector<byte> newBuffer(pKey->buffer);
 pKey->ptrFileReader->getBuffer()->Enqueue(newBuffer);

Thanks in advance. I realize as I post this that I missing something fundamental but I am at a loss.

Eric Schmidt
  • 1,257
  • 12
  • 12
  • 3
    What? The default allocator creates a vector of 4 giga elements? Please tell me what compiler you are using, so I can stay away from it. – R. Martinho Fernandes Aug 27 '11 at 18:27
  • 2
    Allocating vectors dynamically is a really bad idea. Just don't do it. – fredoverflow Aug 27 '11 at 18:28
  • 1
    'default allocator creates a really large vector'. Default allocator does no such thing, perhaps you mean the default constructor, but that creates a zero size vector. `key.buffer = new std::vector(bufferSize);` will create a vector of size `bufferSize` and assign pointer to it to `key.buffer`. You say it doesn't but it does. 'Main first question', you do it exactly as you are trying to do it, any of the methods you've posted will work. There's clearly something wrong with the way you are interpreting what you are seeing, but I have no idea what it is. Your code is fine, honestly. – john Aug 27 '11 at 18:32
  • 2
    [Closed as 'go away and read a book'.](http://chat.stackoverflow.com/transcript/message/1335956#1335956) – sbi Aug 27 '11 at 19:41
  • @R. Martinho Fernandes. I am using MSVC2010. I misread the watch window as "allocated size" ? key.buffer.size() 4288718240, prior to doing any allocation. I was looking at process viewer and didn't see my wokring set change, hence the confusion. – Eric Schmidt Aug 28 '11 at 02:07
  • @John. Thanks I'll continue to do use the inline allocation for "newing" per your and Seth's notes below. This was helpful. – Eric Schmidt Aug 28 '11 at 02:09
  • @SBI.I have read several books including the C++ Standard Template Library by Josuttis. I wouldn't post unless I felt stuck. If you have any meaningful advice it would be welcome. – Eric Schmidt Aug 28 '11 at 02:11
  • @Eric: Josuttis' book is called "The C+ Standard Library". It is a great book to learn how to use the C++ standard library, but i's not a book that teaches you the language. See [The Definitive C++ Book Guide and List](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) for good books for learning C++. – sbi Sep 04 '11 at 21:30

2 Answers2

6

You shouldn't be using new in this case. It causes you to have to manage the memory manually, which is never something you should want to do for many reasons1. You said you want to manage the lifetime of the vector by using new; in reality, the lifetime of the vector is already managed because it's the same as the object that holds it. So the lifetime of that vector is the lifetime of the instance of your Reader class.

To set the size of the vector before it gets constructed, you'll have to make a constructor for READBUFF:

// inside the READBUFF struct (assuming you're using a normal variable, not a pointer)
READBUFF() { } // default constructor
READBUFF(int size) : buffer(size) { } // immediately sets buffer's size to the argument 

and use an initialization list in Reader's constructor:

// inside the Reader class
Reader() : readBuffer(8092) { }

Which will set the readBuffer.buffer's size to 8092.


If you really want to use new just for learning:

key.buffer =  new std::vector<byte>(bufferSize);

This will work fine, but you shouldn't be doing it in the Read function, you should be doing it in the object's constructor. That way any member function can use it without having to check if it's NULL.

as the default allocator creates a really large vector [4292060576]

No, it doesn't (if it did, you could have one vector on your entire computer and probably your computer would crash). It incrementally resizes the storage up when you add things and exceed the capacity. Using resize like you are doing is still good though, because instead of allocating a small one, filling it, allocating a bigger one and copying everything over, filling it, allocating a bigger one and copying everything over, etc. you are just allocating the size you need once, which is much faster.

1 Some reasons are:

  1. You have to make sure to allocate it before anyone else uses it, where with a normal member variable it's done automatically before your object has a chance to use it.
  2. You have to remember to delete it in the destructor.
  3. If you don't do the above 2 things, you have either a segfault or a memory leak.
Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
  • @celavek whoops thanks, it's amazing what a difference 3 letters can make. – Seth Carnegie Aug 27 '11 at 22:51
  • There is nothing wrong with managing your own memory. As a programmer, you should be aware at every instance of the program what memory you have and what not. Not having already allocated some memory is a very newbie mistake. If you forget to `delete` that means you have lost track of your own program. Bad sign. (If you are afraid of memory, you can always switch to java) – Shahbaz Aug 27 '11 at 23:01
  • @Shahbaz "Not having already allocated some memory is a very newbie mistake" yeah, and the nature of this question prompted me to say it. And no, there is nothing wrong with managing your own memory, but why complicate things with manual memory management when you could have it automatically managed for you? You don't gain anything from dynamic memory in this case. – Seth Carnegie Aug 27 '11 at 23:21
  • @seth carnegie. In the case of this question, of course. I mean, you are using vectors, you might as well use vectors of vectors, right? ;) – Shahbaz Aug 27 '11 at 23:52
  • @Seth Carnegie. Thanks man. You hit on the core of my question, which was really about memory management. I got rat holed by misunderstanding what the immediate window was telling me in VS. I am all for the non "newing" route for vectors. I am coming from the .NET world as well as old C (10 years) ago and as Shahbaz has a point about "being afraid of memory" - my goal was to better understand the pros and cons here. I get it now. – Eric Schmidt Aug 28 '11 at 02:19
  • @Eric glad to help, good luck with your project and on your journey to C++ nirvana. – Seth Carnegie Aug 28 '11 at 02:22
2

I think you may be misinterpreting the result of calling max_size() on a vector:

#include <vector>
#include <iostream>

int main() {
  std::cout << std::vector<char>().max_size() << std::endl;
  std::cout << std::vector<char>::size_type(~0) << std::endl;
}

This program prints the maximum possible size of the vector, not the current size. size() on the other hand does print the current size (ignoring anything that's been reserved).

Flexo
  • 87,323
  • 22
  • 191
  • 272