Ready to practice?
Sign up to access interactive coding exercises and track your progress.
Generic Pointer Type
Understand void pointers and memory management concepts.
Void pointers
The void pointer (also called a generic pointer) is a special pointer type that can point to objects of any data type. Declare a void pointer using the void keyword as the pointer's type:
void* anyPtr{};
A void pointer can point to any data type:
int health{};
double attackPower{};
struct Character
{
int level;
double experience;
};
Character player{};
void* anyPtr{};
anyPtr = &health;
anyPtr = &attackPower;
anyPtr = &player;
However, because void pointers don't know what type they point to, dereferencing them directly is illegal. You must first cast the void pointer to the appropriate type:
int gold{ 500 };
void* vPtr{ &gold };
int* intPtr{ static_cast<int*>(vPtr) };
std::cout << *intPtr << '\n';
Output:
500
The obvious question: if a void pointer doesn't know what it points to, how do you know what to cast it to? That's your responsibility to track.
Here's a practical example:
#include <cassert>
#include <iostream>
enum class StatType
{
HEALTH,
DAMAGE,
NAME
};
void displayStat(void* ptr, StatType type)
{
switch (type)
{
case StatType::HEALTH:
std::cout << *static_cast<int*>(ptr) << '\n';
break;
case StatType::DAMAGE:
std::cout << *static_cast<double*>(ptr) << '\n';
break;
case StatType::NAME:
std::cout << static_cast<char*>(ptr) << '\n';
break;
default:
std::cerr << "displayStat(): unknown type\n";
assert(false && "type not handled");
break;
}
}
int main()
{
int playerHealth{ 100 };
double weaponDamage{ 45.5 };
char heroName[]{ "Alaric" };
displayStat(&playerHealth, StatType::HEALTH);
displayStat(&weaponDamage, StatType::DAMAGE);
displayStat(heroName, StatType::NAME);
return 0;
}
Output:
100 45.5 Alaric
Void pointer miscellany
Void pointers can be null:
void* ptr{ nullptr };
Deleting a void pointer causes undefined behavior because the pointer doesn't know what type (and therefore what destructor) to use. If you must delete through a void pointer, first cast it back to the correct type.
Pointer arithmetic doesn't work with void pointers. Arithmetic requires knowing the object size to calculate offsets, and void pointers don't have that information.
Void references don't exist. A void& wouldn't know what type it references, making it meaningless.
Conclusion
Avoid void pointers when possible. They bypass type checking, allowing nonsensical operations that compile without warnings:
int playerHealth{ 100 };
displayStat(&playerHealth, StatType::NAME);
This compiles but produces garbage output or undefined behavior.
The displayStat() function above seems clever for handling multiple types, but C++ offers better alternatives. Function overloading handles multiple types while preserving type safety. Templates provide even more flexibility with full type checking.
If you encounter a situation where void pointers seem necessary, first verify that function overloading, templates, or std::variant won't solve the problem more safely. Void pointers should be a last resort.
Summary
Void pointers: Declared as void*, can point to objects of any type. They trade type safety for flexibility.
Cannot dereference directly: Void pointers don't know their pointed-to type, so dereferencing is illegal. Cast to the appropriate type using static_cast first.
Tracking type information: Programmers must track what type a void pointer references, typically using an accompanying enum or other mechanism.
Void pointer limitations: Can hold nullptr, but deleting causes undefined behavior (cast first). Pointer arithmetic doesn't work. No such thing as a void reference.
Type safety concerns: Void pointers bypass type checking, allowing operations that compile but don't make sense. Errors only appear at runtime.
Better alternatives: Function overloading and templates handle multiple types with full type checking. std::variant provides type-safe unions. Prefer these over void pointers.
Void pointers sacrifice type safety for flexibility. Use them only when no safer alternative exists.
Generic Pointer Type - Quiz
Test your understanding of the lesson.
Practice Exercises
Type-Safe Void Pointer Manager
Create a data manager that uses void pointers to store different types of data. Use an enum to track the type and practice safe casting operations.
Lesson Discussion
Share your thoughts and questions
No comments yet. Be the first to share your thoughts!