Comprehensive example that demonstrates the use of raw pointers, smart pointers (std::shared_ptr), and std::unique_ptr in the context of scientific computing and simulations. This example will include a memory manager for a 3D grid, a particle system simulation, and a grid ownership model.
algorithm, auto, command_line_arguments, constructor, destructor, initializer_list, iostream, memory, namespace, private, protected, public, push_back, random, range-based, raw_pointer, smart_pointers, sstream, std::mt19937, std::random_device, std::shared_ptr, std::uniform_real_distribution, std::unique_ptr, std::weak_ptr, template, vector
#include <iostream>
#include <vector>
#include <memory>
#include <random>
// Memory Manager for 3D grid using raw pointers
class MemoryManager {
public:
MemoryManager(int x, int y, int z) : x_(x), y_(y), z_(z) {
std::cout << "Allocating 3D grid of size " << x_ << " x " << y_ << " x " << z_ << std::endl;
grid_ = new double**[x_];
for (int i = 0; i < x_; ++i) {
grid_[i] = new double*[y_];
for (int j = 0; j < y_; ++j) {
grid_[i][j] = new double[z_];
}
}
}
~MemoryManager() {
std::cout << "Deallocating 3D grid" << std::endl;
for (int i = 0; i < x_; ++i) {
for (int j = 0; j < y_; ++j) {
delete[] grid_[i][j];
}
delete[] grid_[i];
}
delete[] grid_;
}
void setValue(int x, int y, int z, double value) {
if (x < x_ && y < y_ && z < z_) {
grid_[x][y][z] = value;
}
}
double getValue(int x, int y, int z) const {
if (x < x_ && y < y_ && z < z_) {
return grid_[x][y][z];
}
return 0.0; // Handle out of bounds
}
private:
int x_, y_, z_;
double*** grid_;
};
// Particle class for particle system simulation
class Particle {
public:
Particle(double x, double y, double z) : x_(x), y_(y), z_(z) {}
void move(double dx, double dy, double dz) {
x_ += dx; y_ += dy; z_ += dz;
}
void print() const {
std::cout << "Particle at (" << x_ << ", " << y_ << ", " << z_ << ")" << std::endl;
}
private:
double x_, y_, z_;
};
// Particle system using std::shared_ptr
class ParticleSystem {
public:
void addParticle(double x, double y, double z) {
particles_.push_back(std::make_shared<Particle>(x, y, z));
}
void moveParticles() {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis(-0.1, 0.1);
for (auto& particle : particles_) {
particle->move(dis(gen), dis(gen), dis(gen));
}
}
void printParticles() const {
for (const auto& particle : particles_) {
particle->print();
}
}
private:
std::vector<std::shared_ptr<Particle>> particles_;
};
// Grid class for unique ownership demonstration
class Grid {
public:
Grid(int size) : size_(size) {
std::cout << "Creating Grid of size " << size_ << std::endl;
}
~Grid() {
std::cout << "Destroying Grid of size " << size_ << std::endl;
}
int getSize() const { return size_; }
private:
int size_;
};
// Simulation class using std::unique_ptr for Grid ownership
class Simulation {
public:
Simulation(int gridSize) : grid_(std::make_unique<Grid>(gridSize)) {}
void run() {
std::cout << "Running simulation with grid size " << grid_->getSize() << std::endl;
}
private:
std::unique_ptr<Grid> grid_;
};
int main() {
// Demonstrate MemoryManager with raw pointers
{
MemoryManager mm(4, 4, 4);
mm.setValue(2, 2, 2, 3.14);
std::cout << "Value at (2, 2, 2): " << mm.getValue(2, 2, 2) << std::endl;
}
std::cout << "\n";
// Demonstrate ParticleSystem with std::shared_ptr
{
ParticleSystem ps;
ps.addParticle(0, 0, 0);
ps.addParticle(1, 1, 1);
std::cout << "Initial particle positions:" << std::endl;
ps.printParticles();
ps.moveParticles();
std::cout << "Particle positions after movement:" << std::endl;
ps.printParticles();
}
std::cout << "\n";
// Demonstrate Simulation with std::unique_ptr
{
Simulation sim(10);
sim.run();
}
return 0;
}
This comprehensive example demonstrates the use of raw pointers, std::shared_ptr, and std::unique_ptr in scientific computing contexts:
Raw Pointers: The MemoryManager
class uses raw pointers to manage a 3D grid, which could be used in fluid dynamics simulations. It demonstrates manual memory management with proper allocation and deallocation.
std::shared_ptr: The ParticleSystem
class uses std::shared_ptr to manage particles in a particle system simulation. This ensures that memory is automatically released when particles are no longer in use, and allows for easy sharing of particle data if needed.
std::unique_ptr: The Simulation
class uses std::unique_ptr to manage the ownership of a Grid
object. This ensures that each Grid
is uniquely owned by one Simulation
instance, preventing accidental sharing of grid data.
The main function demonstrates the usage of each of these classes, showing how they can be applied in different scientific computing scenarios. This code provides a solid foundation for understanding memory management techniques in C++ within the context of scientific simulations.