c++ Trouble assigning pointer to object via a pointer to that object - c++

I'm having trouble assigning a pointer to an object, by assigning it to another pointer that is pointing to that object. Here's my code:
In Map.h:
using namespace std;
class Map;
Map *CurrentMap;
class Map
{
private:
Map *NM, *EM, *SM, *WM;
string NMe, EMe, SMe, WMe;
public:
void Initialize(Map N, Map E, Map S, Map W, string MeN, string MeE, string MeS, string MeW)
{
NM = &N; EM = &E; SM = &S; WM = &W;
NMe = MeN; EMe = MeE; SMe = MeS; WMe = MeW;
}
void GoNorth()
{
cout << NMe << endl;
CurrentMap = NM; //This is the problem, this is where it crashes my program
}
void GoEast()
{
cout << EMe << endl;
CurrentMap = EM;
}
void GoSouth()
{
cout << SMe << endl;
CurrentMap = SM;
}
void GoWest()
{
cout << WMe << endl;
CurrentMap = WM;
}
};
In Main.cpp:
#include <iostream>
#include <string>
#include "Map.h"
using namespace std;
int main()
{
Map A,B,C,D,E,F;
A.Initialize(B,C,D,E,"Towards B","Towards C","Towards D","Towards E");
B.Initialize(D,F,A,F,"Towards D","Towards F","Towards A","Towards F");
C.Initialize(F,E,F,A,"Towards F","Towards E","Towards F","Towards A");
D.Initialize(A,F,B,F,"Towards A","Towards F","Towards B","Towards F");
E.Initialize(F,A,F,C,"Towards F","Towards A","Towards F","Towards C");
F.Initialize(A,A,A,A,"Towards A","Towards A","Towards A","Towards A");
CurrentMap = &A;
CurrentMap->GoNorth();
CurrentMap->GoNorth();
CurrentMap->GoNorth();
system("pause");
return 0;
}
The expected output from the above code is:
Towards B
Towards D
Towards A
But what I get is:
Towards B
//Crash, Unhandled Exception: Access violation reading location 0xcccccccc

You are passing by value and with those values
you are creating temporary copies and taking the address of them,
which of course will be invalid as soon as they go out of scope.
Change the signature of Initialize to take pointers or references.
`void Initialize(Map *N, Map *E, Map *S, Map *W, string MeN, string MeE, string MeS, string MeW);`
And take the addresses when initializing.
`A.Initialize(&B, &C, &D, &E,"Towards B","Towards C","Towards D","Towards E");`

In the code below, you are assigning your pointers to passed-by-value arguments, which means that as soon as Initialize() returns, your class's pointers are now pointing at objects that no longer exist.
void Initialize(Map N, Map E, Map S, Map W, string MeN, string MeE, string MeS, string MeW)
{
NM = &N; EM = &E; SM = &S; WM = &W;
NMe = MeN; EMe = MeE; SMe = MeS; WMe = MeW;
}
If you really want your class to hold pointers to the objects that you declared in main(), you'll need to do pass-by-reference instead:
void Initialize(Map & N, Map & E, Map & S, Map & W, string MeN, string MeE, string MeS, string MeW)
{
NM = &N; EM = &E; SM = &S; WM = &W;
NMe = MeN; EMe = MeE; SMe = MeS; WMe = MeW;
}
... or you could change Initialize() to accept pointer arguments (e.g. Map *) instead. But you might want to reconsider your design, and just hold copies of the objects instead of pointers to objects declared elsewhere. Doing it that way will be less fragile, so you'll be less likely to make a mistake that causes your program to crash.

Related

Passing an Array of Objects into a Function

