Initialization of vector of objects - c++

Before I put my question let me mention in advance that I am aware that this topic has been discussed a lot, but yet again by looking to most of the answers I failed to figure out the proper way to achieve what I want (most probably because I missed sth from the anwers given).
So, say I want to create 20 times a vector of objects (say of size ten each) that should be of global scope (in the sense that this is done inside a class and i want these vectors of objects to be passed outside the class).
So, I am really not sure if the following is valid:
for ( int i =0; i<20; i++)
vector<A> * vec_of_class = new vector<A>(10);
/*where A is the class and I use new to have them in the heap,
so that they won't be local */
Now, I know that this means that I should be extra carefull with handling them
and make sure that I preper delete them, but I am not sure if the operation I am doing is valid. In general I want to achieve to initialize 20 different vectors of object A that can be used in the global scope (the operation is happening inside a function of an other class), I know that it could be used
a vector of vectors of object A, but I would like to find out how to do correctly this kind of operation (initializing 20 different vectors of object A inside the body function of an other class and use them globally).
I hope ,my question was not to confusing and you could give me some help here.

There should never be a case when you dynamically allocate any standard container, including vector. So std::vector<> = new <> is always wrong.
To initialize your vector, you can use multitude of techniques. I find initializer lists especially handy, like here:
std::vector<int> vec{10, 20, 30, 40, 50};

So, say I want to create 20 times a vector of objects (say of size ten each)
That's easy. Use:
std::vector<std::vector<A>> my_data{20, std::vector<A>{10}};
that should be of global scope (in the sense that this is done inside a class and i want these vectors of objects to be passed outside the class).
I don't have a clear picture of what you want to accomplish here.
When something is done inside a class, it could be done in a static member function or a regular member function. It seems like you should use a static member function but I am not sure.
If you use a static member function, I would suggest:
std::vector<std::vector<A>> const& TheClass::get_my_data()
{
static std::vector<std::vector<A>> my_data{20, std::vector<A>{10}};
static bool inited = false;
if ( !inited )
{
// Set the values of the elements in my_data
// ...
inited = true;
}
return my_data;
}
If you use a regular member function, I suggest populating my_data in the constructor and returning from a function.
// Need to make my_data a member variable
TheClass::TheClass() : my_data{20, std::vector<A>{10}}
{
// Set the values of the elements in my_data
// ...
}
std::vector<std::vector<A>> const& TheClass::get_my_data() const
{
return my_data;
}

If you declare a variable into a function, the scope of that variable will be the function. It won't be accessible from outside.
What you can do is declare the 20 pointers in the global scope, and initialize them wherever you want (inside a function, for instance).

Related

Failing to change members of structs stored in two-dimensional array

