I have two structures in which the second structure has the first structure nested inside of it:
struct first
{
int a;
};
struct second
{
first nested;
};
Now the problem is that the second structure has to be dynamically allocated through a pointer. Also, the nested first structure has to be a dynamically allocated array through a pointer, whose array size has to be read in through an input file.
I know how to read it in but I don't know how to access it. For example lets suppose the size is 8. How would I go about specifying the values for the second structure given the pointer's format?
I tried assuming ptr points to first structure and ptr1 points to second structure ptr1->((ptr+count)->a) where we can process it through a loop. This doesn't work. So I was wondering how you would initialize the values the second structure whose member includes all the n structures in the n element array.
Vector is really easy just stick your struct where type is and use it like any other array. Although what you described really sounds like linked list but hey vector will probably be better for you :)
#include <vector>
//main
vector <Type> myArray(8); //set the number of elements you want
myArray[0] = blablabla
More specific example:
struct first
{
int a;
};
vector <first> myArray(8);
first[0].a = 1; // you get the idea :)
EDIT
From the comments this seems to me more up your alley.
struct bla {
int num;
};
//in main
bla *balBla = NULL;
blaBla = new(bla[8]); //There made on the fly dynamic man
blaBla[0].num = 7;
//Don't forget to delete when done or scary memory leak!!!
delete[] blaBla;
Last Edit If this is not what you want then no one will ever understand what you mean
#include <iostream>
using namespace std;
struct b {
int num;
};
struct a {
b *nested = NULL;
a(){} //Default Constructor
a(int elements) {
nested = new(b[elements]);
} //Lets you add elements to nested at initialization
void addElem(int elements) {
if (nested != NULL) {
delete[] nested;
}
nested = new(b[elements]);
} //Redefine or make new array
~a() {
delete[] nested;
} //destructor
};
int main() {
a myStupidObj(3);
myStupidObj.nested[0].num = 69;
myStupidObj.nested[1].num = 77;
myStupidObj.nested[2].num = 666;
cout << "Struct of one D array of structs" << endl;
cout << myStupidObj.nested[0].num << endl;
cout << myStupidObj.nested[1].num << endl;
cout << myStupidObj.nested[2].num << endl;
//Make 2d version
a *my2DStupidObj = new(a[2]);
my2DStupidObj[0].addElem(3);
my2DStupidObj[0].nested[0].num = 666;
my2DStupidObj[0].nested[1].num = 6969;
my2DStupidObj[0].nested[2].num = 80085;
cout << "array of struct of one D array of structs" << endl;
cout << my2DStupidObj[0].nested[0].num << endl;
cout << my2DStupidObj[0].nested[1].num << endl;
cout << my2DStupidObj[0].nested[2].num << endl;
my2DStupidObj[1].addElem(3);
my2DStupidObj[1].nested[0].num = 11;
my2DStupidObj[1].nested[1].num = 111;
my2DStupidObj[1].nested[2].num = 1111;
cout << my2DStupidObj[1].nested[0].num << endl;
cout << my2DStupidObj[1].nested[1].num << endl;
cout << my2DStupidObj[1].nested[2].num << endl;
delete [] my2DStupidObj;
return 0;
}
In C, you sometimes see something like:
struct second {
int count;
first nested[1];
};
Then, you allocate memory. The amount you allocate is computed as sizeof(struct second) plus the size of first times the number of elements you want in the array minus 1 (since there is already one included).
ptr = (struct second *)malloc(sizeof(struct second) + ((n-1) * sizeof(first)));
Then you can use
ptr->nested[idx].a
or if you have to use pointers,
((ptr->nested)+idx)->a
Of course, you have to do all the housework and cleanup yourself. C++ and its std libraries do most of that for you.
Related
I would like to identify a canonical approach to allocating the equivalent of an array of pointers to pointers to int (like: int ** int_array), but using unique_ptr.
I would like a C++11 solution that is extensible to an array of pointers to pointers to an instance of a class, if possible (I've used ints here to simplify, and I realize there may be other issues when using class instances).
I understand how to create a fixed-size array of unique_ptr where the size is known in advance. The goal is to do the same where the array size is not known.
I have looked at a number of related solutions including the one below, but they seem to deal only with fixed allocation of unique_ptr arrays (that is, the size of the array of unique_ptr is already known in advance):
Proper way to create unique_ptr that holds an allocated array
I've implemented a simple program that attempts to demonstrate and compare 3 approaches: traditional dynamic creations of pointers, a fixed array of unique_ptr, and the goal: a dynamic array of unique_ptr.
#include <iostream> // include iostream
#include <memory> // include memory
using namespace std;
int main() {
cout << "Testing dynamic arrays of pointers\n";
int **num_array; // typical dynamic array of pointers to int
int count; // count of ints the user wants to generate
unique_ptr<int[]> f_num_array(new int[200]());
// above: fixed array of unique pointers to int - not what I want
unique_ptr<int[]> u_num_array;
// above: GOAL: dynamic array of unique pointers to int
int sum, u_sum, f_sum;
// above: test sum of each type of array (should match user count)
cout << "How many pointers would you like? ";
cin >> count; // get user input
num_array = new int*[count]; // allocate array of pointers on heap
//u_num_array = new int[count](); // GOAL - would like to do this
// above: ERROR: no overload for =; cannot allocate this way
for(int i=0; i<count; i++) { // allocate ints and store pointer
num_array[i] = new int(1); // pointer to an int on the heap
f_num_array[i] = 1; // assign 1 to the pre-allocated unique pointer array
unique_ptr<int> u_tmp(new int(1)); // temporary unique_ptr to int
// u_num_array[i] = u_tmp; // GOAL - would like to do this...
// ERROR: cannot assign unique_ptr this way
}
sum = 0; f_sum = 0; u_sum = 0; // init our sums to verify
for(int i=0; i<count; i++){
sum += *(num_array[i]); // summing our traditional array of pointers
f_sum += f_num_array[i]; // summing our fixed unique array of pointers
}
cout << "Sum = " << sum << "\n";
cout << "Sum (fixed unique_ptr array) = " << f_sum << "\n";
cout << "Sum (dynamic unique_ptr array) = " << u_sum << "\n";
delete[] num_array; // delete the dynamic array
f_num_array.release(); // delete the dynamic array
cout << "\nDone!\n";
}
#include <iostream>
#include <memory>
#include <vector>
int main() {
std::cout << "Testing dynamic arrays of pointers\n";
//int **num_array; - Never use except you are forced by some external interface.
int count = 0; // Always initialize variables
std::vector<std::unique_ptr<int>> num_array;
std::cout << "How many pointers would you like? ";
std::cin >> count; // get user input
num_array.resize(count);
for (auto& p : num_array) // You can do it with some algorithm, but I prefer this way
p = std::make_unique<int>(1);
int sum = 0; // Don't declare variables before you use them.
for (auto& p : num_array)
sum += *p;
std::cout << "Sum = " << sum << "\n";
num_array.clear();
std::cout << "\nDone!\n";
}
(Disclaimer: Pointers in C++ is a VERY popular topic and so I'm compelled to believe that someone before me has already raised this point. However, I wasn't able to find another reference. Please correct me and feel free to close this thread if I'm wrong.)
I've come across lots of examples that distinguish between pointer to first element of array and pointer to the array itself. Here's one program and its output:
//pointers to arrays
#include <iostream>
using namespace std;
int main() {
int arr[10] = {};
int *p_start = arr;
int (*p_whole)[10] = &arr;
cout << "p_start is " << p_start <<endl;
cout << "P_whole is " << p_whole <<endl;
cout << "Adding 1 to both . . . " <<endl;
p_start += 1;
p_whole += 1;
cout << "p_start is " << p_start <<endl;
cout << "P_whole is " << p_whole <<endl;
return 0;
}
Output:
p_start is 0x7ffc5b5c5470
P_whole is 0x7ffc5b5c5470
Adding 1 to both . . .
p_start is 0x7ffc5b5c5474
P_whole is 0x7ffc5b5c5498
So, as expected, adding 1 to both gives different results. But I'm at a loss to see a practical use for something like p_whole. Once I have the address of the entire array-block, which can be obtained using arr as well, what can I do with such a pointer?
For single arrays, I don't think there's much point to it. Where it becomes useful is with multi-dimensional arrays, which are arrays of arrays. A pointer to one of the sub-arrays is a pointer to the row, and incrementing it gets you a pointer to the next row. In contrast, a pointer to the first element of the inner array is a pointer to a single element, and incrementing it gets you the next element.
int (*)[10] is a "stronger" type than int* as it keeps size of the array,
so you may pass it to function without passing additional size parameter:
void display(const int(*a)[10]) // const int (&a)[10] seems better here
{
for (int e : *a) {
std::cout << " " << e;
}
}
versus
void display(const int* a, std::size_t size) // or const int* end/last
{
for (std::size_t i = 0; i != size; ++i) {
std::cout << " " << a[i];
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I just wrote a simplified implementation of the stack data structure in a class, but the handling of an integer array is behaving in a way that I can't seem to understand.
The same snippet of code as in push() will give the behavior I expect, but in this program assigning a value at a certain array position will assign the value to the index variable>
#include <iostream>
using namespace std;
class stack
{
public:
stack(int size)
{
ar_size = size - 1;
array[ar_size];
index = 0;
}
void push(int value)
{
cout << "index; " << index << endl; //will output 0
cout << "value: " << value << endl; //will output 8
array[index++] = value;
cout << "index; " << index << endl; //will output 8
cout << "value: " << value << endl; //will output 8
cout << "array: " << array[index] << endl; //will output what seems to be a memory address
}
int pop()
{
cout << "index; " << index << endl; //will output 8
return array[index--];
}
private:
int ar_size;
int array[];
int index;
};
int main()
{
stack tower(64);
tower.push(8);
int r = tower.pop();
cout << "pop: " << r << endl; //will output what seemed to be a memory address
return 0;
}
Here is the corrected code of your example:
#include <iostream>
class stack
{
public:
stack(int size)
{
ar_size = size - 1;
array = new int[size];
index = 0;
}
void push(int value)
{
array[index++] = value;
}
int pop()
{
return array[--index];
}
~stack()
{
delete array;
}
private:
int ar_size;
int *array;
int index;
};
int main()
{
stack tower(64);
tower.push(8);
int r = tower.pop();
std::cout << "pop: " << r << std::endl; //Will output 8 :)
return 0;
}
There were several issues with it.
As pointed out in the comments array[ar_size]; in your constructor did not do what you wanted it to. array[ar_size]; accesses the array at the given index, it does not allocate the array for you. I've fixed the problem so that the array is now allocated via new and deleted when the stack is destroyed.
return array[index--]; was not right as well. You need to lower the index before accessing the element. return array[--index]; is now right.
You're missing a BUNCH of checks so that your stack does not cause a segfault or any other undefined behaviour. You need to check if you can still push values or if you can pop values and so on.
I hope it clears things up a bit.
You could use dynamic memory allocation.Something like this
private:
int ar_size;
int *array;//pointer to array
int index;
and then in the constructor
stack(int size)
{
ar_size = size - 1;
array=new int[ar_size];
index = 0;
}
Since this is dynamic memory allocation make sure to free the allocated memory.You can have a destructor
~stack()
{
delete[] array;
}
Another point is after you push an element,you increase the index by 1.So now index does point to the next insertion point in the stack.So if you do a pop operation it will remove an element from index location but there is no element there yet.So you can change your pop function to
int pop()
{
cout << "index; " << index << endl; //will output 8
return array[--index];//now index will point to the top element
}
I think you want array = new int[ar_size]; instead of array[ar_size];. You'll need to make a destructor that does delete [] array; as well then.
I'm trying to figure out how I can or why I can't access the member of this class. First I'll show you what works so you know what I'm thinking, then I'll show you what I can't seem to do.
What I can do is this: I have a class with a member. I make an pointer array of that class and make NEW pieces of it (through loop) and that's fine and all. I can also make another class with a similar array and even make NEW instances of that as well and initialize them, but when I try to access them, I have problems.
This code almost works fine:
#include <iostream>
using namespace std;
class testClass{
public:
int number;
};
class testPoint{
public:
testClass testInstance;
testClass *testclassArray[5];
void makeArray();
void setToI();
};
void testPoint::makeArray(){
for (int i = 0; i < 5; i++){
testclassArray[i] = new testClass;
}
}
void testPoint::setToI(){
for (int i = 0; i < 5; i++){
(*testclassArray[i]).number = i;
}
}
int main(void){
testPoint firstTestPoint;
firstTestPoint.makeArray();
firstTestPoint.setToI();
// EXCEPT FOR THIS LINE this is where I have problems
cout << firstTestPoint.(*testclassArray[0]).number << endl;
return 0;
}
I know this should work becuase this works
int main(void){
testPoint firstInstance;
firstInstance.testInstance.number = 3;
cout << firstInstance.testInstance.number << endl;
// and this works
return 0;
}
and this works
int main(void){
testClass *testPointer[5];
for (int i = 0; i < 5; i++){
testPointer[i] = new testClass;
(*testPointer[i]).number = i;
}
cout << (*testPointer[0]).number << endl;
return 0;
}
so why can't I access the members on the cout function the same way?
The following is invalid syntax:
cout << firstTestPoint.(*testclassArray[0]).number << endl;
The most common way to write what you are trying to accomplish is:
cout << firstTestPoint.testclassArray[0]->number << endl;
But, if you prefer, you can also write:
cout << (*firstTestPoint.testclassArray[0]).number << endl;
(The second way is far less common.)
The . operator is used to access members of direct objects, e.g. a.member where a might be declared as struct A a;. The -> operator is used to access members of indirect objects (aka pointers to objects), e.g. b->member where b might be declared as struct B* b = new B();.
You are dereferencing the variable in an incorrect way.
Try doing
cout << firstTestPoint.testclassArray[0]->number << endl;
instead.
In the same way the second attempt, where it works for you, could also have been written:
out << testPointer[0]->number << endl;
Try using this code:
cout << firstTestPoint.testclassArray[0]->number << endl;
I'm working my way through Accelerated C++ and have decided to mess around with the one of structs that were defined in there. While doing so, I've come across a problem: creating a vector of these structs and modifying the elements in each one seems to modify the elements in all of them.
I realize that this probably means I've initialized all the structs in the vector to a struct at a single memory address, but I used the .push_back() method to insert "dummy" structs in to the vector. I was under the impression that .push_back() pushes a copy of its argument, effectively creating a new struct.
Here is the header for the struct:
#ifndef _STUDENT_INFO__CHAPTER_9_H
#define _STUDENT_INFO__CHAPTER_9_H
#include <string>
#include <iostream>
#include <vector>
class Student_info9{
public:
Student_info9(){homework = new std::vector<double>;};
Student_info9(std::istream& is);
std::string getName() const {return name;};
double getMidterm() const {return midterm;};
double getFinal() const {return final;};
char getPassFail() const {return passFail;};
std::vector<double> *getHw(){return homework;};
void setName(std::string n) {name = n;};
void setMidterm(double m) {midterm = m;};
void setFinal(double f) {final = f;};
private:
std::string name;
double midterm;
double final;
char passFail;
std::vector<double> *homework;
};
#endif /* _STUDENT_INFO__CHAPTER_9_H */
And here is the code that i'm fooling around with (excuse the excessive print statements... the result of some time trying to debug :) ):
vector<Student_info9> did9, didnt9;
bool did_all_hw9(Student_info9& s)
{
vector<double>::const_iterator beginCpy = s.getHw()->begin();
vector<double>::const_iterator endCpy = s.getHw()->end();
return(find(beginCpy, endCpy, 0) == s.getHw()->end());
}
void fill_did_and_didnt9(vector<Student_info9> allRecords)
{
vector<Student_info9>::iterator firstDidnt = partition(allRecords.begin(), allRecords.end(), did_all_hw9);
vector<Student_info9> didcpy(allRecords.begin(), firstDidnt);
did9 = didcpy;
vector<Student_info9> didntcpy(firstDidnt, allRecords.end());
didnt9 = didntcpy;
}
int main(int argc, char** argv) {
vector<Student_info9> students;
Student_info9 record;
for(int i = 0; i < 5; i++)
{
students.push_back(record);
}
for(int i = 0; i < students.size(); i++)
{
students[i].setMidterm(85);
students[i].setFinal(90);
students[i].getHw()->push_back(90);
std::cout << "student[" << i << "]'s homework vector size is " << students[i].getHw()->size() << std::endl;
students[i].getHw()->push_back(80);
std::cout << "student[" << i << "]'s homework vector size is " << students[i].getHw()->size() << std::endl;
students[i].getHw()->push_back(70);
std::cout << "student[" << i << "]'s homework vector size is " << students[i].getHw()->size() << std::endl;
std::cout << "Just pushed back students[" << i << "]'s homework grades" << std::endl;
if(i == 3)
students[i].getHw()->push_back(0);
}
std::cout << "student[3]'s homework vector size is " << students[3].getHw()->size() << std::endl;
for(vector<double>::const_iterator it = students[3].getHw()->begin(); it != students[3].getHw()->end(); it++)
std::cout << *it << " ";
std::cout << std::endl;
std::cout << "students[3] has " << ( ( find(students[3].getHw()->begin(),students[3].getHw()->end(), 0) != students[3].getHw()->end()) ? "atleast one " : "no " )
<< "homework with a grade of 0" << std::endl;
fill_did_and_didnt9(students);
std::cout << "did9's size is: " << did9.size() << std::endl;
std::cout << "didnt9's size is: " << didnt9.size() << std::endl;
}
As you can see by the print statements, it seems that the homework grades are being added only to one Student_info9 object, copies of which seem to be populating the entire vector. I was under the impression that if you were to use consecutive copies of .push_back() on a single object, it would create copies of that object, each with different memory addresses.
I'm not sure if that's the source of the problem, but hopefully someone could point me in the right direction.
Thanks.
When you push a StudentInfo onto the vector, it is indeed copied, so that's not the problem. The problem is the vector containing the homework grades. Since you only store a pointer to that vector in StudentInfo, only the pointer, not the vector, is copied when you copy a StudentInfo. In other words you have many different StudentInfos that all have a pointer to the same homework vector.
To fix this you should define a copy constructor which takes care of copying the homework vector.
Have you learned about the copy constructor yet? If so, think about what is happening with vector<Student_info9> students on push_back().
Specifically, what happens with this pointer.
std::vector<double> *homework;
The line Student_info9 record; constructs a Student_info9 using the first constructor. This first constructor creates a vector and stores a pointer to it as a member variable. You then proceed to add a copy of this Student_info9 to a vector 5 times. Each copy has a pointer to the same vector.
Your StudentInfo9 class contanis a pointer to a std::vector<double>, which means in the default copy constructor (which will be called when you add a StudentInfo9 object to your vector), the pointer itself is copied. That means all of your StudentInfo9 objects have the same homework vector.
Does that make sense? Please refer to http://pages.cs.wisc.edu/~hasti/cs368/CppTutorial/NOTES/CLASSES-PTRS.html for a more in depth look at pointers and copy constructors.