Structs???? Malloc??? Pointers to Malloc and Structs??

I'm learning C++ right now and I am having a very hard time understandind structures, dynamic memory, and pointers to the latters. I understand this is how you write a pointer:
1
2
int x;
int *y = &x;


and this is how you write a structure
1
2
3
4
5
6
struct person
{
int age;
float height;
char *name;
};


though I'm not sure how you are supposed to use syntax for malloc, it's confusingint array[10] = (10 * sizeof(int); ?????

And pointers to structs are like
1
2
3
4
5
6
struct *person
{
int age;
float height;
char *name;
};


and pointers to malloc are like ]int *array[10] = (10 * sizeof(int)

Like what difference does it make if you write a pointer to a struct or not? What about malloc? What is the synatx structure of it? I really hope you guys can help me. This is what I'm most struggling with right now.
Whoever is teaching you C++ is doing it poorly -- they are teaching you C -- not C++.

though I'm not sure how you are supposed to use syntax for malloc, it's confusingint array[10] = (10 * sizeof(int); ?????


malloc has no place in C++. It's a C function and should not be used in C++ because it is type unaware and will not work with complex types.

The C++ alternative is the new and delete keywords... but even those you should avoid using. C++ offers a 'vector' class which effectively is a resizable array, removing the need to dynamically allocate arrays manually.

Additionally... using a char* to have a string is a bad idea. C++ offers an actual string class (in the <string> header) that is easier and much safer to use.


If you want to have a struct:
1
2
3
4
5
6
struct Person
{
    int age;
    float height;
    std::string name;  // be sure to #include <string>
};


If you want to create an array of Persons, but do not know the exact size of the array at compile time, you can use a vector:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// create a resizable array of people.  Start with 10 people in the array
std::vector< Person >  myPeople(10);

// here, 'myPeople' can be treated like an array:
myPeople[0].name = "Jeff";
myPeople[0].height = 5.8f;
myPeople[0].age = 25;

// if you want to add another person at the end of the array:
Person newperson;  // create a new person
newperson.name = "NewPerson";
newperson.height = 1.5f;
newperson.age = 3;

myPeople.push_back( newperson ); // add that new person at the end of the array

// here, myPeople now is an array of 11 people.  [0] being Jeff and [10] being NewPerson.

// if you want to resize the array to a specific size, you can use resize:

myPeople.resize(5);

// here, myPeople is now an array of 5 people.  The last 6 people in the array have been dropped. 
I know it's more 'C' like, but I want to learn that part, it has a much smaller overhead than vectors and new/delete and non C-style strings
it has a much smaller overhead than vectors and new/delete and non C-style strings


No it doesn't. Whoever is telling you that is lying to you.

Yes there is more code behind vector and string -- but if you don't use them you'll just have to write that code yourself. So you'll end up with the same thing, only you had to do a bunch of extra work and you'll have more bugs.

In fact... C++'s string class is actually faster for some operations (like finding the length and concatenating) than the C strlen/strcat functions.



I know it's more 'C' like, but I want to learn that part,


okay okay.

I'm open for knowledge -- but please note that you should never, ever, ever be writing this in C++. This is C code:

malloc is type unaware so the size you give it has to be the number of bytes you want to allocate. sizeof() can give you the size of one element in an array, so you'll need to multiply that with the number of elements you want.

Also... malloc cannot return an array because it doesn't know it's allocating an array -- it's just allocating a clump of memory. Therefore, it'll return a pointer which contains the address of the memory it just allocated for you. You would assign this to a Person pointer, so that you can use it as an array:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
typedef struct
{
    int age;
    float height;
    char *name;
} Person;

// if we want an array of 10 Persons:
Person* people = malloc(
                         sizeof(Person)  // <- the size of 1 person
                         * 10            // <- we want room for 10 people
                       );
                       
// now 'people' can be treated like an array of 10 people
people[0].name = malloc( sizeof(char) * 20 ); // allocate room for a string of length 19 (plus the null)
strcpy( people[0].name, "BillyBob" );         // set the name to BillyBob
people[0].height = 1.5f;
people[0].age = 15;


//////////////////
// Don't forget to clean up when you're done.  Unlike with string and vector, this is not
//   done automatically.
//
// If you do not do this, you will leak memory, and your program will consume more and more
//   and more memory as it runs
//
// EVERY malloc must have a matching free.  No exceptions.
//   In the above example, there were 2:  1 for BillyBob's name
//   and another for the array:
free(people[0].name);  // clean up BillyBob's name
free(people);          // then the array 



Note again that malloc and free will fail catastrophically and possibly cause your program to crash if you are using complex types (classes) which is why you should never use these functions in C++.
Disch why do you not recommend new and delete?
My general philosophy is that if you are manually deleting, you are doing it wrong. C++ provides RAII mechanisms so things can be cleaned up automatically upon destruction. Using those tools properly makes it virtually impossible to leak resources. There is very rarely a good reason not to use them.

vector and unique_ptr go a long way in making leak-proof and exception-safe code.

The more manual cleanup you have to do.. the more likely you are to screw up and have leaks.
Last edited on
Topic archived. No new replies allowed.