C++ vector of custom template class and unclean (?) allocation - c++

I have a quite complex Problem and couldn't find out, where the Problem is. Part of the Problem might be, that i didn't fully understand the data structures. I have the following custom template class, with this member variables:
template <class T>
class Matrix
{
private:
T * *M; /* array of row pointers */
size_t n_rows, /* number of rows */
n_cols; /* number of columns */
size_t row_start, /* first row of submatrix */
col_start, /* first column of submatrix */
origcols; /* refers to original matrix */
bool hasownvalues, /* has matrix own value? */
initialized; /* are matrix values initialed? */
I also made a custom constructor, which makes a 2D array out of a file with tab-separated data:
Matrix(const std::string &filename)
{ do.stuff }
I'm not sure, if it is really important how this exactly works, it quite a bunch of code. if so, i could edit it later, but the constructor works well as long as i declare a single variable for such an object.
My problem occurs when i try to make a bunch of the objects and try to wrap them up in a vector. Lets say i have x different files, each containing data for a matrix. I also have a vector in which the filenames are stored:
std::vector<std::string> filenames{};
for (int idx = 3; idx < argc; idx++)
{
filenames.push_back(argv[idx]);
}
So far this code works and it is mandatory that i keep it unchanged to keep the rest of the program working.
The following is flexible and thats where i have problem:
std::vector<Matrix<T>> coredata; /* initialize the vector for the wrap */
...
for (auto& it : filenames)
{
Matrix<T> M(it); /* call the special constructor*/
coredata.push_back(M); /* add new object to the vector */
}
The first assignment works well, but from the second on it seems that it appends the new Matrix, but also overwrites the old one or at least a part of it. And in the third one i get a segmentation fault when running the program.
Some information of the program around:
the constructor works with space allocated by the "new" command, maybe that could be part of the problem.
the real size of the Matrix object isn't known before run time. (the arrays can be of different size), but i could arrange, that the read data in fact always is of the same size
T is constant within the vector. it can't happen, that M is sometimes Matrix int and sometimes Matrix float
the vector would be embedded in another superclass and the snippet above is part of a constructor of this class, coredata is a member variable.
I'm quite puzzled what the problem exactly is. Maybe some variables don't live long enough. I also thought of assigning just a reference to the address in the vector, but as far as i understand, a vector already stores just a reference, so it seems not that plausible.
I also thought of initializing the vector with a bunch of "0"-matrices and then overwrite them with the constructed objects. But i don't know how to do that and on top of that,
i don't know at compile time how many rows and columns the read Matrices will have.
Maybe a vector isn't a useful solution at all, i also thought of making a plain C-array.
But there i have the problem again, that i have to initialize this array first and can't just append another Matrix-Object to it.

Related

How using size_t as a parameter works

So I am making my first attempt in making a hash table and am completely stumped as to what to do for my constructors?
class HashTable {
typedef vector <list<HashNode> > Table;
Table *table; // size of table is stored in the Table data structure
size_t num; // number of entries in the HashTable;
}
this is the class I'm trying to make constructors for and I have been given.
public:
HashTable(); // constructor, initializes table of size 1;
HashTable(size_t num); // constructor, requires size of table as arg
I don't really understand as to what am supposed to do. So first I'm to initialize the size of the table to 1. Which since I'm using a vector, I'm assuming I'm to use the reserve function? So I went ahead and got this:
this->table->resize(num);
which compiled fine and I had no issue with and I think is correct. The second constructor is where I had an issue understanding, mainly due to the use of size_t. By my understanding here is where I set the size of the table to size_t? But what is size_t supposed to be? I think its a data type but why would I set the Hashtable size to a datatype? Unless I'm missing something obvious here I can't see.

Why is the dynamically allocated array attribute of my class template only able to store one item?

I am trying to expand the functionality of a class template I created. Previously it allowed you to use key-value pairs of any type but only if you knew the size of the arrays at compile time. It looked like this:
template <typename K, typename V, int N>
class KVList {
size_t arraySize;
size_t numberOfElements;
K keys[N];
V values[N];
public:
KVList() : arraySize(N), numberOfElements(0) { }
// More member functions
}
I wanted to be able to use this for a dynamic number of elements decided at run-time, so I changed the code to this:
template <typename K, typename V>
class KVList {
size_t arraySize;
size_t numberOfElements;
K* keys;
V* values;
public:
KVList(size_t size) : numberOfElements(0) {
arraySize = size;
keys = new K[size];
values = new V[size];
}
~KVList() {
delete[] keys;
keys = nullptr;
delete[] values;
values = nullptr;
}
// More member functions
}
The new constructor has one parameter which is the size that will be used for the KVList. It still starts the numberOfElements at 0 because both of these uses would start the KVList empty, but it does set arraySize to the value of the size parameter. Then it dynamically allocated memory for the arrays of keys and values. An added destructor deallocates the memory for these arrays and then sets them to nullptr.
This compiles and runs, but it only stores the first key and first value I try to add to it. There is a member function in both that adds a key-value pair to the arrays. I tested this with the Visual Studio 2015 debugger and noticed it storing the first key-value pair fine, and then it attempts to store the next key-value pair in the next index, but the data goes no where. And the debugger only shows one slot in each array. When I attempt to cout the data I thought I stored at that second index, I get a very small number (float data type was trying to be stored), not the data I was trying to store.
I understand it might be worth using the vectors to accomplish this. However, this is an expansion on an assignment I completed in my C++ class in school and my goal with doing this was to try to get it done, and understand what might cause issues doing it this way, since this is the obvious way to me with the knowledge I have so far.
EDIT: Code used to add a key-value pair:
// Adds a new element to the list if room exists and returns a reference to the current object, does nothing if no room exists
KVList& add(const K& key, const V& value) {
if (numberOfElements < arraySize) {
keys[numberOfElements] = key;
values[numberOfElements] = value;
numberOfElements++;
}
return *this;
}
EDIT: Code that calls add():
// Temp strings for parts of a grade record
string studentNumber, grade;
// Get each part of the grade record
getline(fin, studentNumber, subGradeDelim); // subGradeDelim is a char whose value is ' '
getline(fin, grade, gradeDelim); // gradeDelim is a char whose value is '\n'
// Attempt to parse and store the data from the temp strings
try {
data.add(stoi(studentNumber), stof(grade)); // data is a KVList<size_t, float> attribute
}
catch (...) {
// Temporary safeguard, will implement throwing later
data.add(0u, -1);
}
Code used to test displaying the info:
void Grades::displayGrades(ostream& os) const {
// Just doing first two as test
os << data.value(0) << std::endl;
os << data.value(1);
}
Code in main cpp file used for testing:
Grades grades("w6.dat");
grades.displayGrades(cout);
Contents of w6.dat:
1022342 67.4
1024567 73.5
2031456 79.3
6032144 53.5
1053250 92.1
3026721 86.5
7420134 62.3
9762314 58.7
6521045 34.6
Output:
67.4
-1.9984e+18
The problem (or at least one of them) is with this line from your pastebin:
data = KVList<size_t, float>(records);
This seemingly innocent line is doing a lot. Because data already exists, being default constructed the instance that you entered the body of the Grades constructor, this will do three things:
It will construct a KVList on the right hand side, using its constructor.
It will call the copy assignment operator and assign what we constructed in step 1 to data.
The object on the right hand side gets destructed.
You may be thinking: what copy assignment operator, I never wrote one. Well, the compiler generates it for you automatically. Actually, in C++11, generating a copy assignment operator automatically with an explicit destructor (as you have) is deprecated; but it's still there.
The problem is that the compiler generated copy assignment operator does not work well for you. All your member variables are trivial types: integers and pointers. So they just copied over. This means that after step 2, the class has just been copied over in the most obvious way. That, in turn, means that for a brief instance, there is an object on the left and right, that both have pointers pointing to the same place in memory. When step 3 fires, the right hand object actually goes ahead and deletes the memory. So data is left with pointers pointing to random junk memory. Writing to this random memory is undefined behavior, so your program may do (not necessarily deterministic) strange things.
There are (to be honest) many issues with how your explicit resource managing class is written, too many to be covered here. I think that in Accelerated C+, a really excellent book, it will walk you through these issues, and there is an entire chapter covering every single detail of how to properly write such a class.

How can I allocate memory for a data structure that contains a vector?

If I have a struct instanceData:
struct InstanceData
{
unsigned usedInstances;
unsigned allocatedInstances;
void* buffer;
Entity* entity;
std::vector<float> *vertices;
};
And I allocate enough memory for an Entity and std::vector:
newData.buffer = size * (sizeof(Entity) + sizeof(std::vector<float>)); // Pseudo code
newData.entity = (Entity *)(newData.buffer);
newData.vertices = (std::vector<float> *)(newData.entity + size);
And then attempt to copy a vector of any size to it:
SetVertices(unsigned i, std::vector<float> vertices)
{
instanceData.vertices[i] = vertices;
}
I get an Access Violation Reading location error.
I've chopped up my code to make it concise, but it's based on Bitsquid's ECS. so just assume it works if I'm not dealing with vectors (it does). With this in mind, I'm assuming it's having issues because it doesn't know what size the vector is going to scale to. However, I thought the vectors might increase along another dimension, like this?:
Am I wrong? Either way, how can I allocate memory for a vector in a buffer like this?
And yes, I know vectors manage their own memory. That's besides the point. I'm trying to do something different.
It looks like you want InstanceData.buffer to have the actual memory space which is allocated/deallocated/accessed by other things. The entity and vertices pointers then point into this space. But by trying to use std::vector, you are mixing up two completely incompatible approaches.
1) You can do this with the language and the standard library, which means no raw pointers, no "new", no "sizeof".
struct Point {float x; float y;} // usually this is int, not float
struct InstanceData {
Entity entity;
std::vector<Point> vertices;
}
This is the way I would recommend. If you need to output to a specific binary format for serialization, just handle that in the save method.
2) You can manage the memory internal to the class, using oldschool C, which means using N*sizeof(float) for the vertices. Since this will be extremely error prone for a new programmer (and still rough for vets), you must make all of this private to class InstanceData, and do not allow any code outside InstanceData to manage them. Use unit tests. Provide public getter functions. I've done stuff like this for data structures that go across the network, or when reading/writing files with a specified format (Tiff, pgp, z39.50). But just to store in memory using difficult data structures -- no way.
Some other questions you asked:
How do I allocate memory for std::vector?
You don't. The vector allocates its own memory, and manages it. You can tell it to resize() or reserve() space, or push_back, but it will handle it. Look at http://en.cppreference.com/w/cpp/container/vector
How do I allocate memory for a vector [sic] in a buffer like this?
You seem to be thinking of an array. You're way off with your pseudo code so far, so you really need to work your way up through a tutorial. You have to allocate with "new". I could post some starter code for this, if you really need, which I would edit into the answer here.
Also, you said something about vector increasing along another dimension. Vectors are one dimensional. You can make a vector of vectors, but let's not get into that.
edit addendum:
The basic idea with a megabuffer is that you allocate all the required space in the buffer, then you initialize the values, then you use it through the getters.
The data layout is "Header, Entity1, Entity2, ..., EntityN"
// I did not check this code in a compiler, sorry, need to get to work soon
MegaBuffer::MegaBuffer() {AllocateBuffer(0);}
MegaBuffer::~MegaBuffer() {ReleaseBuffer();}
MegaBuffer::AllocateBuffer(size_t size /*, whatever is needed for the header*/){
if (nullptr!=buffer)
ReleaseBuffer();
size_t total_bytes = sizeof(Header) + count * sizeof(Entity)
buffer = new unsigned char [total_bytes];
header = buffer;
// need to set up the header
header->count = 0;
header->allocated = size;
// set up internal pointer
entity = buffer + sizeof(Header);
}
MegaBuffer::ReleaseBuffer(){
delete [] buffer;
}
Entity* MegaBuffer::operator[](int n) {return entity[n];}
The header is always a fixed size, and appears exactly once, and tells you how many entities you have. In your case there's no header because you are using member variables "usedInstances" and "allocatednstances" instead. So you do sort of have a header but it is not part of the allocated buffer. But you don't want to allocate 0 bytes, so just set usedInstances=0; allocatedInstances=0; buffer=nullptr;
I did not code for changing the size of the buffer, because the bitsquid ECS example covers that, but he doesn't show the first time initialization. Make sure you initialize n and allocated, and assign meaningful values for each entity before you use them.
You are not doing the bitsquid ECS the same as the link you posted. In that, he has several different objects of fixed size in parallel arrays. There is an entity, its mass, its position, etc. So entity[4] is an entity which has mass equal to "mass[4]" and its acceleration is "acceleration[4]". This uses pointer arithmetic to access array elements. (built in array, NOT std::Array, NOT std::vector)
The data layout is "Entity1, Entity2, ..., EntityN, mass1, mass2, ..., massN, position1, position2, ..., positionN, velocity1 ... " you get the idea.
If you read the article, you'll notice he says basically the same thing everyone else said about the standard library. You can use an std container to store each of these arrays, OR you can allocate one megabuffer and use pointers and "built in array" math to get to the exact memory location within that buffer for each item. In the classic faux-pas, he even says "This avoids any hidden overheads that might exist in the Array class and we only have a single allocation to keep track of." But you don't know if this is faster or slower than std::Array, and you're introducing a lot of bugs and extra development time dealing with raw pointers.
I think I see what you are trying to do.
There are numerous issues. First. You are making a buffer of random data, telling C++ that a Vector sized piece of it is a Vector. But, at no time do you actually call the constructor to Vector which will initialize the pointers and constructs inside to viable values.
This has already been answered here: Call a constructor on a already allocated memory
The second issue is the line
instanceData.vertices[i] = vertices;
instanceData.vertices is a pointer to a Vector, so you actually need to write
(*(instanceData.vertices))[i]
The third issue is that the contents of *(instanceData.vertices) are floats, and not Vector, so you should not be able to do the assignment there.