I have a class that defines object.name as "Ben" and object.favNum as 25.
I also have an array (names) to store 5 objects of this class.
Before I output the attributes of the objects in the array, I change the value of names[0].name to "Jim" and names[0].favNum to 40, using pointer notation.
Here is my code:
#include<iostream>
class Person {
public:
std::string name = "Ben";
int favNum = 25;
};
int main()
{
Person names[5];
Person *ptr = &names[0];
// Changing Values
(ptr + 0)->name = "Jim";
(ptr + 0)->favNum = 40;
for (int i = 0; i < 5; i++)
{
std::cout << (std::string) (ptr + i)->name << std::endl;
std::cout << (int) (ptr + i)->favNum << std::endl << std::endl;
}
system("pause>0");
}
Output:
Jim
40
Ben
25
Ben
25
Ben
25
Ben
25
Where I have the "Changing Values" comment, I want to replace those 2 lines with a function.
The function will be able to change the values as I am doing with the 2 lines.
This is where I am having a problem.
I'm struggling with figuring out what type to declare the function as, how to pass the pointer in, how to receive the pointer, and how to change the values of the objects in the array in the function.
I would recommend against the use of pointers, unless you really need pointers.
// use references instead
void change(Person &person) {
person.name = "Jim";
person.favNum = 40;
};
int main()
{
Person names[5];
change(names[0]);
// ...
}
The appropriate way to write such a function would be using references. A reference is similar to a pointer, but can never be nullptr. In your case you don't need nullability, you just need to edit a Person without copying it.
You probably want change() to be parametric though:
// use references instead
void change(Person &person, std::string name, int favNum) {
person.name = std::move(name);
person.favNum = favNum;
}
But now you are assigning all members of Person using this function, which makes it pointless. It would be simpler if you assigned Person. Why not use a struct and aggregate initialization:
struct Person {
std::string name = "Ben";
int favNum = 25;
};
int main()
{
Person names[5];
names[0] = {"Jim", 40};
// ...
}
On a side note, what you are doing here is unnecessary complicated:
(ptr + 0)->name = "Jim";
// this is equivalent to
ptr[0].name = "Jim";
// this is equivalent to
ptr->name = "Jim";
This is how your code should look in "real" c++ (the setting of the values will be done in the constructor function or using the setNameAndFavNum() function):
#include <array>
#include <iostream>
struct Person {
public:
Person(const std::string& name_ = "Ben", int favNum_ = 25) : name(name_), favNum(favNum_) {};
void setNameAndFavNum(const std::string& name_, int favNum_) {
name = name_;
favNum = favNum_;
};
std::string name;
int favNum;
};
int main() {
std::array<Person, 5> names;
// Changing Values
names[0].setNameAndFavNum("Jim", 40);
// Alternatively you can use the constructor and implicit copy constructor
// names[0] = {"Jim", 40};
for (int i = 0; i < names.size(); i++) {
std::cout << names[i].name << std::endl;
std::cout << names[i].favNum << std::endl << std::endl;
}
}
You shouldn't mess around with pointers and raw values when writing c++ code.

How can I print the variable that a void pointer points to

I would like the function to return different types depending on different parameter values, but how can I print the variable the void pointer points to
in main()?
#include <iostream>
#include <string>
using namespace std;
void * func(int a)
{
if (a == 1)
{
int param = 5;
return &param;
}
else if (a == 2)
{
double param = 5.5;
return &param;
}
else if (a == 3)
{
string param = "hello";
return &param;
}
else
{
return nullptr;
}
}
int main()
{
void *ptr = func(3);//
cout << ptr;// print the address not the value
getchar();
return 0;
}
param is an automatic variable. You cannot return it and use it outside its scope.
param exists only within func, if you return it, the result is Undefined Behaviour.
To fix it you can either:
allocate param on the heap dynamically. After you do that, you can safely return param address but you have to remember to free it when you don't need it.
Here is correction of your code
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
void * func(int a)
{
if (a == 1)
{
int *param = new int(5);
return param;
}
else if (a == 2)
{
double *param = new double(5.5);
return param;
}
else if (a == 3)
{
char *param = new char[50];
strcpy(param, "test");
return param;
}
return nullptr;
}
int main()
{
int *ptr = (int*)func(1);
cout << *ptr << std::endl; // print the int value
delete ptr;
double *ptr2 = (double*)func(2);
cout << *ptr2 << std::endl; // print the double value
delete ptr2;
char *ptr3 = (char*)func(3);
cout << ptr3 << std::endl; // print the string
delete[] ptr3;
getchar();
return 0;
}
If you can use C++17, you can easily solve it by using a std::variant instead of a void *:
#include<iostream>
#include<string>
#include<variant>
std::variant<int, double, std::string, void *> func(int a) {
if (a == 1) {
int param = 5;
return param;
} else if (a == 2) {
double param = 5.5;
return param;
} else if (a == 3) {
std::string param = "hello";
return param;
} else {
return nullptr;
}
}
int main() {
std::visit([](auto v) {
std::cout << v << std::endl;
}, func(3));
}
See it up and running on wandbox.
In C++11/14 you can do the same with a tagged union. The basic idea is that what you return contains enough information so that the caller can get out of it the original type.
Alternatives exist.
As an example, you could erase the type and return a pair that contains both the original (erased) variable and a pointer to function filled with an instantiation of a function template. The latter will be able to reconstruct the original variable from a void * for it knows its type.
Well, pretty much a great machinery you can avoid to use with a tagged union or a std::variant (more or less a type-safe version of a tagged union at the end of the day).
What you're returning is the address of a local variable. That variable goes out of scope when the function returns, meaning that the memory it was using could be reused. Attempting to dereference that pointer (i.e. access the memory it points to) invokes undefined behavior.
Even if you were returning a valid pointer, the fact that your function returns a void * means that any type information regarding what that pointer was pointing to is lost. You could print one or more bytes starting at that address, but it won't tell you what the original type was.
Even if that pointer were valid, you simply can't have enough information to force safely a cast to something and then print it.
No information of its size, no information of its internal layout. So,you simply can not print what's pointed by a void*, unless you have some information prepared by hand somewhere, and force a static_cast to the known type.
For example:
double x = 1.2;
int y = 5;
int f(void** output) {
static int x;
if ( x++ ) {
*output = &x;
return 1;
}
*output = &y;
return 2;
}
...
void* out;
int r = f(&out);
if ( r == 1 ) cout << *(static_cast<double*>(out));
else if ( r == 2 ) cout << *(static_cast<int*>(out));