I have a global two dimensional array holding a number of structs. From inside a function I try to change it's members like this:
struct ControlPin {
int pin;
int previousValue;
};
ControlPin controls[CHANNELS][MULTIPLEXERS];
void readControlInput(int channel, int multiplexer) {
ControlPin control = controls[channel][multiplexer];
control.previousValue = analogRead(control.pin);
}
If i print out control.previousValue inside readControlInput() I can verify that it has changed, but after getting out of the function scope, the change is gone. How can I get a reference to the struct instead of copying it? I assume that's what happening, but I cant see why. I know that when you pass a value as a parameter to a function it is actually a copy, but here I'm accessing the global array directly?
I'm used to Java so this is a bit confusing to me.
In Java all objects are (IIRC) references. In C++ the default is that objects are values. When you do
ControlPin control = controls[channel][multiplexer];
you copy the "value" in controls[channel][multiplexer], then when you modify control you only modify the local value, and not the value in the array.
The simplest option is to explicitly say that control is a reference, by using the ampersand (&) when declaring the variable:
ControlPin& control = controls[channel][multiplexer];
// ^
// |
// Note ampersand here
That tells the compiler that control is a reference and then initializes it to reference the object (value) at controls[channel][multiplexer].
On an unrelated not, C++ have no bounds-checking. If you access an array out of bounds the compiler will happily allow it, but it will lead to undefined behavior at run-time. You need to do bounds-checking yourself if you want to avoid weird problems. It doesn't have to be in the function, but it needs to be done somewhere.
You're not accessing the array directly, this works exactly like if you had passed the element to a function:
void readInput(ControlPin control)
{
control.previousValue = analogRead(control.pin);
}
void readControlInput(int channel, int multiplexer) {
readInput(controls[channel][multiplexer]);
}
You can tell from the types - ControlPin means the same thing regardless of whether it is a local variable or a parameter.
In C++, variables that contain class instances always contain class instances and not some kind of "reference" to them, so just like when calling a function,
ControlPin control = controls[channel][multiplexer];
creates a copy of the array element, and
control.previousValue = analogRead(control.pin);
modifies that copy.
The simplest fix is to write it in one line:
controls[channel][multiplexer].previousValue = analogRead(control.pin);
You can also use a reference variable (which is different from Java's "references") to refer to the array element itself:
ControlPin& control = controls[channel][multiplexer];
control.previousValue = analogRead(control.pin);
This is most useful if you need to do more than one thing with the same element - it's both more readable and more resilient to errors than duplicating the indexing.

C++ function call with type pointer, parameter confusion: incomplete type is not allowed

I'm trying to wrap my head around C++. I'm going to just give you tiny pieces to help illustrate the idea without making things to convoluted. Btw, im only implementing these methods, i cannot change the setup or parameters.
I have a class for a dynamic array data structure that holds objects called stocks:
typedef class Stock ArrayType;
class DynamicArray {
ArrayType** items;
int numberOfElements;
...
}
Here's its constructor. I'm supposed to allocate the array and add one item, then set the number of elements.
DynamicArray::DynamicArray(ArrayType* const item){
Stock *items = NULL; // ... i guess? pointers to pointers confuse me
// now im guessing i need to create a actual stock array and point the above pointer to it
items = new Stock[1]; // ERROR: incomplete type is not allowed? I've tried several things, and cant get rid of the red squiggles
this->numberOfElements = 1;
}
Okay, there are a few problems. Off the bat, you have to include Stock first. The compiler needs the full definition of Stock before it can compile DynamicArray, because of memory allocation by my guess.
Secondly, you want the items member-value to contain the reference to the array created in the constructor. So instead of defining Stock *items[1] in the constructor, assign the value of the new statement directly to this->items; you can ommit this-> as long as you don't define a variable with the same name in whatever function you're working on.
Finally, you're allocating an array of pointers, so you use this syntax: new ArrayType*[1]
Additionally, just as a coding-practices point, you shouldn't mix the use of typedefs and their original types in the same source. So I'd recommend you use ArrayType throughout or not at all.

Accessing a Class Function when the Class instance is within a Struct

I have an array of structs -
struct MagicalUnicornBullets {
PS2Sprite SparklyUnicornBullet();
bool onscreen;
};
MagicalUnicornBullets MagicalUnicornBullets[25];
I want to loop through the array, and initialise the contents of the struct.
Obviously, this is just the case of a for loop, and for the bool it's simply onscreen = false; but how would I initialise the SparklyUnicornBullet?
Right now my code is -
MagicalUnicornBullets[i].SparklyUnicornBullet.ScaleAbsolute(4,4);
I'm well aware this is wrong - but how do I access the class functions when they're within the Struct?
Realize that SparklyUnicornBullet is actually a member function which returns a PS2Sprite object. This returned PS2Sprite has a member function ScaleAbsolute which you want to call. So your code above is nearly correct. You are simply missing ()'s:
MagicalUnicornBullets[i].SparklyUnicornBullet().ScaleAbsolute(4,4);
That said, there's a number of things that's bad with your code. For one, you are declaring an array that has the same name as an object:
MagicalUnicornBullets MagicalUnicornBullets[25];
I think this is allowed, but it is so evil and malmotivated that I can't even say that for certian, because I would reject any such code regardless of it's motivation or legality. You should give the array a different name:
MagicalUnicornBullets bullets[25];
Next, your initialization loop is unneeded. The code:
MagicalUnicornBullets MagicalUnicornBullets[25];
creates a C-style array of 25 MagicalUnicornBullets by calling each one's default constructor. So the easiest thing to do is to simply provide a default constructor that does what you want:
struct MagicalUnicornBullets {
MagicalUnicornBullets();
// ...
};
MagicalUnicornBullets::MagicalUnicornBullets()
: onscreen(false)
{
SparklyUnicornBullet().ScaleAbsolute(4,4)
}
Now there's no need for a loop at all. All 25 will be constructed and initialized the way you want.
Finally, usually in C++ it's advantagerous to not use a C-style array at all, but a collection class such as std::vector.

Using a vector data structure - design and syntax questions

I have some basic C++ design/syntax questions and would appreciate your reply.
I have N number of regions
Each region needs to store information about an object "element"
i.e. I want to achieve something like this:
region[i].elements = list of all the elements for region i.
Question 1:
Does the following syntax (see code below) / design look correct. Am I missing anything here?
EDIT
The instances of struct elem are created by some other class and its memory deallocation is handles by that class only I just want to access that object and its members using reg[i].elements list (vector) ... so, how should I add these element objects to the vector "elements" in class Region?
//Already have this stucture that I need to use
struct elemt {
int* vertex;
int foo1;
double foo2;
};
class Region{
public:
// I am not sure what should be the syntax here!
// is it correct?
std::vector <elemt*> elements;
}
// Following is the constructor of "class A"
A::A(){
// --header file defines: Region *reg;
// Let numOfRegions be a class variable. ( changes based on "Mac"'s suggestion)
numOfRegions = 100;
//allocate memory:
reg = new Region[numOfRegions];
}
A::~A(){
delete [] reg;
reg = NULL;
}
A::doSomething(){
// here I want to append the elements to the vector
// Let i be region 10.
// Let e1 be an element of "struct elemt" that needs to be added
reg[i].elements.push_back(e1);
}
Question 2:
Is the syntax in doSomething() correct? Later I want to run an iterator over all the elements in reg[i] and want to access, e1->foo1, e1->foo2 and like that.
Question 3:
In do something method, how do I ensure that e1 is not already in the "elements"
UPDATE
Corrected some syntax errors, and hopefully fixed memory leak noticed by user 'Mac. '
First of all get rid of the memory leak from the code.
A::A(int numOfRegions = 100){
m_reg = new Region[numOfRegions]; // define Region *m_reg in the class
}
A::~A(){
delete [] m_reg;
m_reg = NULL;
}
You are allocating memory in the constructor and storing return address in local variable and it ll get destroyed when its scope is over .
You should store the base address so that you can delete it .
How do you know if two elements are same or not?
From your question about detecting if e1 is already there in elements, It seems like a map/set/hash might be a better data structure than a vector.
Also, I believe it is push_back, not pushBack.
You should detach the syntax from the design question. Syntax is something the compiler will check, and enforce, but then again you might get unwanted semantics...
Focusing on the design, what are your requirements? (Sorry I tend to read diagonally if there are more than a couple of lines, so I might have missed something there)
There is a class that creates/destroys elemt objects, is dynamic allocation really a requirement? or is it just because the elements are constructed with data available in the constructing class? If dynamic allocation is a requirement, then it looks like elemt objects should be held by pointer (probably smart pointers). Does the class that is meant to delete the objects keep track of them, or does it just handle the objects to the outside world expecting user code to call a deallocator function? Are the elemt objects shared among different entities? And there are other issues that you should consider...
Maybe you should try to reword your question, the code you posted basically is syntactically correct (just check with a compiler, I did not), but without knowing what you really want to achieve, you cannot really ask whether that is a good or bad design. Describe your real problem and then ask whether the code can be a solution to your requirements.
As you ask for syntax, I can spot a missing semi-colon right away.
Also, public data (such as elements) is not really recommended. Instead, try to use getter and setter functions.
The numOfRegions variable aught to be const int, not just int. Also, feels off to declare it in the c'tor instead of in the class declaration, as it is a tuneable setting. As soon as you want to iterate over reg, you'll need to redeclare it if you keep it as now.
As for question three, you will simply have to check to see if you can find it. You will probably need an bool operator==(const elemt &, const elemt &) to be able to do that conveniently.

C++ Accessing the Heap

This problem involved me not knowing enough of C++. I am trying to access a specific value that I had placed in the Heap, but I'm unsure of how to access it. In my problem, I had placed a value in a heap from a data member function in an object, and I am trying to access it in another data member function. Problem is I do not know how, and I had searched examples online, but none were what I needed as they were all in int main() and were not specifically what I needed.
In the first data member function, I declare the value I want to be sent to the Heap;
Here's an example of what my first data member function.
void Grid::HeapValues()
{
//Initializing Variable
value = 2; //The type is already declared
//Pointers point a type towards the Heap
int* pValue = new int;
//Initialize an a value of in the Heap
*pValue = value;
}
And in data member function This is what want:
void Grid::AccessHeap()
{
//Extracting heap:
int heap_value = *pValue; //*pValue does not exist in this function
cout << heap_value; //Delays the value 2, which is found
//in the first data member function
}
I feel foolish for asking, but I am unable to find the answers and do not how. Does anyone know how to access a value from the heap in a simple way? And I would need it to be able to access in more then two data member function.
pValue needs to be a member-variable of the class Grid.
class Grid
{
private: int* pValue;
public: void HeapValues();
void AccessHeap();
};
Now the member-variable pValue is accessible from any member-function of Grid.
Don't forget to delete your pointer in the destructor when you are done. For more information visit:
http://www.cplusplus.com/doc/tutorial/variables.html <-- Variable scope
http://www.cplusplus.com/doc/tutorial/pointers.html <-- Pointers
http://www.cplusplus.com/doc/tutorial/dynamic.html <-- Dynamic memory
Like Aaron said you can make the value a member of your Grid class. In this case though there is no need for it to be a pointer to an int.
class Grid
{
private:
int value;
public:
void HeapValue();
void AccessHeap();
};
The value will be stored as part of the object wherever it is instanciated. You can make it on the stack or the heap, it doesn't matter. For simple values like the built in types and Objects that will be owned by the instance of the class it is unnecessary to allocate them using new. This way you don't need to worry about cleaning up with the delete operator in the Grid destructor, just make sure you dispose of the owning Grid instance properly ;-)
Of coarse there are exceptions to this that you will learn as you delve more into C++, but for your example the above will be fine.
Why do you want it on the heap? If you add it as part of the class then it will be in the same place the class is, possibly on the stack or in global memory. Perhaps you want to have a variable size to your integer pointer? In that case, then you need to be sure to deallocate the memory when you are done with it.
The problem with stuff on the heap is finding it. There is no accessing it by name, unless you add a mechanism for that. Somehow you need to communicate the location to whatever code needs to access it. In this case, it looks like you only need access within the Grid class, so it is easy. Just make it a member variable like Aaron indicates. You might end up with something like:
class Grid
{
protected:
int* pVals;
public:
Grid() pVals(NULL) { }
~Grid() { delete [] pVals; }
void HeapValues() {
pVals = new int[getHeapValuesSize()];
pVals[0] = 1; // ...
}
void AccessHeap() {
cout << pVals[0]; // ...
}
(On a side note, you appear to be using the phrase "data member function" when you mean "member function". "Data member" refers to member data of a class, like pVals, but I'm not sure what "data member function" would mean.)