How to convert column vector into MxN matrix?

I am relatively new to C++ and kind of stuck in this problem. I have 999x1 vector of point coordinates and I want to convert it in 333x3 matrix dyanamically. Besides this, I am using different Cpp files for one project so the function which reads the points set is in different file. How to make this matrix and how should I access it in my main code?
I tried using vector<vector<float> > Mymatrix thing but you need to specify the rows and column size in this kind of definition which I cannot get until I read the file. If I try to declare above Mymatrix variable in the function which is reading the pointset file, its scope gets limited and I cannot use that Mymatrix in main.cpp.
Its little bit difficult to write the code here because it has many links with other files. I hope you have got my problem! Please help me in this issue...Thanks in advance!
vector is really just a container for array. So basically what you have is a int A[999] and want to convert this into int M[333][3];
Considering that in memory both a 1D and a 2D array are stored in a contiguous memory region, you can achieve this in several ways:
- use a pointer and two indexes i, j: the first 3 elements are your first row,
the next 3 elements your second row and so on.
int vector<int> v;
int *p, i=0,j=0; // i=[0..332], j=[0..2]
p=&v[0];
*(p+(i*3)+j); //this is the same as p[i][j];
Or declare matrix (either allocate static or dynamic memory for it) and copy all the elements int the matrix:
int M[333][3]; //i'll go with static allocation for this example
for(i=0;i<333;i++)
for(j=0;j<3;j++)
M[i][j] = v[i*3 + j];
choose which ever method you want - the advantage of the first one is that it does not us the extra memory.
You can create your MyMatrix as a pointer and pass to your function as parameter:
vector<vector<float> >* Mymatrix; //Don't forget to initialize the pointer
functionThatReadsFiles(Mymatrix); //That function makes changes to Mymatrix
With this, any changes you make to Mymatrix inside "functionThatReadsFiles" will remain after its call. Anyway, make sure you fully understand how to operate with pointers before trying this.
As #erlc says, you can also declare your function with:
void functionThatReadsFiles(vector<vector<float> >& Mymatrix);
And call just call it normally (without pointers), and again the changes will remain into your Mymatrix.

