Array of pointers to nodes not declared in scope - c++

I'm trying to assign a node to a pointer along an array of pointers but it keeps telling me that my array was not declared in the scope. I'm totally confused on how or why so any help would be greatly beneficial! Thanks for taking the time to respond!
#include <iostream>
#include "book.h"
using namespace std;
class bookstore
{
private:
int amount = 5;
int counting = 0;
public:
bookstore()
{
bookstore *store;
store = new book*[amount];
for(int i = 0; i < amount; i++)
{
store[i] = NULL;
}
}
~bookstore(){ delete[] store; }
void addbook(string a,string b, string c, string d, string e)
{
if (counting == amount)
{
cout<<"Full House!"<<endl;
return;
}
store[counting] = new book(a,b,c,d,e);
counting++;
}
void print()
{
for(int i = 0; i < amount; i++)
{
cout<<store[i]->name<<" "<<store[i]->publisher<<" "<<store[i]->year<<" "<<store[i]->price<<" "<<store[i]->category<<endl;
}
}
};

Your pointer store is local to the default constructor. It looks like you're after a data member. Furthermore, you seem to be after an array of pointers. If so, you need bookstore needs to be a pointer to pointer:
class bookstore
{
private:
bookstore** store; // or bookstore* store
int amount = 5;
int counting = 0;
and fix the constructor to use that:
bookstore()
{
store = new book*[amount]; // or store = new book[amount]
....
Note that your class is attempting to manage dynamically allocated resources, so you will need to take care of the copy constructor and assignment operators (either make the class non-copyable and non-assignable, or implement them. The defaults are not acceptable. See the rule of three.) If you are really using an array of dynamically allocated pointers, then you need to fix your destructor too. Currently, it only deletes the array, but not the objects pointed at by the pointers in it.
The better solution would be to use a class that manages the resources for you and has the desired semantics. It is easier to have each class handle a single responsibility.

Related

C++ Initializing an Array of Objects

I'm having a little trouble grasping some concepts with C++ arrays.
On my assignment, I did something like the code below. From what I can tell, this not only creates space on the heap for [size] Object1 objects, but also initializes all of them too. Can somebody explain what is exactly happening on the heap and stack here?
class Object1
{
Private:
int dummy;
Public:
Object1();
};
Object1::Object1()
{
dummy = 1;
}
class Foo
{
private:
Object1 * myObject;
public:
Foo(int size);
};
Foo::Foo(int size)
{
myObject = new Object1[size];
}
If Object1's constructor had taken a parameter, like in the code below, then what would happen differently on the stack and heap, if anything? I'm not sending any parameters into each instance of object1, so would it still initialize any object, or just create the space?
class Object1
{
Private:
int dummy;
Public:
Object1(int myInt);
};
Object1::Object1(int myInt)
{
dummy = myInt;
}
I also saw the code below somewhere. What is happening in this case, and how is it different than the cases above?
myclass *array[10];
for (int i = 0 ; i != 10 ; i++) {
array[i] = new myclass();
}
I've completed the assignment, but am just trying to make sure I understand what's happening behind the scenes.
Thank you in advance for taking the time to help!
If your class does not have a default constructor, you won't be able to use:
myObject = new Object1[size];
The difference between
myObject = new Object1[size];
and
myclass *array[10];
for (int i = 0 ; i != 10 ; i++) {
array[i] = new myclass();
}
The first one allocates size objects and stores the pointer to the array of objects in myObject.
The second one allocates 10 objects but there are 10 pointers. Each pointer points to only one dynamically allocated object.

inconsistent object IDs inside multiple vector in C++

just a beginner here.
i'm trying to store some objects inside a vector, so i can loop it later, but the reference changes afterwards, i'm not sure what happened
the code's below;
#include <iostream>
#include <vector>
using namespace std;
class Car;
class Garage {
public:
vector<Car*> vCar;
};
class Car {
public:
short id;
};
int main()
{
Garage garage;
short i;
for(i = 0; i < 10; i++) {
Car car;
car.id = i;
garage.vCar.push_back(&car);
}
for(i = 0; i < garage.vCar.size(); i++) {
cout << i << " " << garage.vCar[i]->id << endl;
// output 9,9,9,..9 instead of 1,2,3,4...10, why is that?
}
return 0;
}
vector<Car*> vCar;
is a vector that stores pointers to Car objects.
for(i = 0; i < 10; i++) {
Car car;
car.id = i;
garage.vCar.push_back(&car);
}
Inside the above for loop, you create Car objects on stack. By the end of the for loop, those objects are out of scope and will be destroyed. Therefore, your pointers inside the vector point to some objects that do not exist. You have undefined behavior in your code.
You may store objects directly, which stores copy of the original objects. You can find a Live Demo here.
You're pushing the address of a stack-based object into the vector, but that stack based object will be destroyed as soon as it goes out of scope (so as soon as the iteration of the for-loop is complete). When you dereference the pointer later on you're actually reading from the address on the stack where the last object was created, which is why you get the same value every time.
How you fix this is up to you - you could change the vector to store Car objects rather than pointers to Car objects, you could use smart pointers, etc..
Change
class Garage {
public:
vector<Car*> vCar;
};
To
class Garage {
public:
vector<Car> vCar;
};
And
garage.vCar.push_back(&car);
To
garage.vCar.push_back(car);
This will eliminate the undefined behaviour that you are experiencing ( you are taking an address of an item off the stack!)

How would I create this array of object using pointer

Basically I want to create an array of objects with a size which is passed through from one class to another i.e.
Object * ArrayOfObjects = new Object[Size];
Whilst that creates an array successfully, it doesnt allow me to use constructors.
How can I create an array of my objects then define each object in the array?
Once you allocate memory for the array you can then assign to it by looping:
for (int i = 0; i < Size; ++i)
{
ArrayOfObjects[i] = Object( /* call the constructor */ );
}
Or you can use a vector to do the same but with more ease of use:
std::vector<Object> ArrayOfObjects = { Object(...), Object(...) };
What you're asking may not actually be the best thing to do - which would be to use something like std::vector or something, but under the hood what they're going to do is what your question asks about anyway.
Then you can either assign or placement new each entry:
for (size_t i = 0; i < Size; ++i)
{
// Option 1: create a temporary Object and copy it.
ArrayOfObjects[i] = Object(arg1, arg2, arg3);
// Option 2: use "placement new" to call the instructor on the memory.
new (ArrayOfObjects[i]) Object(arg1, arg2, arg3);
}
Once you allot memory, as you did. You initialize each object by traversing the array of objects
and call its constructor.
#include<iostream>
using namespace std;
class Obj
{
public:
Obj(){}
Obj(int i) : val(i)
{
cout<<"Initialized"<<endl;
}
int val;
};
int allot(int size)
{
Obj *x= new Obj[size];
for(int i=0;i<10;i++)
x[i]=Obj(i);
//process as you need
...
}

Cannot operate on an array of structures which comprise a string C++

I have a structure which includes a string field. I create an array of those structures and then I want to pass them to a function (by reference). Everything works perfectly fine when I comment out the string field, but if I don't the program crashes. I can't find an answer to this anywhere..
Here's the code (I reduced it to only show the issue):
struct student {
int a;
int b;
string name[20];
char status;
};
void operation(student the_arr[1],int number_of_students) {
delete[] the_arr;
the_arr = new student[3];
for(int i = 0; i<3; i++) {
the_arr[i].a = i+5;
the_arr[i].b = i+4;
}
}
int main() {
student *abc;
abc = new student[0];
operation(abc, 0);
system("pause");
return 0;
}
I need the array to be dynamic so I can change its' size when I need to.
Assuming you can't use std::vector instead of dynamically allocated arrays follow the answer below. In any other case you should use the containers provided by the standard library.
Note: Your program doesn't crash. The only things the compiler will complain about it the allocating zero elements part, but will let you compile and run this program.
Your function is completely wrong. When using dynamic allocation you can simply pass a pointer like this:
void operation(student* the_arr, int number_of_students) {
Then inside your function you are dynamically allocating memory which is stored inside the the_arr pointer which is not passed by reference therefore leading to the creation of a local pointer variable that will lose the pointer after its execution:
void operation(student*& the_arr [...]
I suggest you to avoid the below solution though and return the new pointer instead:
student* operation(student* the_arr, int number_of_students) {
delete[] the_arr;
the_arr = new student[3];
[...]
return the_arr; // <----
}
Allocating abc = new student[0]; doesn't make any sense. You are trying to allocate an array of 0 elements. Maybe you meant abc = new student[1];?
You should just use the vector or other sequence objects. Though I'm not sure what you are trying to do with your code. Here's a quick example:
// Vector represent a sequence which can change in size
vector<Student*> students;
// Create your student, I just filled in a bunch of crap for the
// sake of creating an example
Student * newStudent = new Student;
newStudent->a = 1;
newStudent->b = 2;
newStudent->name = "Guy McWhoever";
newStudent->status = 'A';
// and I pushed the student onto the vector
students.push_back( newStudent );
students.push_back( newStudent );
students.push_back( newStudent );
students.push_back( newStudent );

How to clean up class member of pointer to vector of pointers to a class?

I have a class called Foo which has a member that is a pointer to a vector of pointers to another class called Bar. I initialise it in the constructor but I'm not sure how to deallocate it in the destructor. I'm still learning. Would appreciate your help. The reason for having this member is so that the scope persists beyond that method i.e. beyond the stack. Thanks.
#include <iostream>
#include <vector>
using namespace std;
class Bar {};
class Foo {
public:
Foo() {
bars = new vector<Bar*>*[10];
for (int i = 0; i < 10; i++) {
bars[i]->push_back(new Bar());
}
}
~Foo () {
for (int i = 0; i < 10; i++) {
// TODO: how to clean up bars properly?
}
}
private:
vector<Bar*>** bars;
};
int main () {
new Foo();
return 0;
}
Update: I appreciate the feedback on all fronts. I'm new to C and C++. Basically I wanted a 2d structure as a class member that would persist for the lifetime of the class. The reason the outer structure is an array is because I know how big it needs to be. Otherwise I was previously using vector of vectors.
This isn't even allocated properly. You allocate an array of pointers to std::vector<Bar*>, but never any std::Vector<Bar*>.
The best thing to do is just something like std::vector<std::unique_ptr<Bar>> or even std::unique_ptr<std::vector<std::unique_ptr<Bar>>> or something like that. What you've got is just WTF.
Or std::unique_ptr<std::array<std::unique_ptr<std::vector<std::unique_ptr<Bar>>>, 10>>.This is an exact match (but self-cleaning).
The number of pointers is a bit ridiculous, as all they are doing is causing confusion and leaks, as evident from non-proper initialization and the question's title. You don't actually need any pointers at all, and don't have to worry about any cleanup.
For a 2D array with the first dimension passed into the constructor, you can use a vector of vectors:
std::vector<std::vector<Bar>> bars;
To initialize the outer vector with the passed in size, use an initializer:
Foo(size_t size)
: bars(size) {}
When the object is destroyed, bars and all of it elements are as well, so there's no chance of forgetting to clean up or doing so improperly.
If performance is an issue, this can be translated into a sort of Matrix2D class that acts like a 2D array, but really only has an underlying 1D array.
EDIT: In the case of a 2D structure (and you said you know how big your 2D structure needs to be, so we'll assume that the 10 in your loops is the size of the 2D array you desire.
#include <iostream>
#include <vector>
using namespace std;
class Bar {
public:
int BarInfo;
};
class Foo {
public:
Foo() {
// Allocates 10 vector spots for 10 bar elements - 100 bars, 10 x 10
for (int i = 0; i < 10; i++) {
// Puts 10 bars pointer at the end;
// Heap-allocated (dynamically), which
// means it survives until you delete it
// The [10] is array syntax, meaning you'll have 10 bars
// for each bars[index] and then
// you can access it by bars[index][0-9]
// If you need it to be more dynamic
// then you should try vector<vector<Bar>>
bars.push_back(new Bar[10]);
}
}
Bar* operator[] (int index) {
return bars[index];
}
~Foo () {
// Cleanup, because you have pointers inside the vector,
// Must be done one at a time for each element
for (int i = 0; i < bars.size(); i++) {
// TODO: how to clean up bars properly?
// Each spot in the vector<> contains 10 bars,
// so you use the array deletion
// and not just regular 'delete'
delete[] bars[i]; // deletes the 10 array elements
}
}
private:
// vector might not be a bad idea.
vector<Bar*> bars;
};
This is the main I have for testing the code written, and it works like you would think a 2D array should work:
int main ( int argc, char* argv[] ) {
Foo foo;
// Bar at 1st row, 2nd column ( row index 0, column index 1 )
// Bar& is a reference
Bar& bar12 = foo[0][1];
bar12.BarInfo = 25;
int stuffInsideBar = foo[0][1].BarInfo; // 25
return 0;
}
I hope that helps and gets you closer to what you're doing. I've used a technique here that might go over a starters head to make the Foo class behave like you would think a 2D array would. It's called operator overloading. It's a powerful feature in C++, so once you master more basics it might be useful to you in your future projects or current one. Good luck!
~~~~~~~~~~~~~~~~~~~~~~~
OLD ANSWER BEFORE EDIT
~~~~~~~~~~~~~~~~~~~~~~~
It appears you're doing far too much indirection. While another person's answer shows you how to clean up what you've managed to do, I think you could benefit from changing how exactly you're handling the class.
#include <iostream>
#include <vector>
using namespace std;
class Bar {};
class Foo {
public:
Foo() : bars() {
// bars is no longer a pointer-to-vectors, so you can just
// allocate it in the constructor - see bars() after Foo()
//bars = new vector<Bar>();
for (int i = 0; i < 10; i++) {
// Puts 1 bar pointer at the end;
// Heap-allocated (dynamically), which
// means it survives until you delete it
bars.push_back(new Bar());
}
}
~Foo () {
// Cleanup, because you have pointers inside the vector,
// Must be done one at a time for each element
for (int i = 0; i < 10; i++) {
// TODO: how to clean up bars properly?
// TODOING: One at a time
delete bars[i]; // deletes pointer at i
}
}
private:
// You don't need to ** the vector<>,
// because it's inside the class and
// will survive for as long as the class does
// This vector will also be copied to copies of Foo,
// but the pointers will remain the same at the time
// of copying.
// Keep in mind, if you want to share the vector, than
// making it a std::shared_ptr of a
// vector might not be a bad idea.
vector<Bar*> bars;
};
If you pass the class by reference into functions, than the vector<Bar*> inside the class won't copy itself or delete itself, making it persist past a single stack frame.
In your main, this should clean up properly and is a lot easier to keep track of than vector** . However, if for some reason vector** is required, than home_monkey's answer should help you more.
I think there is an issue with allocation. The line
new vector <Bar*> * [10]
will give you an array of points to objects of type vector <Bar*> * and you
will need to allocate some additional memory for your vector <Bar*> type.
I've had a go,
Foo()
{
bars = new vector<Bar*>*[10]; // A.
for (int i = 0; i < 10; i++)
{
bars[i] = new vector<Bar*>; // B. Extra memory assigned here.
bars[i]->push_back(new Bar); // C.
}
}
To free resources, you'll have to reverse the above
~Foo ()
{
for (int i = 0; i < 10; i++)
{
// I'm assuming that each vector has one element
delete bars[i][0]; // Free C
delete bars[i]; // Free B
}
delete [] bars; // Free A
}
I don't believe you're even allocating it properly. To undo what you've done so far, all you'd have to do is:
for(int i=0; i < 10; ++i)
while(bars[i]->size > 0)
{
delete *bars[i]->front();
pop_front();
}
delete[] bars;
But, you need to allocate each of the vectors themselves, for instance in the constructor:
for(int i=0; i<10; ++i)
bars[i] = new vector<Bar*>();
Which would require you change the destructor to:
for(int i=0; i < 10; ++i)
{
while(bars[i]->size > 0)
{
delete *bars[i]->front();
pop_front();
}
delete bars[i];
}
delete[] bars;
With regard to your update, I would then suggest changing the type of bars to:
vector<Bar*>* bars;
and the allocation to (without the need to do the for loop allocation suggested above):
bars = new vector<Bar*>[10];