C++ program crashing (has something to do with with dynamic memory)

I'm having the weird crashing that occurs everytime it goes to the for loop to initialize each position to undefined. Can anyone shine light on why this is happening?
#include
#include
#include
using namespace std;
class MyPhoneBook
{
public:
MyPhoneBook(int, string, string, string, string);
MyPhoneBook();
~MyPhoneBook();
void initialise(int, int, string, string, string, string);
bool search(string&, int);
bool find_free_pos();
void add();
void remove();
void display(int);
friend istream& operator >> (istream& in, MyPhoneBook& ph);
friend ostream& operator << (ostream& out, MyPhoneBook& ph);
private:
int *recordid;
int *status; // -1 is no longer at this number, 0 is blocked, 1 is not blocked, 2 is free
string *name, *areacode, *number, *group;
};
int main(int argc, char** argv)
{
cout << "test 1" << endl;
MyPhoneBook *myphbk; // pointer that will point to an object of a MyPhoneBook class
myphbk = new MyPhoneBook[100]; // now its using dynamic memory
cout << "test 2" << endl; //just for testing
int pos = 0;
for(pos = 0; pos < 100; pos++) // initializing everything to undefined, and position to free (position is the second parameter sended in)
{
myphbk[pos].initialise( (pos+1) , 2 , "Undefined" , "Undefined" , "Undefined" , "Undefined");
}
cout << "test 3" << endl; //just for testing
}
return 0;
void MyPhoneBook::initialise(int recordid_,int status_, string name_, string areacode_, string number_, string group_)
{
//now assign them to private member variables
*recordid = recordid_;
*status = status_;
*name = name_;
*areacode = areacode_;
*number = number_;
*group = group_;
//end of assigning
}
does anyone have any idea why can't my program reach the cout << "test 3" << endl part of the program without crashing?
Since you did not paste the constructor of MyPhoneBook i can only guess, but the problem could be the lines
*recordid = recordid_;
*status = status_;
if you did not assign a valid address to recordid and status in the constructor, e.g. by
recordid = new int;
status = new int;
You might want to declare those member variables as a simple int.

Passing struct between functions C ++