Copy values to and from a member of a structure in C++

I have a structure as shown below, which I use for the purpose of sorting a vector while keeping track of the indices.
struct val_order{
int order;
double value;
};
(1). Currently what I do is use a loop to copy values as shown below. So my first question is if there is a faster way to copy values to a member of a structure (not copying an entire structure to another structure)
int n=x.size();
std::vector<val_order> index(n);
for(int i=0;i<x.size();i++){ //<------So using a loop to copy values.
index[i].value=x[i];
index[i].order=i;
}
(2). My second question has to do with copying one member of a structure to an array. I found a post here that discusses using memcpy to accomplish that. But I was unable to make it work (code below). The error message I got was class std::vector<val_order, std::allocator<val_order> > has no member named ‘order’. But I was able to access the values in index.order by iterating over it. So I wonder what is wrong with my code.
int *buf=malloc(sizeof(index[0].order)*n);
int *output=buf;
memcpy(output, index.order, sizeof(index.order));
Question 1
Since you are initializing your n vectors from two different sources (array x and variable i), it would be difficult to avoid a loop. (you could initialize the vectors from index.assign if you had an array of val_order already filled with values, see this link)
Question 2
You want to copy all n order values into a int array, and memcpy seems convenient for that. Unfortunately,
each element of a vector is a val_order structure, so even though you could copy via memcpy that would not only copy the int *order* value but also the double *value* value
furthermore, you are dealing with vector, which internal structure is not a simple array (vector allows operations that are not possible with a regular array) and thus you cannot copy a bunch of vector to a int array by simply giving the address of, say, the first vector element to memcpy.
also, memcpy wouldn't work like you want anyway, but it expects an address - thus you would have to give, e.g., &index[0] ... but again, this is not what you want given the points above
So you would have to make another loop instead, like
int *buf = (int *)malloc(sizeof(int)*n);
int *output = buf;
for (int i=0 ; i<n ; i++) {
output[i] = index[i].order;
}