Unhandled exception while reading structures - c++

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.

Related

Std::bad_alloc thrown in the middle of While Loop

I'm writing a function that handles an order input file (csv) using a while loops to iterate though it.
762212,1,2020-03-15,10951-3,64612-2,57544-1,80145-1,27515-2,16736-1,79758-2,29286-2,51822-3,39096-1,32641-3,63725-3,64007-2,23022-1,16974-3,26860-2,75536-2,26461-1
1,373975319551257,12-2023
258572,2,2020-03-15,96497-1,70616-1,80237-2,22248-2,56107-1,59695-1,37948-3,21316-3,63498-1,18329-1,56833-1,66295-1,47680-3,30346-1
1,201741963232463,02-2022
857003,3,2020-03-15,16655-1,88019-3,75069-3,96017-2,46883-2,15138-1,77316-1,70063-3,54452-3,86429-2,15134-2,60176-1,12946-3
2,cfeeham3s
747893,4,2020-03-17,48520-1,93268-2,63636-1,23750-2,99771-3,83203-1,21316-3,89921-2,15134-3,82831-1,30346-2,54044-3,28561-1,14792-2,23523-3,56826-2
1,3571379825697064,04-2025
Every two lines represents an input. I have the following function that handles this input:
list<Order> orders;
void read_orders(string file_name) {
fstream read_file;
read_file.open(file_name, ios::in);
if (read_file.is_open()) {
string s;
int line_num = 1; // keeps track of line number in input file
int o_id;
string o_date;
int c_id;
vector<LineItem> itms;
while (getline(read_file, s)) {
cout << orders.size(); // shows that only two objects are added before failure
if (line_num % 2 == 1) { // handle odd numbered lines of input
auto data = split(s, ',');
int o_id = stoi(data[0]);
string o_date = data[1];
int c_id = stoi(data[2]);
vector<LineItem> itms;
// get line items
int n_line_items = data.size() - 3;
vector<string> end_data(data.end() - n_line_items, data.end());
for (string x: end_data) {
auto parts = split(x, '-');
LineItem* it = new LineItem(stoi(parts[0]), stoi(parts[1]));
itms.push_back(*it);
delete it;
}
} else { // handle even numbered lines of input
auto data = split(s, ',');
Credit* pay_credit = new Credit(0.0, data[1], data[2]); // initialize each type of payment
PayPal* pay_paypal = new PayPal(0.0, data[1]);
WireTransfer* pay_wire = new WireTransfer(0.0, data[1], data[2]);
if (data[0] == "1") {
Order* ordr = new Order(o_id, o_date, c_id, itms, *pay_credit);
orders.push_back(*ordr);
delete ordr;
} else if (data[0] == "2") {
Order* orr = new Order(o_id, o_date, c_id, itms, *pay_paypal);
orders.push_back(*orr);
delete orr;
} else if (data[0] == "3") {
Order* odr = new Order(o_id, o_date, c_id, itms, *pay_wire);
orders.push_back(*odr);
delete odr;
}
delete pay_credit; // trying to clean up memory
delete pay_paypal;
delete pay_wire;
}
line_num += 1;
}
read_file.close();
}
}
Because of my cout statement, I can tell that it only adds two items to the list before running into the std::bad_alloc error. It seems to happen when it switches from adding a Credit object to adding a PayPal object into the Order(...) when it's initialized. I did a lot of research into why this might happen, so I tried to clean up as much as I knew how to (I'm new to C++) but the same error kept popping up. Does the error happen when I'm adding things to the list or is it when I'm creating these new objects?/How could I fix something like that?
Here are my class definitions in case that's important:
class Payment {
public:
double amount;
string print_detail() {
return "hey";
};
};
class Credit: public Payment {
private:
string card_number;
string expiration;
public:
Credit(double amt, string cn, string exp) {
this->amount = amt;
this->card_number = cn;
this->expiration = exp;
}
string print_detail() {
return "Credit card " + this->card_number + ", exp. " + this->expiration;
}
};
class PayPal: public Payment {
private:
string paypal_id;
public:
PayPal(double amt, string pp_id) {
this->amount = amt;
this->paypal_id = pp_id;
}
virtual string print_detail() {
return "Paypal ID: " + this->paypal_id;
}
};
class WireTransfer: public Payment {
private:
string bank_id;
string account_id;
public:
WireTransfer(double amt, string b_id, string a_id) {
this->amount = amt;
this->bank_id = b_id;
this->account_id = a_id;
}
string print_detail() {
return "Wire transfer from Bank ID " + this->bank_id + ", Account# " + this->account_id;
}
};
class LineItem {
private:
int item_id;
int qty;
public:
LineItem(int i_id, int qt) {
this->item_id = i_id;
this->qty = qt;
}
double subtotal() {
double subtot = 0.0;
for (auto x: items) {
if (x.item_id == this->item_id) {
subtot += x.price * this->qty;
}
}
return subtot;
};
};
class Order {
private:
int order_id;
string order_date;
int cust_id;
vector<LineItem> line_items;
Payment payment;
public:
Order(int o_id, string o_date, int c_id, vector<LineItem> li, Payment pay) {
this->order_id = o_id;
this->order_date = o_date;
this->cust_id = c_id;
this->line_items = li;
this->payment = pay;
}
string pay_type = "";
double total() {
double result = 0.0;
for (auto li: line_items) {
result += li.subtotal();
}
return result;
}
string print_order() {
string text = "===========================\nOrder #";
text += to_string(this->order_id) + ", Date: " + this->order_date + "\nAmount: $";
text += to_string(this->total()) + ", Paid by ";
text += payment.print_detail();
return text;
}
};
And this was the error message showing that it did insert two items:
001122terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Process returned 3 (0x3)
std::bad_alloc is often thrown when there is not enough memory to be allocated. I can't say if this will solve the problem, but your repeated allocations and deallocations of objects are both unnecessary and harmful (causing memory fragmentation).
Instead of
LineItem* it = new LineItem(stoi(parts[0]), stoi(parts[1]));
itms.push_back(*it);
delete it;
you should do
itms.push_back(LineItem(stoi(parts[0]), stoi(parts[1]));
or
itms.emplace_back(stoi(parts[0]), stoi(parts[1]));
The same applies to every occurence of new in read_orders. You don't need any of them.
Another helpful thing you can do is to preallocate memory for std::vector. If you don't know how many items it will have, do an educated guess (100, 1000, 10000, etc.).
itms.reserve(1000); //before you start to push_back() to it
Also, make sure to std::move your vectors if you want to transfer the whole content of it and not make a copy.

Losing a data member of a base class after the constructor is called

I have been working on a project and had no problems until today where I lost a class data member after the constructor is called. I could not pinpoint where the change happens. I have several classes for cars. The classes related to the cars are in the code block below. After all the cars are created in the class RegistrationSystem they are stored in an array. however, while calling a display function in RegistrationSystem the first car loses the color value. In the class RegistrationSystem the first Pickup in the class stores the value until the constructor is complete. After the constructor ends, the color value string shows " " in the debugger.
class Car {
protected:
string color;
public:
Car(string c) { color = c; };
string getColor(void) { return color; }
friend ostream& operator<<(ostream& outStream, const Car& car) {
cout << car.color;
return outStream;
}
};
class Pickup : public Car {
public:
Seat *frontSeat = new Seat(FRONT_SEAT_CREDIT);
Pickup(string c) : Car(c) {}
};
class Compact : public Car {
public:
Seat *frontSeat = new Seat(FRONT_SEAT_CREDIT);
Seat *sideBackLeftSeat = new Seat(BACK_SEAT_COMPACT_CREDIT);
Seat *sideBackRightSeat = new Seat(BACK_SEAT_COMPACT_CREDIT);
Compact(string c) : Car(c) {}
};
class Sedan : public Car {
public:
Seat *frontSeat = new Seat(FRONT_SEAT_CREDIT);
Seat *sideBackLeftSeat = new Seat(SIDE_BACK_SEDAN_CREDIT);
Seat *sideBackRightSeat = new Seat(SIDE_BACK_SEDAN_CREDIT);
Seat *middleBackSeat = new Seat(MID_BACK_SEDAN_CREDIT);
Sedan(string c) : Car(c) {}
};
class RegistrationSystem {
private:
string file_name;
int menu_response;
Reservation *reservations[24] = { NULL };
Passenger *rowers[24];
Pickup *pickup_cars[3];
Compact *compact_cars[3];
Sedan *sedan_cars[3];
// Displays the Layouts
void displaySeatArrangements(void);
// Saves the information in the file
void saveToFile(void);
// Find the rower in array rowers
Passenger* findRower(string);
// Displays the menu for the seat choice of a car type
bool displayCarSeatingChoiceMenu(string);
// Make a reservation in the system
bool makeReservation(string, string, int, Passenger&);
// Delete a reservation
bool deleteReservation(int);
// Print Reservations
void saveReservationsToFile(void);
// Sub functions for makeReservation()
bool makePickupReservation(Pickup*, Passenger, int&, string, string);
bool makeCompactReservation(Compact*, Passenger, int&, string, string);
bool makeSedanReservation(Sedan*, Passenger, int&, string, string);
public:
RegistrationSystem(void);
void chooseOperation(void);
Passenger* getPassengers(void) { return *rowers; }
friend ostream& operator<<(ostream&, const RegistrationSystem&);
friend istream& operator>>(istream&, RegistrationSystem&);
};
The display function has a line:
<< setw(8) << *(pickup_cars[index]) << setw(8) << *(compact_cars[index]) << setw(11) << *(sedan_cars[index]) << endl
where the *(pickup_cars[index]) is set to " " and the seat value gives error = read memory from 0x6 failed (0 of 4 bytes read). That is also set to NULL.
Here is the code of the RegistrationSystem constructor:
RegistrationSystem::RegistrationSystem(void) {
file_name = "seat_credits.txt";
menu_response = 0;
ifstream inFile(file_name);
if(!inFile.is_open()) {
cout << "Error opening file. Terminating...";
exit(1);
}
// Read file to set passengers and their credits in rowers array
int count = 0;
while(!inFile.eof() && count < 24) {
string first, last;
int credits;
inFile >> first >> last >> credits;
string fullName = first + ' ' + last;
rowers[count] = new Passenger(fullName, credits);
count++;
}
// Assign all the cars to the arrays
pickup_cars[0] = new Pickup("PURPLE");
pickup_cars[1] = new Pickup("YELLOW");
pickup_cars[2] = new Pickup("RED");
compact_cars[0] = new Compact("GREEN");
compact_cars[1] = new Compact("BLUE");
compact_cars[2] = new Compact("YELLOW");
sedan_cars[0] = new Sedan("RED");
sedan_cars[1] = new Sedan("GREEN");
sedan_cars[2] = new Sedan("BLUE");
inFile.close();
}
The problem occurred when the input file stream was still open and I was creating new instances and assigning their addresses to pointers before I closed the file. After I switched the order and closed the file, then assigned pointers the addresses of the new objects the problem went away.
These operations were happening inside of the constructor of the RegistrationSystem class. Here is the new code:
RegistrationSystem::RegistrationSystem(void) {
file_name = "seat_credits.txt";
menu_response = 0;
ifstream inFile(file_name);
if(!inFile.is_open()) {
cout << "Error opening file. Terminating...";
exit(1);
}
// Read file to set passengers and their credits in rowers array
int count = 0;
while(!inFile.eof() && count < 24) {
string first, last;
int credits;
inFile >> first >> last >> credits;
string fullName = first + ' ' + last;
rowers[count] = new Passenger(fullName, credits);
count++;
}
inFile.close();
// Assign all the cars to the arrays
pickup_cars[0] = new Pickup("PURPLE");
pickup_cars[1] = new Pickup("YELLOW");
pickup_cars[2] = new Pickup("RED");
compact_cars[0] = new Compact("GREEN");
compact_cars[1] = new Compact("BLUE");
compact_cars[2] = new Compact("YELLOW");
sedan_cars[0] = new Sedan("RED");
sedan_cars[1] = new Sedan("GREEN");
sedan_cars[2] = new Sedan("BLUE");
}
The line inFile.close() was placed after all the array assignments. Moving it above them solved the problem of losing the first data member of my Pickup object.

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

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.

access violation reading location c++

I'm writing a program that print the full english name of the number inputted by the user. it's not a complete program but i keep getting an error:
First-chance exception at 0x00b02c76 in Programming Challenge 14.1.exe: 0xC0000005: Access violation reading location 0xcccccd80.
Unhandled exception at 0x00b02c76 in Programming Challenge 14.1.exe: 0xC0000005: Access violation reading location 0xcccccd80.
I've tried looking around and couldn't find anything of use to me. here this the program:
header file:
#ifndef NUMBERS_H
#define NUMBERS_H
#include <string>
using namespace std;
const int SIZE1 = 18;
const int SIZE2 = 8;
class Numbers
{
private:
int number;
string hundred;
string thousand;
string * one;
string * ten;
public:
Numbers(int num)
{
number = num;
hundred = "hundred";
thousand = "thousand";
string * one = new string[SIZE1];
string * ten = new string[SIZE2];
}
void initializeArray()
{
// Intialize array "one"
one[0] = "zero";
one[1] = "one";
one[2] = "two";
one[3] = "three";
one[4] = "four";
one[5] = "five";
one[6] = "six";
one[7] = "seven";
one[8] = "eight";
one[9] = "nine";
one[10] = "eleven";
one[11] = "twelve";
one[12] = "thirteen";
one[13] = "fourteen";
one[14] = "fifteen";
one[15] = "sixteen";
one[16] = "seventeen";
one[17] = "eighteen";
one[18] = "nineteen";
// Initialize the ten array
ten[0] = "ten";
ten[1] = "twenty";
ten[2] = "thirty";
ten[3] = "forty";
ten[4] = "fifty";
ten[5] = "sixty";
ten[6] = "seventy";
ten[7] = "eighty";
ten[8] = "ninety";
}
string determine()
{
string name = "";
for (int i = 0; i <= number; i++)
{
if (number == i)
{
name = one[i];
}
}
return name;
}
~Numbers()
{
delete [] one;
delete [] ten;
}
};
#endif
and this is the main program, im just using a constructor to assign a value to number to make debugging a little faster
#include <iostream>
#include "Numbers.h"
using namespace std;
int main()
{
Numbers n(5);
string name = n.determine();
cout << "The number is " << name << endl;
cin.ignore();
cin.get();
return 0;
}
by the way this is vc++ for the compiler
ill answer any questions as this isnt really too organized
const int SIZE1 = 18;
Valid array index for the array of SIZE1 are 0 to 17. In general, valid indexes for an array of size N are 0 to N-1.
I recommend using std::vector<std::string>.
one holds 18 elements, but you put 19 elements in there.
Two things here:
You are not calling "initializeArray()" at all. So when you are trying to access the array there is nothing there. I would recommend calling it in the constructor. Like this:
Numbers(int num)
{
number = num;
hundred = "hundred";
thousand = "thousand";
one = new string[SIZE1];
ten = new string[SIZE2];
initializeArray();
}
Second, is what the guys above said. You have an incorrect value for the size of your array since you are trying to assign 19 values to an array of size 18. Just to be really sure lets make the size bigger than we expect and you can adjust later:
const int SIZE1 = 20;
const int SIZE2 = 20;
Additionally, See your determine()? instead of using a for loop why don't you go:
string name = one[number];
EDIT: Wow there was another thing I missed...you have declared your array pointer variable twice and so it's actually going out of scope thinking you want to make some local versions. Look at my adjusted implementation of your constructor above again. See how I've removed the "String *" from before the variable names.
The variable "one" and "ten" have been changed from string pointers to vectors holding strings. Called the initializeArray within the constructor. Changed the way the name string was being assigned the new string. Here is the working code.
class Numbers
{
private:
int number;
string hundred;
string thousand;
vector<string> one;
vector<string> ten;
public:
Numbers(int num)
{
number = num;
hundred = "hundred";
thousand = "thousand";
initializeArray();
}
void initializeArray()
{
one.push_back("zero");
one.push_back("one");
one.push_back( "two");
one.push_back("three");
one.push_back("four");
one.push_back("five");
one.push_back("six");
one.push_back("seven");
one.push_back("eight");
one.push_back("nine");
one.push_back("eleven");
one.push_back("twelve");
one.push_back("thirteen");
one.push_back("fourteen");
one.push_back("fifteen");
one.push_back("sixteen");
one.push_back("seventeen");
one.push_back("eighteen");
one.push_back("nineteen");
// Initialize the ten array
ten.push_back("ten");
ten.push_back("twenty");
ten.push_back("thirty");
ten.push_back("forty");
ten.push_back("fifty");
ten.push_back("sixty");
ten.push_back("seventy");
ten.push_back("eighty");
ten.push_back("ninety");
}
string determine()
{
string name("");
for (int i = 0; i <= number; i++)
{
if (number == i)
{
auto iter = one.begin();
iter += i;
name.assign(*iter);
}
}
return name;
}
~Numbers()
{
}
};
int main()
{
Numbers n(5);
string name = n.determine();
cout << "The number is " << name << endl;
cin.ignore();
cin.get();
return 0;
}

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