I've searched but haven't been able to get what I want...
I'm doing a little game. And I got this struct that contains the player details.
struct Player
{
string name;
int level;
int exp;
int hp; // life
int mp; // mana
int shield;
};
And when in the menu, the user chooses to start a new game, it goes to this function:
int StartNewPlayer(string name)
{
Player player;
player.name = name;
player.level = 1;
player.exp = 0;
player.hp = 20;
player.mp = 5;
player.shield = 0;
*pass/return the struct here*
}
Then I have a function that prints the game board, and where I should use the data from the new player struct, for example:
void game_board ()
{
cout << "Hello!" << player.name;
(...)
}
Finally, somewhere in main I have:
int main ()
{
StartNewPlayer(new_game());
game_board();
}
that calls all the functions above.
But I can't figure it out... I tried references, pointers without luck.. I need some help here please...
How about this?
Player StartNewPlayer(string name)
{
Player player;
player.name = name;
player.level = 1;
player.exp = 0;
player.hp = 20;
player.mp = 5;
player.shield = 0;
return player;
}
void game_board(Player player)
{
cout << "Hello!" << player.name;
(...)
}
int main ()
{
Player player = StartNewPlayer(new_game());
game_board(player);
}
Do not create extra copies of the data with complex datatypes by using pass-by-value
Use pointers instead to pass the address of the variable that can be modified in the function. The changes will be reflected in the caller's function as well.
void StartNewPlayer(string name, Player *player)
{
player->name = name;
player->level = 1;
player->exp = 0;
player->hp = 20;
player->mp = 5;
player->shield = 0;
}
void game_board(Player* player)
{
cout << "Hello!" << player->name;
(...)
}
int main ()
{
Player player;
StartNewPlayer(new_game(), &player);
game_board(&player);
}
Alternative using pass-by-reference:
If you're a fan of references, (which is just a clever compiler-trick that makes use of pointers internally again):
void StartNewPlayer(string name, Player& player)
{
player.name = name;
player.level = 1;
player.exp = 0;
player.hp = 20;
player.mp = 5;
player.shield = 0;
}
void game_board(Player& player)
{
cout << "Hello!" << player.name;
(...)
}
int main ()
{
Player player;
StartNewPlayer(new_game(), player);
game_board(player);
}
I would suggest returning a pointer to a Player struct. If you return a "reference" like you are doing right now, it will call the copy constructor of Player which can lead to further complications.
Normally, at the end of StartNewPlayer(...), the Player you declared there will cease to exist as the object scope will end, so when you return it, the c++ compiler gets that you want to keep the object alive and will create a copy for you, invisibly. If you return a pointer to it, you really are returning the object you allocated in your function.
Suppose that you have pointers in your Player structure, such as
struct Player
{
int level;
char* name; //lets assume you did it like that
}
When you are returning the Player, the int will be copied, but the char* will not. ints are easy to handle while char* need all kind of tricky functions like strlen and strncpy. The more complex your Player struct becomes, the more problem you will face by using the default copy constructor.
Another solution would be to declare a copy constructor yourself for the Player struct ( really, you could use classes since they are mostly interchangeable in c++ ).
Player(const Player& p)
{
name = p.name;
level = p.level;
// and so forth
}
So I would use
Player* StartNewPlayer(std::string name)
{
Player* player = new Player();
player->name = name;
player->level = 1;
// snip
return player;
}
At the end of your program, be sure to delete player otherwise you will have a memory leak

Unhandled exception while reading structures

The program throws an unhandled exception on this line:
}else if(s == "backpack"){
cout << "\nEquipped items: " << endl;
cout << weapon->Name << endl << cArmour->Name << endl; //this line
It prints 'Equipped items: ' then throws an exception. This file - Player.h - includes Library.h, which in turn includes Globals.h, which has the structs:
struct sWeapon{
std::string Name;
int Damage;
};
struct sArmour{
std::string Name;
int AP;
};
In the Player constructor, it creates the struct objects:
Player::Player(std::map<std::string,sWeapon*> wepArray,std::map<std::string,sArmour*> armArray){
weapons = wepArray;
armour = armArray;
weapon = wepArray["None"];
cArmour = armArray["None"];
}
At the beginning of the entire program, it calls init_weapons and init_armour:
int main(){
using namespace std;
//initialise the game
std::map<std::string,sWeapon*> wepArray = init_weapons(); //get weapon array
std::map<std::string,sArmour*>armArray = init_armour(); //get armour array
which return the map of all the weapons:
//init_weapons()
//sets up weapons map
std::map<std::string,sWeapon*> init_weapons(void){
std::map< std::string, sWeapon* > weapons; //map of weapons
//starting 'none'
sWeapon* none = new sWeapon();
none->Name = "None";
none->Damage = 0;
//create weapons
sWeapon* w1 = new sWeapon();
w1->Name = "Rusty dagger";
w1->Damage = 3;
//put in map
weapons[w1->Name] = w1;
return weapons;
}
std::map<std::string,sArmour*> init_armour(void){
std::map< std::string, sArmour* > armour; //map of armour
//starting 'none'
sArmour* none = new sArmour();
none->Name = "None";
none->AP = 0;
//create armour
sArmour* a1 = new sArmour();
a1->Name = "Leather";
a1->AP = 10;
//put in map
armour[a1->Name] = a1;
return armour;
}
then passes those maps as arguments to the player constructor shown above.
I'm guessing either weapon or cArmour is null or point nowhere.
That's all more likely since you're not storing your "None" weapon and armor in your global hash.
Try printing out the pointer for those two "None" objects, then the pointer values for the object members weapon or cArmour.