Initialization of a vector inside a struct - c++

struct geopoint {
double x;
double y;
const char * description;
};
struct georectangle {
double left_x;
double bottom_y;
double right_x;
double top_y;
const char * description;
};
struct geomap {
vector < geopoint * > geopointList;
vector < georectangle * > georectangleList;
};
struct geomap * geomap_new() {
struct geomap * newGeoMap = (struct geomap * ) malloc(sizeof(struct geomap));
return newGeoMap;
}
void geomap_delete(struct geomap * m) {
printf("%lu\n", m->geopointList.size());
for (int i = 0; i < m->geopointList.size(); i++) {
free(m->geopointList[i]);
}
printf("%lu\n", m->georectangleList.size());
for (int i = 0; i < m->georectangleList.size(); i++) {
free(m->georectangleList[i]);
}
free(m);
}
int main () {
struct geomap * m = geomap_new();
assert(m);
geomap_delete(m);
}
I'm new to C++ and I'm super confused about object initialization in this language... In Java you always use the new keyword when you initialize an object not of a primitive type. In C++, it looks to me that sometimes the default constructor is automatically executed and sometimes it isn't.
In the above snippet of code through the geomap_new() function I create an instance of struct geomap which contains two vectors of pointers.
My questions are the following:
How do I initialize these two vectors to be fresh new empty vectors? In Java I would use the new keyword... Is there such thing also in C++?
I'm asking this question because if I don't initialize them in any way, when I printf the size of these two vectors in the geomap_delete function, the size of the geopointList is 0, as it should be, but the size of the georectangleList is a big random number. It looks like to me that only the first vector is being initialized.
Another question...
If a start adding a lot of stuff in the vectors, these vectors will start growing up. Is it possible that their size will become bigger than the size of the struct itself? Is the struct going to realloc?

You could simplify your code to
#include <iostream>
#include <string>
#include <vector>
struct geopoint {
double x;
double y;
std::string description;
};
struct georectangle {
double left_x;
double bottom_y;
double right_x;
double top_y;
std::string description;
};
struct geomap {
std::vector<geopoint> geopointList;
std::vector<georectangle> georectangleList;
};
int main () {
geomap m;
std::cout << "m.geopointList.size(): " << m.geopointList.size() << '\n';
std::cout << "m.georectangleList.size(): " << m.georectangleList.size() << '\n';
m.geopointList.push_back({1, 2, "Description"});
m.georectangleList.push_back({1, 2, 3, 4, "Description"});
std::cout << "m.geopointList.size(): " << m.geopointList.size() << '\n';
std::cout << "m.georectangleList.size(): " << m.georectangleList.size() << '\n';
}
to avoid such problems. Avoid dynamic memory allocation and deallocation. Don't use malloc, free, new and delete.
"How do I initialize these two vectors to be fresh new empty vectors?" The default constructor does this for you.
"Is it possible that their size will become bigger than the size of the struct itself? Is the struct going to ```realloc``" The struct has a fixed size and contains two vectors. Both vectors contain a reference/pointer to dynamic memory outside of the struct. The struct and both vectors are created on the stack (in my example code) and the dynamic memory of the vectors is on the heap.

Related

Store dynamic amounts of data in a class C++

