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::vector
class template is used to create a vectorpoints
that can holdPoint
objects. - The constructor
std::vector<Point>(5)
initializes the vector with 5 default-constructedPoint
objects. - A loop iterates over the vector, initializing each
Point
object with specific values using its constructor. - Another loop iterates over the vector, accessing and printing the objects using the
print()
method.
- The
Using
new
anddelete
(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
Shape
is defined with a virtualdraw()
method. - A derived class
Circle
inherits fromShape
and implements thedraw()
method. - A pointer array
shapes
is dynamically allocated usingnew
to holdShape
pointers. - Individual objects are created using
new
and assigned to the corresponding elements in the array. - The virtual
draw()
method is called on each object using polymorphism. - Memory is manually deallocated using
delete
for each object and then for the array itself.
- An abstract base class
Key Considerations and Best Practices
- Prefer
std::vector
for most cases:std::vector
offers automatic memory management, safer bounds checking, and iterator-based access
Comments
Post a Comment