C++: Dynamic memory allocation using a struct member

In summary: The right hand side is looking to assign that to a local variable named pSuit. You don't have such a variable, hence the error. You don't want to assign it to the struct itself; that doesn't make sense. What you should be doing is assigning this allocated memory to an instance of the struct. If you have seven cards, you will have to make seven of these allocations.You will also have to remember to free that memory once you are done using it. Forgetting to release allocated memory is called a memory leak. The operating system will clean up after you, so failing to release resources might not be a problem your current program, but it will kill you eventually.Always clean up
  • #1
Dembadon
Gold Member
659
89

Homework Statement



I am trying to allocate memory on the heap (free-store) for an array of characters using one of my struct members, which is a pointer. However, I am running into scoping issues no matter how I try to go about doing it.

Homework Equations



<data type> *<pointer name>;
<pointer name> = new <data type>[ <size of array> ];

I am using the gcc compiler in unix.

The Attempt at a Solution



Here is my struct:
Code:
struct card {
	char *pSuit;
	int rank;
	char color;
};

Here is a snippet of my initialization section within main:
Code:
pSuit = new char[ 11 ];

Shouldn't this allocate space on the heap for an array of 12 characters? The compiler keeps barking at me, saying: "‘pSuit’ was not declared in this scope". When I try to allocate memory within my struct in hopes to resolve the scoping problem, it tells me the action is forbidden.
 
Last edited:
Physics news on Phys.org
  • #2
Dembadon said:
Shouldn't this allocate space on the heap for an array of 12 characters?
The left hand side allocates an array of 11 chars, not 12. If you want to use this to store a C-style string, that's enough space to hold a string with at most 10 (not 12) characters.

The right hand side is looking to assign that to a local variable named pSuit. You don't have such a variable, hence the error. You don't want to assign it to the struct itself; that doesn't make sense. What you should be doing is assigning this allocated memory to an instance of the struct. If you have seven cards, you will have to make seven of these allocations.

You will also have to remember to free that memory once you are done using it. Forgetting to release allocated memory is called a memory leak. The operating system will clean up after you, so failing to release resources might not be a problem your current program, but it will kill you eventually.

Always clean up after yourself. That's what destructors are for.

What you should have instead of a simple struct where memory is allocated from the outside is a class with a constructor that allocates memory upon construction, releases memory upon destruction. The C++ mantra is "resource allocation is initialization", which really means "resource allocation should be done at initialization time only, and don't forget to clean up the mess when you are done."

In your case you don't have to do any of this resource allocation/deallocation rigamarole. Simply change the type of your data member pSuit from char* to std::string. Prefer C++ strings over C-style strings if at all possible. You don't do the allocation or deallocation; the string object does. Example: Suppose make this change and you have a card card1; variable and you want to set it to the ten of clubs. You can do this via card1.rank = 10; card1.suit = "clubs";
 
  • #3
Dembadon said:

Homework Statement



I am trying to allocate memory on the heap (free-store) for an array of characters using one of my struct members, which is a pointer. However, I am running into scoping issues no matter how I try to go about doing it.

Homework Equations



<data type> *<pointer name>;
<pointer name> = new <data type>[ <size of array> ];

I am using the gcc compiler in unix.

The Attempt at a Solution



Here is my struct:
Code:
struct card {
	char *pSuit;
	int rank;
	char color;
};

Here is a snippet of my initialization section within main:
Code:
pSuit = new char[ 11 ];

Shouldn't this allocate space on the heap for an array of 12 characters? The compiler keeps barking at me, saying: "‘pSuit’ was not declared in this scope". When I try to allocate memory within my struct in hopes to resolve the scoping problem, it tells me the action is forbidden.

pSuit is not a standalone variable. It's an element of a structure. In order to use it, you must have an instance of the structure. For example:

Code:
int main ()
{
    card c;
    c.pSuit = new char[11];
    ...
    delete[] c.pSuit;
}

However, you shouldn't do it this way unless there's a good reason. Generally, you should put new/delete into the constructor/destructor for the struct or class. That way, you cannot accidentally forget to allocate or deallocate the memory pointed to by pSuit.

Code:
struct card {
        card() { pSuit = new char[11]; }
        ~card() { delete[] pSuit; }
	char *pSuit;
	int rank;
	char color;
};

Moreover, if the array you're constructing always has the same size, consider whether it needs to be dynamically allocated in the first place. Would the following not suffice:

Code:
struct card {
	char pSuit[11];
	int rank;
	char color;
};
 
Last edited:
  • #4
D H said:
The left hand side allocates an array of 11 chars, not 12. If you want to use this to store a C-style string, that's enough space to hold a string with at most 10 (not 12) characters.
Indeed. Not sure why I said 12, since the address at 11 will hold the null terminator.

D H said:
The right hand side is looking to assign that to a local variable named pSuit. You don't have such a variable, hence the error. You don't want to assign it to the struct itself; that doesn't make sense. What you should be doing is assigning this allocated memory to an instance of the struct. If you have seven cards, you will have to make seven of these allocations.
Last week's assignment required the suit member to be a C-style string; this week is must be a char* member. I'm familiar with reading-in values to an instance of the struct when the member data type is a character array, but the pointer requirement is throwing me off.

D H said:
You will also have to remember to free that memory once you are done using it. Forgetting to release allocated memory is called a memory leak. The operating system will clean up after you, so failing to release resources might not be a problem your current program, but it will kill you eventually.

Always clean up after yourself. That's what destructors are for.
The professor mentioned this last lecture, during which we were introduced to classes. We aren't allowed to use classes for this week's assignment, but next week's assignment will require us to change our program to use a class instead of a struct.

Since I can't change my struct to a class yet, my understanding of cleaning-up is to delete the memory allocation and set the corresponding pointer to NULL.

