Back to C++
2026-03-058 min read

C++ Pointers to Structure

Learn C++ Pointers to Structure step by step with clear examples and exercises.

Why This Matters

Welcome back! Today, we'll delve into an essential aspect of C++ programming: using pointers with structures. This skill is crucial for understanding and manipulating complex data structures efficiently. Let's explore why this matters, prerequisites, the core concept, a worked example, common mistakes, practice questions, and frequently asked questions.

Why Pointers to Structures Matter

  1. Memory Management: Pointers allow you to manipulate memory directly, which is essential when dealing with large data structures like arrays, linked lists, trees, or graphs.
  2. Efficiency: Using pointers can significantly improve the performance of your code by reducing the overhead associated with creating and managing objects.
  3. Real-world Applications: Pointers to structure are used extensively in various domains such as game development, system programming, and data processing, where large amounts of data need to be handled efficiently.
  4. Interview Preparation: Familiarity with pointers to structures is often tested in job interviews, especially for positions that require low-level programming or working with complex data structures.
  5. Flexibility: Pointers to structures enable you to create dynamic data structures that can grow and shrink as needed during runtime.
  6. Passing Structures by Reference: Passing structures by pointers allows functions to modify the original data instead of creating a copy, which can lead to more efficient code.

Prerequisites

To follow this lesson effectively, you should have a good understanding of the following topics:

  1. C++ Basics: Variables, data types, operators, control statements (if...else, for loops), and functions.
  2. Structures: Basic concepts of structures in C++, including their declaration and initialization.
  3. Pointers: Understanding how pointers work, pointer arithmetic, and pointer dereferencing.
  4. Memory Management: Concepts such as dynamic memory allocation (new and delete) and smart pointers (std::unique_ptr, std::shared_ptr, and std::weak_ptr).
  5. Standard Template Library (STL): Familiarity with the STL, including vectors, iterators, and algorithms.

Core Concept

In C++, we can use pointers to manipulate structures directly. This is achieved by declaring a pointer to the structure type and assigning it the address of an existing structure. Let's consider an example:

#include <iostream>
using namespace std;

struct Student {
string name;
int age;
float gpa;
};

int main() {
Student s1 = {"John", 20, 3.5};
Student* pStudent = &s1; // Create a pointer to the structure

cout << "Name: " << pStudent->name << endl; // Access name using pointer
cout << "Age: " << pStudent->age << endl; // Access age using pointer
cout << "GPA: " << pStudent->gpa << endl; // Access gpa using pointer

return 0;
}

In the example above, we first declare a structure Student with three fields: name, age, and gpa. We then create an instance of this structure called s1. To create a pointer to s1, we use the address-of operator & to get the memory address of s1 and assign it to a pointer variable pStudent. Finally, we access the fields of the structure using the arrow operator ->.

Pointer Arithmetic with Structures

Pointer arithmetic allows you to manipulate the memory location of a structure. This is useful when working with arrays of structures or linked lists. Here's an example:

#include <iostream>
using namespace std;

struct Student {
string name;
int age;
float gpa;
};

int main() {
const int NUM_STUDENTS = 3;
Student students[NUM_STUDENTS] = {{"John", 20, 3.5}, {"Jane", 19, 3.7}, {"Doe", 21, 4.0}};

for (Student* pStudent = students; pStudent != students + NUM_STUDENTS; ++pStudent) {
cout << "Name: " << pStudent->name << endl;
cout << "Age: " << pStudent->age << endl;
cout << "GPA: " << pStudent->gpa << endl;
}

return 0;
}

In this example, we create an array of Student structures called students. We then use a pointer pStudent to iterate through the array using pointer arithmetic. Note that the address of the first element in the array is students, and the last element's address is students + NUM_STUDENTS - 1.

Worked Example

Let's create a simple program that manages a list of students using pointers to structures. We will add, remove, and search for students in this list.

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Student {
string name;
int age;
float gpa;
};

void addStudent(vector<Student*>& studentList, const Student& newStudent) {
auto it = find_if(studentList.begin(), studentList.end(), [newStudent](const Student* s) { return s->age > newStudent.age; });
if (it == studentList.end()) {
studentList.push_back(new &newStudent); // Create a new object and add its address to the list
cout << "Added student: " << newStudent.name << endl;
} else {
int index = distance(studentList.begin(), it);
studentList[index] = new &newStudent; // Replace the existing student with the new one
cout << "Replaced student: " << newStudent.name << endl;
}
}

void removeStudent(vector<Student*>& studentList, const string& nameToRemove) {
for (auto it = studentList.begin(); it != studentList.end(); ) {
if ((*it)->name == nameToRemove) {
it = studentList.erase(it);
delete *it; // Delete the object at the erased position
cout << "Removed student: " << nameToRemove << endl;
} else {
++it;
}
}
}

void findStudent(const vector<Student*>& studentList, const string& nameToFind) {
for (auto it = studentList.begin(); it != studentList.end(); ++it) {
if ((*it)->name == nameToFind) {
cout << "Found student: " << (*it)->name << endl;
return;
}
}
cout << "Student not found: " << nameToFind << endl;
}

