I'm trying to build an understanding of objects, arrays, and pointers. When I compile my code I ended up with 0xCCCCCCCC. I understand that this error is probably due to an uninitialized pointer. The problem is I don't know where or how to.
#include <iostream>
#include <string>
using namespace std;
class Person {
public:
string name;
};
void createPerson(Person* person[]);
int main() {
Person* person[5];
createPerson(person);
for (int i = 0; i < 5; i++) {
cout << person[i]->name << endl;
}
return 0;
}
void createPerson(Person* person[]) {
string n[5] = { "Dwayne Johnson", "Connor McGregor", "SpongeBob","BatMan", "Ash Ketchum" };
for (int i = 0; i < 5; i++) {
person[i]->name = n[1];
}
}
I'm trying to get the list of names to display.
The Problem is you have an Array of Person Person* person[] pointers and not an array of persons. I fixed the code and removed the pointers:
#include <iostream>
#include <string>
using namespace std;
class Person {
public:
string name;
};
void createPerson(Person person[]);
int main() {
Person person[5];
createPerson(person);
for (int i = 0; i < 5; i++) {
cout << person[i].name << endl;
}
return 0;
}
void createPerson(Person person[]) {
string n[5] = { "Dwayne Johnson", "Connor McGregor", "SpongeBob","BatMan", "Ash Ketchum" };
for (int i = 0; i < 5; i++) {
person[i].name = n[i];
}
}
As you can see I removed the pointer from your array definitions. This way the Person object gets initialized on the stack. In your way the pointers get initialized, but they dont point to anything. Thats why you get your error, because the pointers are dangling. If you really want to use an array of pointer you have to initialize these pointers like this:
#include <iostream>
#include <string>
using namespace std;
class Person {
public:
string name;
};
void createPerson(Person* person[]);
int main() {
Person* person[5];
createPerson(person);
for (int i = 0; i < 5; i++) {
cout << person[i]->name << endl;
//delete person so that we dont leak mem
delete person[i];
}
return 0;
}
void createPerson(Person* person[]) {
string n[5] = { "Dwayne Johnson", "Connor McGregor", "SpongeBob","BatMan", "Ash Ketchum" };
for (int i = 0; i < 5; i++) {
person[i] = new Person();
person[i]->name = n[i];
}
}
BTW: I would not use pointers this way. If you are new and try to understand stuff its fine to experiment. But you should almost always use smart_pointers like std::shared_ptr etc. The next thing to experiment with should be containers and proper data structures.
You are declaring an array of pointers of Person, but not initializing those pointers. By default, a pointer can point to some random location based on what garbage value is stored in its respective address (in this case 0xCCCCCCCC).
Solution is simple, just allocate a new memory using new keyword.
Also, since you are using new to allocate memory, you should call delete to de-allocate memory when you no longer require those pointers.
#include <iostream>
#include <string>
using namespace std;
class Person {
public:
string name;
};
void createPerson(Person* person[]);
int main() {
Person* person[5];
createPerson(person);
for (int i = 0; i < 5; i++) {
if (person[i] != nullptr)
cout << person[i]->name << endl;
}
for (int i = 0; i < 5; i++) {
if (person[i] != nullptr)
delete person[i];
}
return 0;
}
void createPerson(Person* person[]) {
string n[5] = { "Dwayne Johnson", "Connor McGregor", "SpongeBob","BatMan", "Ash Ketchum" };
for (int i = 0; i < 5; i++) {
person[i] = new Person();
person[i]->name = n[i];
}
}
In C++, you can use smart pointers instead of raw pointers also. See this
Related
I am working on a sample test in the site: https://www.testdome.com/for-developers/solve-question/9808
I added two destructors for base class and derived class respectively to release the memory allocated by constructors. The first two requirements of this question are solve successfully, but the result give a fail as: Using timed multiple choice test as multiple choice test: Memory limit exceeded
My modified code as given below, I will appreciate if you can help to fix the fail...
#include <iostream>
#include <string>
class MultipleChoiceTest
{
public:
MultipleChoiceTest(int questionsCount)
{
this->questionsCount = questionsCount;
answers = new int[questionsCount];
for (int i = 0; i < questionsCount; i++)
{
answers[i] = -1;
}
}
void setAnswer(int questionIndex, int answer)
{
answers[questionIndex] = answer;
}
int getAnswer(int questionIndex) const
{
return answers[questionIndex];
}
~MultipleChoiceTest()
{
delete answers; // release memory
}
protected:
int questionsCount;
private:
int* answers;
};
class TimedMultipleChoiceTest : public MultipleChoiceTest
{
public:
TimedMultipleChoiceTest(int questionsCount)
: MultipleChoiceTest(questionsCount)
{
times = new int[questionsCount];
for (int i = 0; i < questionsCount; i++)
{
times[i] = 0;
}
}
void setTime(int questionIndex, int time)
{
times[questionIndex] = time;
}
int getTime(int questionIndex) const
{
return times[questionIndex];
}
~TimedMultipleChoiceTest()
{
delete times; // release memory
}
private:
int* times;
};
#ifndef RunTests
void executeTest()
{
MultipleChoiceTest test(5);
for (int i = 0; i < 5; i++)
{
test.setAnswer(i, i);
}
for (int i = 0; i < 5; i++)
{
std::cout << "Question " << i + 1 << ", correct answer: " << test.getAnswer(i) << "\n";
}
}
int main()
{
for (int i = 0; i < 3; i++)
{
std::cout << "Test: " << i + 1 << "\n";
executeTest();
}
}
#endif
you should use delete [] instead of delete to deallocate dynamic arrays.
Also, you don't seem to use the derived class but, nevertheless, the destructor in MultipleChoiceTest should be virtual
This is my class
class Process {
public:
Process();
void createBurstArray(int *bursts, int sizeOfArray);
void createIOArray(int *IO, int capacity);
int *burstArray;
int *ioArray;
int currentBurst;
int currentIO;
int currentState;
};
Process::Process()
{
}
void Process::createBurstArray(int *bursts, int capacity){
burstArray = new int[capacity];
burstArray = bursts;
};
void Process::createIOArray(int *IO, int capacity) {
ioArray = new int[capacity];
ioArray = IO;
for (int i = 0; i < capacity; i++)
};
void main(){
int processOneBursts[7] = { 12,10,15,11,9,10,11 };
int processOneIO[6] = { 44,52,21,42,31,77 };
Process processes[9];
Process one;
processes[0] = one;
one.createBurstArray(processOneBursts, 7);
one.createIOArray(processOneIO, 6);
}
When I try accessing the ioArray
one.ioArray[1]
I get the value stored in the ioArray at index 1, butw hen I try accessing the ioArra through my object array index it doesn't work:
for (int i = 0; i < 9; i++) {
cout << processes[i].ioArray[i] << endl;
}
What am I doing wrong?
#include <iostream>
using namespace std;
class Process {
public:
// Process();
void createBurstArray(int *bursts, int sizeOfArray);
void createIOArray(int *IO, int capacity);
int *burstArray;
int *ioArray;
int currentBurst;
int currentIO;
int currentState;
};
int main()
{
Process p[10];
for (int i = 0; i < 9; i++) {
p[i].ioArray = new int[1];
}
for (int i = 0; i < 9; i++) {
p[i].ioArray[0] = i;
}
for (int i = 0; i < 9; i++) {
cout << p[i].ioArray[0] << endl;
}
return 0;
}
This works, i think you didn't initialize the dynamic array.
You are object of the class with default constructor which means all the elements in the class will be uninitialized including the element int *ioArray;.
And you are trying to access ioArray in the for loop which is road set to segmentation fault.
To correct this, you must initialize the element before using them.
Also, Your below function is problematic.
void Process::createIOArray(int *IO, int capacity) {
ioArray = new int[capacity];
ioArray = IO;
}
This is a memory leak, since you have assign ioArray to IO ,new int[capacity] memory will not be freed.
Solution:
#include <iostream>
using namespace std;
class Process {
public:
Process();
void createBurstArray(int sizeOfArray);
void createIOArray(int capacity);
int *burstArray;
int *ioArray;
int currentBurst;
int currentIO;
int currentState;
// Don't forget to delete burstArray, ioArray in destructor.
};
void Process::createIOArray(int capacity) {
ioArray = new int[capacity];
};
void Process::createBurstArray(int sizeOfArray) {
burstArray = new int[sizeOfArray];
};
Process::Process(){
createIOArray(10);
createBurstArray(10);
// Similarly you have to initialize other members of the class
}
int main()
{
Process processes[9];
for (int i = 0; i < 9; i++) {
cout << processes[i].ioArray[i] << endl;
}
}
I'm new to C++, and I'm having significant trouble with creating an array of objects using a pass by pointer and reference. This is not the actual code; it's an example of what the code essentially does.
#include <iostream>
class MyClass
{
public:
MyClass();
static int doStuff(MyClass *&classArray);
void print_number();
private:
int number;
};
MyClass::MyClass()
{
}
int MyClass::doStuff(MyClass *&classArray)
{
int i = 0;
for (i = 0; i < 10; i++) {
*classArray[i].number = i;
}
return i;
}
void MyClass::print_number()
{
std::cout << number << "\n";
}
int main(void)
{
MyClass *test = nullptr;
int p = MyClass::doStuff(test);
std::cout << p << '\n';
for (int i = 0; i < 10; i++) {
test[i].print_number();
}
return 0;
}
When compiled, this gives a segmentation fault.
This is how you do it (don't forget do delete classArray with delete[] at the end of your program or destructor:
new operator has to have default constructor, if you want to use non-default it is easier to create copy constructor, then a temporary object and copy.
#include <iostream>
class MyClass
{
public:
MyClass();
MyClass(int x, int y);
MyClass(MyClass &OldClass);
static int doStuff(MyClass *&classArray, int Size, int x, int y);
void print_number();
private:
int number, x, y;
};
MyClass::MyClass()
{
number = 0;
x = 0;
y = 0;
}
MyClass::MyClass(int x, int y)
{
number = 0;
this->x = x;
this->y = y;
}
MyClass::MyClass(MyClass &OldClass)
{
this->number = OldClass.number;
this->x = OldClass.x;
this->y = OldClass.y;
}
int MyClass::doStuff(MyClass *&classArray, int Size, int x, int y)
{
if (Size > 0)
{
classArray = new MyClass[Size];
for (int i = 0; i < Size; i++)
{
classArray[i] = MyClass(x, y);
classArray[i].number = i;
}
return Size;
}
else
return 0;
}
void MyClass::print_number()
{
std::cout << number << " " << x << " " << y << "\n";
}
int main(void)
{
MyClass *test = nullptr;
int p = MyClass::doStuff(test, 10, 5, 6);
std::cout << p << '\n';
for (int i = 0; i < p; i++) {
test[i].print_number();
}
delete[] test;
std::cin.get();
return 0;
}
It is not working because you need to allocate the array, as the function is trying to access elements of an array which has yet not been initialized to hold that amount of elements. You can do this by
MyClass *test = new MyClass[array_size];
Or
MyClass test[array_size];
Or by using a resizable container such as std::vector, and changing the function parameters accordingly
*classArray[i].number = i;
You called doStuff with a null pointer, so classArray is null and is not an array. Dereferencing a null pointer results in undefined behavior and on most implementations you'll usually get a crash.
You're also dereferencing something that's not a pointer so this code will not even compile. The error I get is:
main.cpp:23:9: error: indirection requires pointer operand ('int' invalid)
*classArray[i].number = i;
^~~~~~~~~~~~~~~~~~~~~
Presumably this is just because, as you say, the code you're showing is not your real code and classArray[i].number corresponds to a pointer in your real code. But I thought I'd point this out anyway, just in case.
Given the context of your code, here's a working example of your code:
#include <iostream>
class MyClass
{
public:
MyClass() {}
static int doStuff(MyClass*& classArray, size_t sz)
{
int i = 0;
for (; i < sz; i++) {
classArray[i].number = i;
}
// not sure what you want here, but this will return sz+1 if sz>0
return i;
}
void print_number()
{
std::cout << this->number << std::endl;
}
private:
int number;
};
int main(void)
{
MyClass* test = new MyClass[10];
int p = MyClass::doStuff(test, 10);
std::cout << p << '\n';
for (int i = 0; i < 10; i++) {
test[i].print_number();
}
delete[] test;
return 0;
}
Though as others have pointed out, you are using C++, while it's a great exercise in understand how to pass pointers and arrays around, you might find the STL and C++stdlib contain a lot of these types of idioms in an 'easier to understand context'.
Here's your code with some C++ STL:
#include <iostream>
#include <vector>
class MyClass
{
public:
MyClass() {}
MyClass(int i) : number(i) {}
static int doStuff(std::vector<MyClass>& classArray, size_t sz)
{
int i = 0;
for (; i < sz; i++) {
classArray.push_back(MyClass(i));
}
// not sure what you want here, but this will return sz+1 if sz>0
return i;
}
void print_number()
{
std::cout << this->number << std::endl;
}
private:
int number;
};
int main(void)
{
std::vector<MyClass> test;
int p = MyClass::doStuff(test, 10);
std::cout << test.size() << '\n';
// can use iterators here if you want
std::vector<MyClass>::iterator itr = test.begin();
for (; itr != test.end(); itr++) {
itr->print_number();
}
return 0;
}
Hope that can help.
So I'm trying to create a 2 dimensional array of pointers to a object of type Piece. The problem is when i try assign a pointer to a piece to the array i get a segmentation fault. I realized I needed to initialize to array to sometime before I can start allocating but I can't get it right.
Here is the header file of Map which contains a 2-d array of pointers.
#ifndef MAP_H
#define MAP_H
#include <iostream>
#include <vector>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <string>
#include <cstring>
#include "Player.h"
#include "Sprite.h"
#include "Piece.h"
#include "Messages.h"
#include "PieceType.h"
using namespace std;
class Map
{
private:
Piece*** pieces;
int startingX;
int startingY;
int width;
int height;
string mapName;
public:
Map(string);
~Map();
void printMap() const;
Piece* pieceType(char);
void setSprite(Piece*);
void firstMove();
void resetMap(string);
bool moveUp(int, int);
bool moveDown(int, int);
bool moveLeft(int, int);
bool moveRight(int, int);
int getHeight();
int getWidth();
};
#endif
The array I'm talking about is pieces.
I try to allocate this in the constructor of Map.
Map::Map(string name)
{
ifstream map;
string line;
string dimention;
mapName = name;
map.open(name.c_str());
if (map.good())
{
getline (map, line);
int i = 0;
while(line[i] != 'X')
{
dimention[i] = line[i];
i++;
}
stringstream convert(dimention);
convert >> width;
int temp = i;
dimention = "";
i = 1;
while(line[(i + temp)] != '\0')
{
dimention[i] = line[(i + temp)];
i++;
}
stringstream convertTwo(dimention);
convertTwo >> height;
for (int i = 0; i < height; i++)
{
if (!(map.eof()))
{
getline (map, line);
}
else
{
cout << "Error with file" << endl;
break;
}
for (int j = 0; j < width; j++)
{
pieces[i][j] = pieceType(line[j]); //This is where I'm getting the segmentation fault
cout << "assigned" << endl;
if ((pieces[i][j])->getType() == WAYPOINT)
{
if (pieces[i][j]->getWaypointType() == 0)
{
startingX = j;
startingY = i;
}
}
else
{
(pieces[i][j])->setXCordinate(j);
(pieces[i][j])->setYCordinate(i);
}
}
}
}
}
Where name is a string that holds the name of the file that has the information for loading a particular map.
Also the function pieceType is as follows:
Piece* Map::pieceType(char type)
{
Piece* temp;
if (type == '.')
{
return NULL;
}
if (type == 'S')
{
temp = new Waypoint(0);
return temp;
}
if (type == 'E')
{
temp = new Waypoint(1);
return temp;
}
}
Waypoint is a derived class of Piece.
The problem is indeed that you have to initialize that array. Like this:
pieces=new Piece**[height];
for(int i=0;i<height;i++){
pieces[i]=new Piece*[width];
}
Write that just after you get width and height, and before you start using pieces.
But something you should know: for each new, there should be a corresponding delete, or else that memory will never be freed, and you will get a memory leak. To free that memory, add this in your destructor:
for(int i=0;i<height;i++){
for (int j = 0; j < width; j++){
delete pieces[i][j];
}
delete[] pieces[i];
}
delete[] pieces;
This assumes that every pieces[i][j] contains either an object allocated with new or NULL, and it works with both. Looking at your code, that seems to be your case. However, it would not work if one of them is not assigned (not your case).
Use std::vector<std::vector<Pieces>>instead of (trying to, because it does not work) reinventing the wheel. Its safe, easy, and avoids getting manual-memory-management headaches.
#include <iostream>
class MyClass
{
public:
MyClass() {
itsAge = 1;
itsWeight = 5;
}
~MyClass() {}
int GetAge() const { return itsAge; }
int GetWeight() const { return itsWeight; }
void SetAge(int age) { itsAge = age; }
private:
int itsAge;
int itsWeight;
};
int main()
{
MyClass * myObject[50]; // define array of objects...define the type as the object
int i;
MyClass * objectPointer;
for (i = 0; i < 50; i++)
{
objectPointer = new MyClass;
objectPointer->SetAge(2*i + 1);
myObject[i] = objectPointer;
}
for (i = 0; i < 50; i++)
std::cout << "#" << i + 1 << ": " << myObject[i]->GetAge() << std::endl;
for (i = 0; i < 50; i++)
{
delete myObject[i];
myObject[i] = NULL;
}
I am wondering why the objectPointer must be inside the for loop, if I take it out and place it right before the for loop, I get nonsensical results. Help would be appreciated, thanks...sorry for the terrible formatting.
myObject[i] = objectPointer;
It should be inside the loop because you are storing a new reference in the array of the pointers. If it is outside the loop, then all the array of pointers point to the same reference. In such scenario, you should be careful while deallocation as all the array of pointers point to the same memory location.