Understanding Dynamic Arrays and Objects in C++
- Dynamic Arrays: In C++, arrays are typically fixed-size at compile time. Dynamic arrays, also known as
std::vector, provide a flexible way to create arrays whose size can be determined or modified at runtime. They automatically manage memory allocation and deallocation, reducing the risk of memory leaks. - Objects: Objects encapsulate data (member variables) and behavior (member functions) within a self-contained unit. In OOP, objects interact with each other through method calls, adhering to the principles of data abstraction, encapsulation, inheritance, and polymorphism.
Creating Dynamic Arrays of Objects
There are two main approaches to create dynamic arrays of objects in C++:
Using
std::vector:C++#include <iostream> #include <vector> class Point { int x, y; public: Point(int xVal, int yVal) : x(xVal), y(yVal) {} void print() const { std::cout << "(" << x << ", " << y << ")" << std::endl; } }; int main() { // Create a dynamic array of 5 Point objects std::vector<Point> points(5); // Initialize the objects' values for (int i = 0; i < 5; ++i) { points[i] = Point(i, i + 1); } // Access and manipulate objects for (const Point& point : points) { point.print(); } return 0; }In this example:
- The
std::vectorclass template is used to create a vectorpointsthat can holdPointobjects. - The constructor
std::vector<Point>(5)initializes the vector with 5 default-constructedPointobjects. - A loop iterates over the vector, initializing each
Pointobject with specific values using its constructor. - Another loop iterates over the vector, accessing and printing the objects using the
print()method.
- The
Using
newanddelete(manual memory management):C++#include <iostream> class Shape { public: virtual void draw() const = 0; ~Shape() = default; // Destructor for proper memory deallocation }; class Circle : public Shape { int radius; public: Circle(int radiusVal) : radius(radiusVal) {} void draw() const override { std::cout << "Drawing a circle with radius " << radius << std::endl; } ~Circle() override { std::cout << "Deleting Circle object" << std::endl; } }; int main() { // Create a dynamic array of 3 Shape pointers Shape** shapes = new Shape*[3]; // Allocate and initialize objects shapes[0] = new Circle(5); shapes[1] = new Circle(10); shapes[2] = new Circle(15); // Call methods on the objects for (int i = 0; i < 3; ++i) { shapes[i]->draw(); } // Deallocate memory manually for (int i = 0; i < 3; ++i) { delete shapes[i]; } delete[] shapes; return 0; }In this example:
- An abstract base class
Shapeis defined with a virtualdraw()method. - A derived class
Circleinherits fromShapeand implements thedraw()method. - A pointer array
shapesis dynamically allocated usingnewto holdShapepointers. - Individual objects are created using
newand assigned to the corresponding elements in the array. - The virtual
draw()method is called on each object using polymorphism. - Memory is manually deallocated using
deletefor each object and then for the array itself.
- An abstract base class
Key Considerations and Best Practices
- Prefer
std::vectorfor most cases:std::vectoroffers automatic memory management, safer bounds checking, and iterator-based access
Comments
Post a Comment