I have a class that stores data and within the class I have an array called 'position' that stores strings of 2 characters. Unfortunately, the amount of 2 character strings it should hold will vary:
class shipStatus
{
public:
char* name;
int x{};
char position[x][2]; // does not work
void setInfo(char name[], int x);
void displayStatus();
};
The setInfo function assigns a numerical value to x, which varies among objects. I would like the value of x to also dictate the length of the character array 'position'.
For example:
if x = 3 then
char position[3][2]; // the length of the second array is always 2
How can I make my code do this? If I try adding a variable as the parameters my code does not compile.
Here is my setInfo function:
void shipStatus::setInfo(char name[], int x)
{
name = name;
x = x;
}
Since this is C++, you should use the C++ facilities that are available to you. In your case, it would be std::string, std::vector, and std::array.
Below is an example using basically what your original shipStatus structure consisted of, and changing it to using the above mentioned constructs:
#include <string>
#include <array>
#include <vector>
#include <iostream>
class shipStatus
{
std::string name; // <-- Replaced char*
std::vector<std::array<char, 2>> position; // <-- A vector of an array that has a size of 2
public:
void setInfo(std::string n, int x);
void displayStatus();
void setPosition(size_t whichItem, char c1, char c2);
size_t getNumPositions() const;
};
void shipStatus::setInfo(std::string n, int x)
{
name = n;
position.resize(x); // <-- All we need to do is resize() to dynamically resize the vector
}
void shipStatus::displayStatus()
{
for (auto& p : position)
std::cout << p[0] << " " << p[1] << "\n";
}
void shipStatus::setPosition(size_t whichItem, char c1, char c2)
{
position[whichItem] = {c1, c2}; // <-- we set one item in the vector, and in
// that item, we set the [0] and [1] characters
}
size_t shipStatus::getNumPositions() const { return position.size(); }
int main()
{
shipStatus sStatus;
sStatus.setInfo("Ship 1", 3);
sStatus.setPosition(0, '4', '2');
sStatus.setPosition(1, 'a', 'b');
sStatus.setPosition(2, 'y', 'z');
std::cout << "Number of positions: " << sStatus.getNumPositions() << "\n";
sStatus.displayStatus();
}
Output:
Number of positions: 3
4 2
a b
y z
Note that we no longer need x as a member, since a std::vector knows its size already by calling the size() member function.
char **position;
position = (char **)malloc(sizeof(char *)*x);
for (int i=0; i<x; ++i)
{
position[i] = (char *)malloc(sizeof(char)*2);
}
This is a classic "C" way of doing it, will work in C++ too.
For a cleaner approach, we should use vectors/lists for this purpose.

Through what to call the method, if I already created constructor with initialization of array of structures?

I'm trying to call the method displayChoices, member of the class MachineManager through the object of the class. But I already have a constructor with initializing of the array of structures. How I understood when we create an object of the class compiler implicitly create a default constructor of the class.
Question: How to call method displayChoices?
#include "MachineManager.h"
using namespace std;
int main()
{
MachineManager mjp;
mjp.displayChoices();
return 0;
}
struct BrewInfo {
string* DrinkName;
double* Cost;
int* Number;
};
class MachineManager {
static const int Num_Drinks = 3; /// why it works only with static?!!!
BrewInfo* BrewArr[Num_Drinks];
public:
MachineManager()
{
*BrewArr[0]->Cost = 1.25;
*BrewArr[0]->Number = 20;
*BrewArr[1]->DrinkName = "pepsi";
*BrewArr[1]->Cost = 1.15;
*BrewArr[1]->Number = 17;
*BrewArr[2]->DrinkName = "Aloe";
*BrewArr[2]->Cost = 2.00;
*BrewArr[2]->Number = 15;
};
int displayChoices();
}
int MachineManager::displayChoices() // (which displays a menu of drink names and prices)
{
cout << 1;
int choice;
cout << "|1." << *BrewArr[0]->DrinkName << " |2." << *BrewArr[1]->DrinkName << " |3." << *BrewArr[2]->DrinkName << " |" << endl;
cin >> choice;
if (!choice || choice == 0) {
system("slc");
displayChoices();
}
else
return choice;
}
displayChoices has to print a menu in console.
You have a majo bug in your source code. You do not yet understand, how pointer work.
You are defining an array of pointer with BrewInfo* BrewArr[Num_Drinks];.
But these pointers are not initialized. They point to somewhere. Then you are dereferencing those pointers (pointing to somewhere) and assigning a value to somewhere in the memory.
This is a major bug.
The array dimensions for C-Sytle arrays must be a compile time constant.
You cannot write
int x=3;
unt array[x];
This is C99 code (called VLA, Variable length array), but not C++.
Solution for you problem:
Do never use C-Style arrays, like int array[5]. Use STL container like std::vector instead.
Do not use pointers.
This is your major problem. Define your array with BrewInfo BrewArr[Num_Drinks];. Please remove also the pointer from
struct BrewInfo {
string* DrinkName;
double* Cost;
int* Number;
};

Why does 'new' fail in class initialization