int main() {
vector<Student*> studentList;
addStudent(studentList, {"Alice", 21, 3.8});
addStudent(studentList, {"Bob", 20, 3.5});
addStudent(studentList, {"Charlie", 22, 3.7});

findStudent(studentList, "Alice");
findStudent(studentList, "David"); // Should not find David in the list

removeStudent(studentList, "Bob");
findStudent(studentList, "Bob"); // Should not find Bob in the list after removal

return 0;
}

In this example, we define functions for adding, removing, and searching students in a dynamic list managed using pointers to structures. We use a vector to store the addresses of the student objects. We also make use of STL algorithms such as find_if and distance.

Common Mistakes

  1. Forgetting to initialize the structure: Make sure you initialize all fields of the structure when declaring an instance, or set them later using the assignment operator.
  2. Dereferencing a null pointer: Always check if a pointer points to a valid memory address before dereferencing it.
  3. Leaking memory: When removing an object from a list managed with pointers, don't forget to delete the corresponding memory using the delete operator.
  4. Using the wrong operator: Be careful when accessing structure fields using the dot operator (.) or arrow operator (->). Use the correct one depending on whether you have a reference or a pointer to the structure.
  5. Incorrect pointer arithmetic: Ensure that you correctly perform pointer arithmetic, including understanding the difference between pre-increment and post-increment operators.
  6. Memory fragmentation: Be aware of memory fragmentation when using dynamic memory allocation with structures, and consider using techniques such as buddy systems or slab allocators to minimize it.
  7. Inconsistent structure layouts: Remember that the layout of structures can vary between different platforms and compilers, which may cause compatibility issues. Use #pragma pack or alignment directives to control the structure layout if necessary.

Practice Questions

  1. Write a function that swaps two students in a list managed with pointers to structures.
  2. Implement a function that sorts a list of students based on their GPA using a quicksort algorithm.
  3. Create a function that finds the student with the highest GPA in a given list managed with pointers to structures.
  4. Write a function that merges two lists of students managed with pointers to structures.
  5. Implement a binary search function for finding a student in a sorted list managed using pointers to structures.
  6. Create a linked list implementation of the Student structure, including functions for insertion, deletion, and traversal.
  7. Write a function that deep copies a list of students managed with pointers to structures.
  8. Implement a hash table using open addressing with linear probing for storing student records managed with pointers to structures.
  9. Create a function that serializes a list of students managed with pointers to structures into a binary file, and another function that deserializes the data from the binary file back into the list.
  10. Write a function that calculates the average GPA of all students in a given list managed with pointers to structures.

FAQ

  1. Why use pointers to structures instead of structures themselves? Pointers allow for more efficient memory management, especially when dealing with large data structures or dynamically allocated memory. They also enable dynamic data structures that can grow and shrink as needed during runtime.
  2. How can I avoid leaking memory when using pointers to structures? Make sure to delete the corresponding memory when removing an object from a list managed with pointers. Consider using smart pointers (std::unique_ptr, std::shared_ptr, and std::weak_ptr) for safer memory management.
  3. What happens if I dereference a null pointer when using pointers to structures? Dereferencing a null pointer results in undefined behavior, which can lead to program crashes or security vulnerabilities. Always check if a pointer points to a valid memory address before dereferencing it.
  4. Can I use pointers to structures as function arguments? Yes, you can pass pointers to structures as function arguments, allowing the function to modify the original data instead of creating a copy. This can lead to more efficient code.
  5. How do I properly allocate memory for a dynamically sized structure array using new[] and delete[]? To allocate memory for a dynamically sized structure array, use new[] with the size calculated at runtime. When deallocating the memory, use delete[]. Make sure to iterate through the array and delete each element individually to avoid memory leaks.
  6. What is the difference between a pointer to a structure and a reference to a structure? A pointer to a structure points to a specific instance of the structure in memory, while a reference to a structure is an alias for an existing structure instance. Pointers allow you to manipulate multiple instances of the structure or dynamically allocated structures, while references are typically used when passing structures as arguments to functions or returning them from functions.
  7. How can I ensure that my structures have consistent layouts across different platforms and compilers? Use #pragma pack or alignment directives to control the structure layout. Be aware that some compilers may not support these directives, so you may need to use platform-specific workarounds or third-party libraries for cross-platform compatibility.
  8. What are some common techniques for minimizing memory fragmentation when using dynamic memory allocation with structures? Techniques for minimizing memory fragmentation include buddy systems, slab allocators, and memory pools. These approaches allocate large blocks of memory and then subdivide them into smaller chunks as needed, reducing the overhead associated with dynamic memory allocation.
  9. What are some best practices for managing memory with pointers to structures in C++? Best practices include initializing all fields of the structure when declaring an instance, checking if a pointer points to valid memory before dereferencing it, and deleting the corresponding memory when removing an object from a list managed with pointers. Additionally, consider using smart pointers (std::unique_ptr, std::shared_
C++ Pointers to Structure | C++ | XQA Learn