Vector of Vectors - a silly goose is me

Consider the following programme:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <windows.h>
#include <vector>

int main() {
	typedef unsigned short		BitDepth;
	typedef std::vector<BitDepth>	AudioBuffer;
	std::vector<AudioBuffer> buffers;

	const unsigned short bufferSize = 16;

	const unsigned short numBuffers = 2;
	for(unsigned i=0; i<numBuffers; ++i) {
		buffers.push_back(AudioBuffer());
		buffers[i].reserve(bufferSize);
		memset(&buffers[i], 0, bufferSize*sizeof(BitDepth));//runtime error!
	}
	return 0;
}


I'm receiving a run-time error when I try to memset my AudioBuffers on line 16. I know it's something small, and I know it's because I can't think straight. I'm also aware that there are other ways of accomplishing the same thing (using classes for AudioBuffers or using std::fill() instead of memset()), I guess that makes this a purely theoretical question.
Last edited on
you want resize(), not reserve()

resize will actually change the size of the vector.


You also are memsetting the vector and not the elements of the vector. You probably meant to do this:

 
memset(&buffers[i][0], ...  // <-note the [0] 


But you shouldn't use memset anyway because it's not typesafe (case in point: this problem you're having). std::fill is a better alternative. (as you already mentioned)

But even that is unnecessary because vector will 0 newly added elements.

This can be greatly simplified:

1
2
3
4
for(unsigned i=0; i<numBuffers; ++i)
    buffers.push_back( AudioBuffer( bufferSize ) );

// that's it 
Last edited on
Why memset? That is a C function.

What is wrong with one of the constructors that sets multiple values in the vector? Seen as this code seems to be for initialisation 8+).

Have a look at version 2 of the constructor here :

http://www.cplusplus.com/reference/vector/vector/vector/


I am a bit wary of nested vectors, they are horribly inefficient when they need to be resized, consider some of the other containers, like a std::list of std::array say - given the size of the buffer is constant.

It's a design decision that depends on whether you need to sort or use find or insert for example. If things need to be sorted, std::set might be better, as it stores items sorted by default. std::map is also good like std::set when there are lots of items, because they use AVL trees internally.

HTH
*EDIT* just read the post below.

Hey Disch,

Thanks for the quick response. I didn't know that a vector will initialize its elements to zero upon resizing. However, let's pretend I'm a curmudgeonly old man and I insist on using memset().

I did what you suggested and added the [0].
memset(&buffers[i][0], ...

Now, I'm getting a vector subscript out of range run-time error.
Any ideas?

*EDIT* after reading my own posts it does sound a lot like I'm asking questions and then not regarding the advice I receive, which I assure you is not the impression I want to give off. I'm very thankful to anyone who responds.
Last edited on
Actually, since initializing the buffers really isn't an issue, perhaps this is a better example of the problem using the same typedefs as before:

1
2
3
4
5
6
7
8
9
10

void WaveFile::write(const char* filename) {
	std::ofstream stream(filename, std::ios::binary);

	//assuming that a wave file has two buffers (weird, I know), and my buffers have data in them, but I only want to write the first buffer
	//write .wav RIFF header

	stream.write((const char*)(&buffers[0]/* [0] */), bufferSize);//run-time error!
	stream.close();
}


How might I go about solving this?
Last edited on
¿have you changed the `reserve()' to `resize()'?
`buffers[i][0]' is out of bounds because `buffers[i]' is empty.

Edit:
The vector, and the data stored by the vector are not contiguous in memory.
You've got a pointer to where the elements are allocated (in the heap)

So stream.write((const char*)(&buffers[0]), bufferSize); is trying to write a vector (say 3 pointers), not its elements.
Last edited on
Ah, I see.
The following seems to have solved the aforementioned problem:

1
2
3
4
5
6
7
8
9
void WaveFile::write(const char* filename) {
	std::ofstream stream(filename, std::ios::binary);

	//write .wav RIFF header

	AudioBuffer buffer=buffers[0];
	stream.write((const char*)&buffer[0], bufferSize);
	stream.close();
}


I admit it's hacky as tabaccy.
Last edited on
Topic archived. No new replies allowed.