How to pass const pointer values in classes in C++ - c++

I'm new to the world of C++ (and OOP).
I'm learning about classes and pointers at this moment, but I'm stuck and hope someone can explain to me what I'm missing or should dig deeper into to broaden my understanding.
Example 1 works:
#include <iostream>
#include <string.h>
using namespace std;
class MyClass
{
private:
char* age;
public:
MyClass(const char* initData)
{
age = NULL;
cout << "In default constructor working on pointers" << endl;
age = new char [strlen(initData)+1];
strcpy(age,initData);
//age = initData;
}
~MyClass()
{
cout << "In destructor working on pointers" << endl;
delete [] age;
}
const char* GetAge()
{
return age;
}
};
int main()
{
//MyClass firstClass(10);
//cout << "First attempt: " ;
//cout << firstClass.GetAge() << endl;
MyClass secondClass("A test from B");
cout << "Second attempt: ";
cout << secondClass.GetAge() << endl;
return 0;
}
However This does not work:
#include <iostream>
#include <string.h>
using namespace std;
class MyClass
{
private:
int* age;
public:
MyClass(const int* initData)
{
cout << "In default constructor working on pointers" << endl;
age = new int;
//strcpy(age,initData);
age = initData;
}
~MyClass()
{
cout << "In destructor working on pointers" << endl;
delete age;
}
const int* GetAge()
{
return age;
}
};
int main()
{
MyClass firstClass(10);
cout << "First attempt: " ;
cout << firstClass.GetAge() << endl;
//MyClass secondClass("B");
//cout << "Second attempt: ";
//cout << secondClass.GetAge() << endl;
return 0;
}
I feel that it has to do with the fact that I pass an int to a constant pointer.
And then try to assign a constant from r-value to l-value with the = operator.
Although it think this is permitted, since I say 'const int* initData' and this tells the compiler to keep the data from changing but memory address can change?
So in my understanding, I pass value 10 to the class that makes a pointer in the default constructor, this makes a memory address and stores it in initData.
I then pass the r-value InitData (mem address) to the l-value age pointer, that accepts memory addresses.
If I try with the exact same code, but use char and copy data over in my first example it works...
Can anyone explain to me what I'm missing, Thanks in advance!
Edit:
I Think I found my solution and understand it better.
Could anyone verify that this is correct, or which is the (more) correct form:
Scenario 1:
#include <iostream>
using namespace std;
class MyClass
{
private:
int* age;
public:
MyClass(const int *initData)
{
cout << "In default constructor working on pointers" << endl;
age = new int;
(*age) = (*initData);
}
~MyClass()
{
cout << "In destructor working on pointers" << endl;
delete age;
}
const int* GetAge()
{
return age;
}
};
int main()
{
int aNum = 10;
MyClass firstClass(&aNum);
cout << "First attempt: " ;
cout << *firstClass.GetAge() << endl;
return 0;
}
Or Scenario 2:
#include <iostream>
using namespace std;
class MyClass
{
private:
int* age;
public:
MyClass(const int &initData)
{
cout << "In default constructor working on pointers" << endl;
age = new int;
(*age) = (initData);
}
~MyClass()
{
cout << "In destructor working on pointers" << endl;
delete age;
}
const int* GetAge()
{
return age;
}
};
int main()
{
MyClass firstClass(10);
cout << "First attempt: " ;
cout << *firstClass.GetAge() << endl;
return 0;
}
I Would think solution 2, as that uses reference to memory and thus speeds up the execution?
Thanks for the assistance already, and sorry for the long post...