win7
gcc 6.4.0
cygwin 2.9.0
the following code fails in function g_block during class initialization but not when used in main. The failure is in the 'for' loop when I attempt to initialize the code (initialization is a side issue here). In both cases allocation seems successful but when used in a class, I can't use the memory allocated.
# include <iostream>
# include <iomanip>
using namespace std;
typedef struct { // gsl allocation 'block' descritpoin
size_t size; // block bytes size
double* data; // pointer to the first byte of the block
} gsl_block;
typedef struct { // matrix definition
size_t size1; // number of rows
size_t size2; // number of columns
size_t tda; // number of elements in row (stride between rows)
double* data; // pointer to matrix[0][0]
gsl_block* block; // pointer to the gsl_matrix block
int owner; // 1: deallocation permitted
} gsl_matrix;
class X {
public:
inline static gsl_matrix& g_matrix(size_t row, size_t col)
{return g_matrix(row, col, g_block(row * col));};
static gsl_block& g_block(size_t size) {
double* ptr = new double(size);
cout << "size " << setw(5)<< size << " addr range "
<< hex << setfill('0') << ptr << " - " << (ptr + size*sizeof(double))
<< dec << setfill(' ') << endl;
for(size_t ndx = 0; ndx < size; ndx++) ptr[ndx] = 0.0;
return * new gsl_block{size, ptr};
};
static gsl_matrix& g_matrix(size_t row, size_t col, gsl_block& block) {
return * new gsl_matrix{row, col, col, block.data, &block, 0}; }
gsl_matrix& g_mat;
X() : g_mat(g_matrix(92, 92)) {}
}; // class X
int main(int argc, char** argv) {
gsl_matrix& mat = X::g_matrix(92, 92);
X* x = new X();
return 0;
}
double* ptr = new double(size);
This line creates a single double with the value size on the free store, and returns a pointer to it.
for(size_t ndx = 0; ndx < size; ndx++) ptr[ndx] = 0.0;
This line then invokes undefined behavior by attempting to write to memory that your program does not own.
You should really use std::vector instead of raw pointers. As your program stands, you have a significant potential to leak memory. If you made gsl_block::data a std::vector<double>, your classes would get proper copy and move semantics for free, and you wouldn't need to directly use new anywhere in your code.
EDIT:
Now that you've mentioned you're using GNU Scientific Library, you should probably just use the functions that library provides for allocating and freeing matricies: gsl_matrix_alloc and gsl_matrix_free. I would re-write your X class to just contain a std::unique_ptr with gsl_matrix_free as its deleter:
struct X
{
struct free_matrix
{
void operator()(gsl_matrix* mat)
{
gsl_matrix_free(mat);
}
};
std::unique_ptr<gsl_matrix, free_matrix> g_mat;
X(std::size_t rows, std::size_t cols)
: g_mat(gsl_matrix_alloc(rows, cols))
{}
};
You could even go further and completely wrap gsl_matrix in a more C++-like interface, with member functions that call gsl_matrix_get/gsl_matrix_set or gsl_matrix_pointer to provide simple access to the matrix elements.

Size of an object without using sizeof in C++

