Pointer Best Practices
Fundamental Guidelines
1. Always Initialize Pointers
// Correct approach
int* ptr = nullptr;
// Incorrect approach
int* ptr; // Dangerous uninitialized pointer
2. Validate Pointer Before Use
void safeOperation(int* ptr) {
if (ptr != nullptr) {
// Perform safe operations
*ptr = 42;
} else {
// Handle null pointer scenario
std::cerr << "Invalid pointer" << std::endl;
}
}
Memory Management Strategies
Smart Pointer Usage
graph LR
A[Raw Pointer] --> B[Smart Pointer]
B --> C[unique_ptr]
B --> D[shared_ptr]
B --> E[weak_ptr]
Recommended Smart Pointer Patterns
Smart Pointer |
Use Case |
Ownership Model |
unique_ptr |
Exclusive ownership |
Single owner |
shared_ptr |
Shared ownership |
Multiple references |
weak_ptr |
Non-owning reference |
Prevent circular references |
Pointer Passing Techniques
Pass by Reference
// Efficient and safe method
void modifyValue(int& value) {
value *= 2;
}
// Preferred over pointer passing
Const Correctness
// Prevents unintended modifications
void processData(const int* data, size_t size) {
for (size_t i = 0; i < size; ++i) {
// Read-only access
std::cout << data[i] << " ";
}
}
Advanced Pointer Techniques
Function Pointer Example
// Typedef for readability
using Operation = int (*)(int, int);
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
void calculateAndPrint(Operation op, int x, int y) {
std::cout << "Result: " << op(x, y) << std::endl;
}
Common Pointer Pitfalls to Avoid
- Avoid Raw Pointer Arithmetic
- Never Return Pointer to Local Variable
- Check for Null Before Dereferencing
- Use References When Possible
Memory Leak Prevention
class ResourceManager {
private:
int* data;
public:
ResourceManager() : data(new int[100]) {}
// Rule of Three/Five
~ResourceManager() {
delete[] data;
}
};
Modern C++ Recommendations
Prefer Modern Constructs
// Modern approach
std::unique_ptr<int> ptr = std::make_unique<int>(42);
// Avoid manual memory management
graph TD
A[Pointer Performance] --> B[Stack Allocation]
A --> C[Heap Allocation]
A --> D[Smart Pointer Overhead]
Optimization Strategies
- Minimize dynamic allocations
- Use references when possible
- Leverage move semantics
Error Handling
std::unique_ptr<int> createSafeInteger(int value) {
try {
return std::make_unique<int>(value);
} catch (const std::bad_alloc& e) {
std::cerr << "Memory allocation failed" << std::endl;
return nullptr;
}
}
Final Best Practices Checklist
- Initialize all pointers
- Use smart pointers
- Implement RAII
- Avoid raw pointer manipulation
- Practice const correctness
By following these best practices in your LabEx C++ programming journey, you'll write more robust, efficient, and maintainable code.