-------------------------------------------------------------------------------------------------------

I greatly appreciate the responses, D H and jbunniii.

After reading through your replies, I realized I could've been more specific with respect to the requirements for this week's assignment. I apologize for wasting your time by not including them in my original post. :redface:

Requirements:
1. For this project you will rewrite Project 3 using dynamic memory for all arrays.
2. Square brackets should only be used when allocating and deallocating arrays.
3. The suit array in the card struct must be represented as a char* data member.
4. Memory for the suit array will be allocated in the program.
5. Pointers must be used to manipulate all arrays.

There are other requirements, but they aren't relevant to memory allocation, so I've omitted them from the list above.

I understand points 1 and 2 to mean that all memory allocation for arrays must occur on the heap rather than the stack.

From Point 3, I infer that I must carve out a chunk of memory on the heap for my suit data member. If this must be done within the program, won't I run into a scoping issue when trying to use pSuit to allocate the memory? I don't understand how I can use my pointer in the struct to allocate memory within main, if said pointer isn't available outside of my struct!

Point 4 seems to imply that I will need to use my suit pointer and the new command to allocate memory for an array that will hold a string which represents the suit of a given card.

Point 5 basically means I will be passing pointers to functions instead of arrays, and will be using pointer arithmetic to "walk" along my arrays. This requirement seems redundant to me, though, since it follows directly from point 2.
 
  • #5
Thanks for clarifying the requirements. I'm not sure why you think the requirement to use a struct instead of a class would change anything with regard to how you allocate and de-allocate the memory. The only difference between a struct and a class is that a struct's elements are public by default, whereas a class's elements are private by default. A struct can have a constructor and a destructor, just like a class.
 
  • #6
Dembadon said:
From Point 3, I infer that I must carve out a chunk of memory on the heap for my suit data member. If this must be done within the program, won't I run into a scoping issue when trying to use pSuit to allocate the memory? I don't understand how I can use my pointer in the struct to allocate memory within main, if said pointer isn't available outside of my struct!

Please review the first block of code in my earlier post. You first need to create an instance of the struct. Then you can use the pSuit member variable belonging to that instance:

Code:
int main ()
{
    card c; // this creates an instance of the card struct
    c.pSuit = new char[11]; // allocate memory and point c.pSuit to the memory
    ...
    delete[] c.pSuit; // deallocate the memory before exiting
}

However, as suggested previously, it's much better to do the allocation and de-allocation in the constructor and destructor for the struct:

Code:
struct card {
        card() { pSuit = new char[11]; }
        ~card() { delete[] pSuit; }
	char *pSuit;
	int rank;
	char color;
};

int main()
{
    card c; // Create an instance of the struct. This also allocates memory and points c.pSuit to that memory.
    ...
    // No need to deallocate the memory before exiting. The destructor will automatically do that when c goes out of scope
}
 
  • #7
jbunniii said:
Please review the first block of code in my earlier post. You first need to create an instance of the struct. Then you can use the pSuit member variable belonging to that instance:

Code:
int main ()
{
    card c; // this creates an instance of the card struct
    c.pSuit = new char[11]; // allocate memory and point c.pSuit to the memory
    ...
    delete[] c.pSuit; // deallocate the memory before exiting
}

However, as suggested previously, it's much better to do the allocation and de-allocation in the constructor and destructor for the struct:

Code:
struct card {
        card() { pSuit = new char[11]; }
        ~card() { delete[] pSuit; }
	char *pSuit;
	int rank;
	char color;
};

int main()
{
    card c; // Create an instance of the struct. This also allocates memory and points c.pSuit to that memory.
    ...
    // No need to deallocate the memory before exiting. The destructor will automatically do that when c goes out of scope
}

I understand now. Thank you, jbunniii!
 
  • #8
jbunniii said:
Code:
        card() { pSuit = new char[11]; }

While irrelevant to the original question, I should warn against using this code. One should use either

Code:
        card() pSuit(0) { pSuit = new char[11]; }

or

Code:
        card() pSuit(new char[11]) {}

The problem with the original code is that operator new may throw an exception, in which case the original code will call the destructor, which will then call operator delete[] on an uninitialized pointer. The first alternative makes sure the pointer is initialized with a safe value, and the second alternative ensures that the destructor will not be called if operator new throws.
 

FAQ: C++: Dynamic memory allocation using a struct member

What is dynamic memory allocation in C++?

Dynamic memory allocation in C++ refers to the process of allocating memory for variables or data structures at runtime, rather than at compile time. This allows for more flexibility in memory usage and can help optimize memory usage in certain situations.

How do you use dynamic memory allocation with a struct member in C++?

To use dynamic memory allocation with a struct member in C++, you can use the new keyword to allocate memory for the struct, and then use the -> operator to access and modify its members. For example: struct Person *p = new Person; p->name = "John";

What is the difference between dynamic memory allocation and static memory allocation?

The main difference between dynamic and static memory allocation is that with dynamic allocation, memory is allocated at runtime and can be resized or freed as needed, whereas with static allocation, memory is allocated at compile time and cannot be resized or freed.

What are some advantages of using dynamic memory allocation in C++?

Some advantages of using dynamic memory allocation in C++ include more efficient memory usage, the ability to allocate memory for large or complex data structures, and the potential for better performance in certain situations.

What are some potential drawbacks of using dynamic memory allocation in C++?

One potential drawback of dynamic memory allocation in C++ is that it can be more complex and error-prone than static allocation, as it requires careful management of memory and can lead to memory leaks or other errors if not handled properly.

Similar threads

Replies
7
Views
2K
Replies
8
Views
2K
Replies
10
Views
6K
Replies
2
Views
2K
Replies
2
Views
1K
Replies
1
Views
4K
Back
Top