This was an interview question:
Say there is a class having only an int member. You do not know how many bytes the int will occupy. And you cannot view the class implementation (say it's an API). But you can create an object of it. How would you find the size needed for int without using sizeof.
He wouldn't accept using bitset, either.
Can you please suggest the most efficient way to find this out?
The following program demonstrates a valid technique to compute the size of an object.
#include <iostream>
struct Foo
{
int f;
};
int main()
{
// Create an object of the class.
Foo foo;
// Create a pointer to it.
Foo* p1 = &foo;
// Create another pointer, offset by 1 object from p1
// It is legal to compute (p1+1) but it is not legal
// to dereference (p1+1)
Foo* p2 = p1+1;
// Cast both pointers to char*.
char* cp1 = reinterpret_cast<char*>(p1);
char* cp2 = reinterpret_cast<char*>(p2);
// Compute the size of the object.
size_t size = (cp2-cp1);
std::cout << "Size of Foo: " << size << std::endl;
}
Using pointer algebra:
#include <iostream>
class A
{
int a;
};
int main() {
A a1;
A * n1 = &a1;
A * n2 = n1+1;
std::cout << int((char *)n2 - (char *)n1) << std::endl;
return 0;
}
Yet another alternative without using pointers. You can use it if in the next interview they also forbid pointers. Your comment "The interviewer was leading me to think on lines of overflow and underflow" might also be pointing at this method or similar.
#include <iostream>
int main() {
unsigned int x = 0, numOfBits = 0;
for(x--; x; x /= 2) numOfBits++;
std::cout << "number of bits in an int is: " << numOfBits;
return 0;
}
It gets the maximum value of an unsigned int (decrementing zero in unsigned mode) then subsequently divides by 2 until it reaches zero. To get the number of bytes, divide by CHAR_BIT.
Pointer arithmetic can be used without actually creating any objects:
class c {
int member;
};
c *ptr = 0;
++ptr;
int size = reinterpret_cast<int>(ptr);
Alternatively:
int size = reinterpret_cast<int>( static_cast<c*>(0) + 1 );

Dynamically Allocated Array of Struct Pointers in C++

Ok i'm pretty new to c++ (I think what we are learning is somehow an hybrid of c and c++).
I've found alot of anwsers to my question, sadly all of them where in C using malloc.
struct A {
int randomStuff = 0;
};
struct B {
int numOfA= 5; // In reality this number is variable.
A** arrayOfA;
};
The struct are given to us. Now I need to allocate and fill this array with pointers to, I guess, A pointers. <- Correct me here if I'm wrong pointers are still quite complex for me.
A * a1 = new A;
A * a2 = new A;
B * b = new B;
// Allocate space for the array...
b->arrayOfA = new A*[numOfA];
// Next I want to initialize the pointers to NULL
for(int i; i < b->numOfA; i++){
b->arrayOfA[i] = NULL;
}
// In another function I would the assign a value to it
b->arrayOfA[0] = a1;
b->arrayOfA[1] = a2;
The way I see it is that b->arrayOfA needs to point to an array of A struct...somehow like this
b->arrayOfA = new A*;
A * arr[numOfA];
b->arrayOfA = arr;
My brain is bleeding.
How do I correctly allocate it and assign existing values(A structs) to it?
*edit
It would appear that the code was working as intended and that my display was causing me issues. Basically, I needed an array "arrayOfA[]" in which I would put the pointers to an A struct. Effectively making the result of this:
cout << arrayOfA[0]->randomStuff // 0 would be displayed
To be 0.
You could allocate an array of pointers and for each of them allocate an array of your objects
int x = 5, y = 6;
b->arrayOfA = new A*[x]; //array of pointers
for(int i=0;i<x;i++){
b->arrayOfA[i] = new A[y]; //matrix (array of arrays)
}
for(int i=0;i<x;i++){
delete[] b->arrayOfA[i]; //don't forget to free memory
}
delete[] b->arrayOfA;
You should be able to just use a vector:
#include <vector>
int main()
{
vector<A> vector_of_a;
vector_of_a.push_back(a1); //store a1 in the vector
vector_of_a.push_back(a2); //store a2 in the vector
//...
std::cout << "Number of A's: " << vector_of_a.size() << std::endl;
std::cout << vector_of_a[0].randomStuff << std::endl; //prints 0 as specified but with '.' not '->' Objects are still on the heap, and not the stack.
}
The A's in the vector are stored on the heap, but you don't need to manage the memory yourself (no need for malloc/free or new/delete.
The A objects will be disposed of correctly when the vector goes out of scope.
You also get
You can push in pointers to objects too, but this reduces the usefulness of the vector as you then have to do your own memory management for the objects:
#include <vector>
int main()
{
A* a1 = new A();
A* a2 = new A();
vector<A> vector_of_a;
vector_of_a.push_back(a1); //store pointer to a1 in the vector
vector_of_a.push_back(a2); //store pointer to a2 in the vector
//...
std::cout << "Number of A's: " << vector_of_a.size() << std::endl;
std::cout << vector_of_a[0]->randomStuff << std::endl; //prints 0 as specified
//...
for (auto i : vector_of_a)
{
delete (i);
}
vector_of_a.clear();
}
If you really don't want to use a vector, then I reccommend turning your struct B into a fully fledged class.
It gives you the benefit of encapsulation, functions to manage the data are stored within the class, and the class does the memory management and doesn't leave it to the
user's code to manage and clear up behind it:
class B
{
public:
array_of_A(unsigned int size);
~array_of_A();
bool init_array();
unsigned int get_size();
A** get_array();
private:
unsigned int num_of_A;
A** array_of_A;
}
B::array_of_A(unsigned int size)
{
num_of_a = size;
array_of_A = new A*[size]; //create array
memset (array_of_A, nullptr, size); //initialise contents to nullptr
}
B::~B()
{
for(unsigned int i = 0; i < num_of_a; i++)
{
delete array_of_a[i]; //delete each A
}
delete[](array_of_a); //delete the array of pointers.
}
unsigned int B::get_size()
{ return num_of_A; }
A** B::get_array()
{ return array_of_A; }
int main()
{
B b((5)); //most vexing parse...
b.get_array()[0] = new A();
b.get_array()[1] = new A();
b.get_array()[2] = new A();
std::cout << b.get_array()[0]->randomStuff << std::endl //prints 0 as requested
} //b goes out of scope, destructor called, all memory cleaned up
aaaand by internalising the memory management and supporting arbitarilly long arrays, we've just started implementing a (much) simpler version of vector. But good for practice/learning.