First: you can not set a const pointer to a non-const pointer, you can circumvent this using a const_cast<int*>(initData) which gets rid of the const-ness of initData when assigning to age.
But i do not think this is what you want to achieve.
So first of all a pointer is just pointing to memory - that memory must therefore be managed by someone else than the pointer. Usually you only need a pointer if you want to reference something or iterate - if you intend to be the owner of that memory you might not want to use a pointer.
Secondly: if you start learning C++ now, try to learnt 'modern' C++ and utilize smart_pointers (see smart pointers form cppreference).
A rule of thumb: if you do not necessarily need a pointer (no need for iteration, direct memory access) use by reference instead.
But bottom line: your example looks like it is not meant to be used with pointers at all. Just store the int value.
class MyClass
{
private:
int age;
public:
// pass by const reference, this is cheap and good practice
MyClass(const int& initData)
{
cout << "In default constructor working on pointers" << endl;
// here the value of initData is actually copied into age
age = initData;
}
And if you really want to try pointers: start with the std::shared_ptr which is a ref-counting pointer easy to use.
Example:
#include <memory>
#include <iostream>
class test
{
private:
std::shared_ptr<int> age;
public:
// cheap and quick const ref
test(const std::shared_ptr<int>& data)
{
age = data;
}
void print()
{
std::cout << *age << std::endl;
std::cout << "Use count: " << age.use_count() << std::endl;
}
};
int main()
{
// here we store the data
int i = 17;
// here we have the shared_ptr
std::shared_ptr<int> p = std::make_shared<int>(i);
// here we pass it to the object
test t(p);
t.print();
return 0;
}

Related

why don't we deallocate memory after allocating memory for object in heap in C++?

#include<iostream>
using namespace std;
class car
{
string name;
int num;
public:
car(string a, int n)
{
cout << "Constructor called" << endl;
this->name = a;
this->num = n;
}
void enter()
{
cin >> name;
cin >> num;
}
void display()
{
cout << "Name: " << name << endl;
cout << "Num: " << num << endl;
}
};
int main()
{
// Using new keyword
car *p = new car("Honda", 2017);
p->display();
}
why don't we deallocate space for 'car *p'? If we don't deallocate memory space on the heap, won't there be a memory leak?
I am a newbie trying to learn c++. I had read that I always had to deallocate space after allocating on heap... I found this code online
Most operating systems will free all memory associated with a program when it ends, so in this case, delete p; can be extraneous.
This gets a bit more uncertain the lower level you go, especially in embedded systems. Best to get in the practice of using delete everytime you use new.
Or don't use new/delete at all when possible.
In your case it is certainly not necessary to use dynamic memory allocation. You could simply write:
int main() {
car p("Honda", 2017);
p.display();
}
If you insisted on using dynamic memory allocation, you might use a smart pointer which will take care of the deallocation for you.
#include <memory>
// car class stuff
int main() {
std::unique_ptr<car> p = std::make_unique<car>("Honda", 2017);
p->display();
}
An aside on your car class: accustom yourself to using member initializer lists in your constructors.
car(string a, int n)
{
cout << "Constructor called" << endl;
this->name = a;
this->num = n;
}
Becomes:
car(string a, int n) : name(a), num(n)
{
cout << "Constructor called" << endl;
}

Passing array of strings to a function

I am trying to create a program that uses class, arrays, and functions to show information about two students(Name, id#, classes registered). The part I am struggling with is passing arrays to a function. How do I do that?
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
class Student // Student class declaration.
{
private:
string name;
int id;
string classes;
int arraySize;
public:
void setName(string n)
{
name = n;
}
void setId(int i)
{
id = i;
}
void setClasses(string c, int num)
{
classes = c;
arraySize = num;
}
string getName()
{
return name;
}
int getId()
{
return id;
}
void getClasses()
{
for (int counter=0; counter <arraySize; counter++) {
cout << classes[counter] << endl;
}
}
};
int main()
{
//Student 1
string s1Name = "John Doe";
int s1Id = 51090210;
int const NUMCLASSES1 = 3;
string s1Classes[NUMCLASSES1] = {"C++","Intro to Theatre","Stagecraft"};
//Student 2
string s2Name = "Rick Harambe Sanchez";
int s2Id = 666123420;
int const NUMCLASSES2 = 2;
string s2Classes[NUMCLASSES2] = {"Intro to Rocket Science","Intermediate Acting"};
//
Student info;
info.setName(s1Name);
info.setId(s1Id);
//info.setClasses(s1Classes, NUMCLASSES1);
cout << "Here is Student #1's information:\n";
cout << "Name: " << info.getName() << endl;
cout << "ID: " << info.getId() << endl;
//cout << "Classes: " << info.getClasses() << endl;
info.setName(s2Name);
info.setId(s2Id);
// info.setClasses(s2Classes, NUMCLASSES1);
cout << "\n\nHere is student #2's information:\n";
cout << "Name: " << info.getName() << endl;
cout << "ID: " << info.getId() << endl;
//cout << "Classes: " << info.getClasses() << endl;
return 0;
}
The usual way to pass around variable-length lists in C++ is to use an std::vector. A vector is a single object that you can easily pass to a function, copying (or referencing) its contents. If you are familiar with Java, it's basically an ArrayList. Here is an example:
#include <vector>
#include <string>
using namespace std;
class foo {
private:
vector<string> myStrings;
public:
void setMyStrings(vector<string> vec) {
myStrings = vec;
}
}
//...
foo myObj;
vector<string> list = {"foo","bar","baz"};
myObj.setMyStrings(list);
If don't want to use the standard library though, you can pass an array C-style. This involves passing a pointer to the first element of the array, and the length of the array. Example:
void processStrings(string* arr, int len) {
for (int i = 0; i < len; i++) {
string str = arr[i];
//...
}
}
string array[] = {"foo","bar","baz"};
processStrings(array, 3); // you could also replace 3 with sizeof(array)
Passing raw arrays like this, especially if you wanted to then copy the array into an object, can be painful. Raw arrays in C & C++ are just pointers to the first element of the list. Unlike in languages like Java and JavaScript, they don't keep track of their length, and you can't just assign one array to another. An std::vector encapsulates the concept of a "list of things" and is generally more intuitive to use for that purpose.
Life lesson: use std::vector.
EDIT: See #nathanesau's answer for an example of using constructors to initialize objects more cleanly. (But don't copy-paste, write it up yourself! You'll learn a lot faster that way.)
You can pass array of any_data_type to function like this
void foo(data_type arr[]);
foo(arr); // If you just want to use the value of array
foo(&arr); // If you want to alter the value of array.
Use std::vector. Also, don't add functions you don't need. Here's an example of using std::vector
#include <string>
#include <iostream>
#include <vector>
using std::string;
using std::vector;
class Student // Student class declaration.
{
private:
vector<string> classes;
string name;
int id;
public:
Student (const vector<string> &classesUse, string nameUse, int idUse) :
classes (classesUse),
name (nameUse),
id (idUse)
{
}
void print ()
{
std::cout << "Name: " << name << std::endl;
std::cout << "Id: " << id << std::endl;
std::cout << "Classes: ";
for (int i = 0; i < classes.size (); i++)
{
if (i < classes.size () - 1)
{
std::cout << classes[i] << ", ";
}
else
{
std::cout << classes[i] << std::endl;
}
}
std::cout << std::endl;
}
};
int main()
{
Student John ({"C++","Intro to Theatre","Stagecraft"},
"John",
51090210);
John.print ();
Student Rick ({"Intro to Rocket Science","Intermediate Acting"},
"Rick",
666123420);
Rick.print ();
return 0;
}
Name: John
Id: 51090210
Classes: C++, Intro to Theatre, Stagecraft
Name: Rick
Id: 666123420
Classes: Intro to Rocket Science, Intermediate Acting
In the private variables of class Student, you are storing a string:
String classes;
where as you should be storing an array of strings like:
String classes[MAX_NUM_CLASSES];
then in the set classes function, pass in an array of strings as the first argument, so it should be :
void setClasses(string[] c, int num)
{
classes = c; //not sure if simply setting them equal will work, rather copy entire array using a for loop
arraySize = num;
}
This should point you in the right direction
Also, use std::vector instead of string[], it will be easier.

Concept of data storing in c++

I have a Spieler class and a Verein class with a vector of Spieler members.
Now if I change something of the Players like the Staerke(german for strength) by using a function of this class in the player class it does not automatically change the value for this player.
Here is the code:
#include <vector>
#include<iostream>
#include <string>
using namespace std;
class Spieler
{
public:
void setinformation(int a, string b, string c, int d)
{
ID = a;
Vorname = b;
Nachname = c;
Staerke = d;
}
void getinformation()
{
cout << "ID: " << ID << endl;
cout << "Vorname: " << Vorname << endl;
cout << "Nachname: " << Nachname << endl;
cout << "Staerke: " << Staerke << endl << endl;
}
void setStaerke(int x)
{
Staerke = x;
}
int getStaerke()
{
return Staerke;
}
private:
string Vorname, Nachname;
int Staerke, ID;
};
class Verein
{
public:
void setSpielerListe(vector<Spieler> x)
{
Spielerliste = x;
}
vector<Spieler> getSpielerListe()
{
return Spielerliste;
}
string getVereinsName()
{
return VereinsName;
}
int getVereinsID() const
{
return VereinsID;
}
void setVereinsID(int x)
{
VereinsID = x;
}
int getGesamtstaerke()
{
Gesamtstaerke = 0;
vector<Spieler> b;
b = getSpielerListe();
for (size_t i = 0; i < b.size(); i++)
{
Gesamtstaerke = Gesamtstaerke + b[i].getStaerke();
}
return Gesamtstaerke;
}
void Vereinsinformationen()
{
vector<Spieler> list;
int id;
string vereinsname;
int gesamtstaerke;
id = getVereinsID();
vereinsname = getVereinsName();
gesamtstaerke = getGesamtstaerke();
list = getSpielerListe();
cout << "VereinsID: " << id << endl;
cout << "Vereinsname: " << vereinsname << endl;
cout << "Gesamstaerke: " << gesamtstaerke << endl << endl;
cout << "Spieler: " << endl;
for (size_t i = 0; i < list.size(); i++)
list[i].getinformation();
}
private:
vector<Spieler> Spielerliste;
int VereinsID, Gesamtstaerke;
string VereinsName;
};
vector<Spieler> spieler;
int main()
{
Spieler Spieler1;
Spieler1.setinformation(0, "Peter", "Pan", 10);
spieler.emplace_back(Spieler1);
Verein Team1;
Team1.setSpielerListe(spieler);
Spieler1.setStaerke(20);
Team1.Vereinsinformationen();
cin.get();
return 0;
}
I'm really new into c++ and programming so the code might be terrible.
Guess it has to do with pointers, I'm really not into the concept of storing data in c++, try to get it by trial & error; So how to change the Staerke in a way that it is changed in the Teams Playerlist too?
The problem is you are storing full object in the vector and not pointers. When you run this line:
spieler.emplace_back(Spieler1);
a copy of Spieler1 is made and put in the vector. So modifying it in the main will have no effect in the vector. Also not that you are copying the vector when setting in Verein class.
You should use pointer if this is what you are after or better yet have a function to modify strength from Verein class taking its id and new strength as parameters might be a good idea. Something like this:
void setStaerke(int id, int x)
{
vector<Spieler>::iterator it = Spielerliste.begin();
while (it != Spielerliste.end())
{
if ((*it).GetId() == id)
{
(*it).setStaerke(x);
break;
}
}
}
If you have access to C++11, it could be made more elegantly.
Hereby you pass and store a copy from the vector into the object:
Team1.setSpielerListe(spieler);
Therefore changes to the original vector and the contained objects will not affect the member.
Further, I don't have much experience with emplace_back, but the more usual way to append an object to a std::vector would also append a copy:
spieler.push_back(Spieler1);
Therefore changes to the original object would not affect the object you've appended to the container.
Make sure you better understand when objects are copied.
For reference:
http://en.cppreference.com/w/cpp/container/vector/emplace_back
http://en.cppreference.com/w/cpp/container/vector/push_back
How to pass objects to functions in C++?

Returning References to Objects

I would like some help in returning references to objects created in the heap.
I am reading a book titled Sam's Teach Yourself C++ and in chapter 12, the author introduces returning references to objects on the heap. The example illustrates a memory leak, and the author says that one of the solutions is to declare the object in the calling function and then to pass it to TheFunction() by reference.
This is the example:
// Listing 12.5
// Resolving memory leaks
#include <iostream>
class SimpleCat
{
public:
SimpleCat (int age, int weight);
~SimpleCat() {}
int GetAge() { return itsAge; }
int GetWeight() { return itsWeight; }
private:
int itsAge;
int itsWeight;
};
SimpleCat::SimpleCat(int age, int weight):
itsAge(age), itsWeight(weight) {}
SimpleCat & TheFunction();
int main()
{
SimpleCat & rCat = TheFunction();
int age = rCat.GetAge();
std::cout << "rCat is " << age << " years old!\n";
std::cout << "&rCat: " << &rCat << std::endl;
// How do you get rid of that memory?
SimpleCat * pCat = &rCat;
delete pCat;
// Uh oh, rCat now refers to ??
return 0;
}
SimpleCat &TheFunction()
{
SimpleCat * pFrisky = new SimpleCat(5,9);
std::cout << "pFrisky: " << pFrisky << std::endl;
return *pFrisky;
}
My attempt:
#include <iostream>
class SimpleCat
{
public:
SimpleCat(int age, int weight);
~SimpleCat() {}
int GetAge() { return itsAge; }
int GetWeight() { return itsWeight; }
private:
int itsAge;
int itsWeight;
};
SimpleCat::SimpleCat(int age, int weight):
itsAge(age), itsWeight(weight) {}
SimpleCat* TheFunction(SimpleCat&);
int main()
{
SimpleCat * rCat;
rCat = TheFunction(rCat);
int age = rCat->GetAge();
std::cout << "rCat is " << age << " years old!\n";
std::cout << "rCat: " << rCat << std::endl;
delete rCat;
rCat = 0;
system("PAUSE");
return 0;
}
SimpleCat* TheFunction(SimpleCat& rCat)
{
rCat = new SimpleCat(5, 9);
std::cout << "rCat: " << rCat << std::endl;
return rCat;
}
Second Attempt
#include <iostream>
using namespace std;
class SimpleCat
{
public:
SimpleCat(int age, int weight)
{
}
void setAge(int age)
{
itsAge = age;
}
void setWeight(int wgt)
{
itsWeight = wgt;
}
~SimpleCat() { cout << "Object is being deleted" << endl; }
int GetAge() { return itsAge; }
int GetWeight() { return itsWeight; }
private:
int itsAge;
int itsWeight;
};
//SimpleCat * TheFunction();
SimpleCat& TheFunction(SimpleCat* rCat)
{
rCat = new SimpleCat(5,9);
//pFrisky->setAge(5);
//pFrisky->setWeight(9);
return *rCat;
}
int main()
{
SimpleCat * rCat;
SimpleCat & rCat = TheFunction(&rCat);
int age = rCat.GetAge();
std::cout << "rCat is " << age << " years old!\n";
system("PAUSE");
return 0;
}
This could work (in the sense, compile), but is actually wrong:
SimpleCat TheFunction()
{
rCat = new SimpleCat(5,9);
// do something with rCat if you want
return *rCat;
}
int main()
{
SimpleCat rCat = TheFunction();
int age = rCat.GetAge();
std::cout << "rCat is " << age << " years old!\n";
system("PAUSE");
return 0;
}
Here, you create the new object and return a reference to it to initialize the other object, which is legit, because every C++ class has a copy constructor by default. However, you'll get a memory leak here, because you create new object which is never deleted afterwards.
This can be a better version:
void TheFunction(SimpleCat*& rCat)
{
if (rCat!=NULL) delete rCat;
rCat = new SimpleCat(5,9);
// do something else with rCat if you want
return; //not required
}
int main()
{
SimpleCat * rCat = NULL;
TheFunction(rCat);
int age = rCat->GetAge();
std::cout << "rCat is " << age << " years old!\n";
system("PAUSE");
return 0;
}
Here, you initialize the new pointer by reference(which is also legit). When you declare the pointer, you declare the variable, which has an address, but doesn't have a sensible content yet. You give the reference to that address to your function, so you don't have to return anything. After the function has initialized your reference, you can use it from your main program. No memory will be leaked here, but only as long as all new pointers are initialized with NULL. So potentially this might cause problems too, if your pointer is somehow pointing to a garbage.
The third version (the safest) would be:
void TheFunction(SimpleCat& rCat)
{
rCat.age = 5;
rCat.weight = 9;
}
int main()
{
SimpleCat rCat;
TheFunction(rCat);
int age = rCat.GetAge();
std::cout << "rCat is " << age << " years old!\n";
system("PAUSE");
return 0;
}
There you give the reference to the new object to the function which will initialize it (i.e. assign some values to its members). The object already exists since the moment it's declared (only initialized by garbage by default), so this is also legit. No memory leak here either, because you don't claim memory for any new object.
SimpleCat * rCat;
SimpleCat & rCat = TheFunction(&rCat);
I don't think these lines are going to do what you think they do.
The first line is declaring a variable rCat that is a pointer to a cat, but never constructing a cat to go with it. The second is going to not work because you're declaring the same variable again. (can't have 2 rCat objects).
I'm still not quite sure what you're trying to do, though.
SimpleCat rCat;
TheFunction(&rCat);
and don't do:
rCat = new SimpleCat(...)
In TheFunction, just do the SetAge/SetWeight calls like you have them.
No leaks because you never called new. Of course, TheFunction no longer needs to return anything either because it's just modifying the object that was passed in. I'm not sure if that demonstrates what the author was trying to get to, though.
I think to demonstrate what the author wants, you'd change your TheFunction to be:
void TheFunction(SimpleCat& rCat) {
rCat.SetAge(5);
rCat.SetWeight(9);
}

error pushing structure objects with string members into a std::vector

I'm a C#, C programmer learning C++ and I'm having a bit of a trouble.
I'm trying to push an object of the struct type 'Person' into a vector but the string values which are members of the Person type are not copied. Also the code exits with an error message - posted at the bottom:
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <string.h>
using namespace std;
typedef struct Person {
string Name;
string Lastname;
int Age;
} Person;
void CreatePerson(Person* in_person, string in_name, string in_last,
int in_age)
{
Person t_person;
t_person.Name = in_name;
t_person.Lastname = in_last;
t_person.Age = in_age;
memcpy(in_person, &t_person, sizeof(t_person));
}
int main(int argc, char *argv[])
{
vector<Person> people;
Person t_ppl;
CreatePerson(&t_ppl, "Zareh", "Petros", 13);
people.push_back(t_ppl);
CreatePerson(&t_ppl, "Tina", "Yarroos", 26);
people.push_back(t_ppl);
int ii;
for(ii=0; ii < people.size() ; ii++) {
cout << "Element - " << ii << endl;
cout << "name:" << people[ii].Name << endl;
cout << "lastname:" << people[ii].Lastname << endl;
cout << "age:" << people[ii].Age << endl;
}
return 0;
}
And here is the error message:
*** glibc detected *** ./a.out: double free or corruption (fasttop): 0x09d48048 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x75ee2)[0xb74e8ee2]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdlPv+0x1f)[0xb76e551f]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZNSs4_Rep10_M_destroyERKSaIcE+0x1b)[0xb76cc99b]
/usr/lib/i386-linux-gnu/libstdc++.so.6(+0x909dc)[0xb76cc9dc]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZNSsD1Ev+0x2e)[0xb76cca4e]
std::string is a class and should not be copied by a memcpy operation. It may hold instance-specific data, which will get scrambled if held by two different instances (and probably that's the cause of your problems).
Imagine, that std::string is something like:
class string
{
private:
char * data;
int dataLength;
};
If you memcpy one string to another, both data and dataLength are copied to another place (lately being treated as a normal string instance). However, when the destructor is called on these strings (when they run out of scope), they will attempt to free the data held in data field. First string (which is an actual owner of this pointer) will free memory pointed to by this pointer. But then another destructor of your copied string will run and will try to free this memory again, what is not permitted.
Note, that it's exactly, what your system is reporting: double freeing of memory.
Your code is very C-style. In C++ one would create a class with constructor rather than a function, which fills in a struct. I would write your code in the following way:
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <string.h>
using namespace std;
struct Person
{
public:
string Name;
string Lastname;
int Age;
Person(string newName, string newLastname, int newAge)
: Name(newName), Lastname(newLastname), Age(newAge)
{
}
};
int main(int argc, char *argv[])
{
vector<Person> people;
Person person1("Zareh", "Petros", 13);
people.push_back(person1);
Person person2("Tina", "Yarros", 26);
people.push_back(person2);
for(unsigned int i=0; i < people.size() ; i++)
{
cout << "Element - " << i << endl;
cout << "name:" << people[i].Name << endl;
cout << "lastname:" << people[i].Lastname << endl;
cout << "age:" << people[i].Age << endl;
}
getchar();
return 0;
}
The role of your creation method takes the class constructor. It fills in fields of the class properly. Also, C++ provides default copy-constructor and assignment operator, which will handle assigning one person to another properly.
Some side notes about your code style.
In C++ avoid using memcpy. If you have a need of using it, you probably should consider creating proper copy constructor, std::copy or simply making an assignment (what would work perfectly in your situation). memcpy should be used only when copying raw chunks of memory.
typedef is no longer required for structs in C++. Instead of writing:
typedef struct Name { ... } Name;
You can simply write:
struct Name { ... };
You've already been told you shouldn't be using memcpy in this situation, so I won't bother repeating that.
The problem with your CreatePerson goes well beyond using memcpy, and just changing to std::copy isn't really going to make it right.
Instead of a free function to create a person, you should almost certainly write that functionality as a constructor instead:
struct Person {
string Name;
string Lastname;
int Age;
Person(string Name, string Last, int Age)
: Name(Name), LastName(Last), Age(Age)
{}
};
With this, we can create Person objects much more cleanly:
std:::vector<Person> people;
people.push_back(Person("Zarah", "Petros", 13));
people.push_back(Person("Tina", "Yarroos", 26));
I'd also write an inserter that's responsible for displaying a Person in the proper format:
std::ostream &operator<<(std::ostream &os, Person const &p) {
return os << "Name: " << p.Name < "\n"
<< "Last: " << p.LastName << "\n"
<< "Age: " << p.Age << "\n";
}
With this, your mainstream of your code can insert complete Person objects into a stream without paying attention to the internal details of what a Person contains or how it should display:
for (int i=0; i<people.size(); i++)
std::cout << people[i] << "\n";
If you want to be a little more ambitious, you can use a standard algorithm instead:
std:copy(people.begin(), people.end(),
std::ostream_iterator<Person>(std::cout, "\n"));
Or, if you're using a relatively new compiler, you can use a range-based for loop:
for (auto &p : people)
std::cout << p << "\n";
Putting all that together, your complete program ends up something like this:
#include <string>
#include <iostream>
#include <vector>
using std::string;
struct Person {
string Name;
string LastName;
int Age;
Person(string Name, string Last, int Age)
: Name(Name), LastName(Last), Age(Age)
{}
};
std::ostream &operator<<(std::ostream &os, Person const &p) {
return os << "Name: " << p.Name << "\n"
<< "Last: " << p.LastName << "\n"
<< "Age: " << p.Age << "\n";
}
int main(){
std::vector<Person> people;
people.push_back(Person("Zarah", "Petros", 13));
people.push_back(Person("Tina", "Yarroos", 26));
for (auto &p : people)
std::cout << p << "\n";
return 0;
}
Do not use memcpy() on non-POD types. It does not call copy-constructors.
Use std::copy() instead.
In this case, it is easier to do an assignment. Replace:
memcpy(in_person, &t_person, sizeof(t_person));
with
*in_person = t_person;