#include <memory> <-- 1 #include <string> using namespace std; #include "Car.hpp" typedef auto_ptr<Car> CarPtr; void f() { CarPtr p(new Car()); <-- 1 p->startEngine(); <-- 2 p->tuneRadioTo("AM", 770); <-- 3 } <-- 4 int main() { f(); }
When control flows over the line labeled 1: Create an object, an object is created dynamically (from the heap). The object is pointed to by the pointer p. The object can be accessed from the point it is created until the CarPtr is destroyed at the } (line 4). Note however that the CarPtr can be returned to a caller. This line is analogous to (but not interchangeable with) the C code p = malloc(sizeof(Car)). Note that parameters can be passed to the constructor; e.g., p = new Car(100, 73);. When control flows over the line labeled 2: Call a member function, the startEngine() member function is called for the object pointed to by p. The line labeled 3: Call another member function is similar, showing how to pass parameters to member functions of dynamically allocated objects. When control flows over the line labeled 4: Destroy the Car object, the Car object pointed to by p is destroyed. If the Car class has a destructor, the runtime system automagically calls the destructor (dtor) when control flows over this line. Note that dynamically allocated objects don't have to be destroyed in the same scope that created them. For example, if the function said return p;, the ownership of the Car object is passed back to the function's caller, meaning that the Car object won't be destroyed until the } of the caller (or the caller's caller if the caller does likewise, and so on): CarPtr g() { CarPtr p(new Car()); // ... return p; <-- 1 } void h() { CarPtr p = g(); <-- 2 // ... } <-- 3
Note to C programmers: It is generally considered bad form to use raw Car* pointers to hold the result of the new Car() operation. This is a big change from the way pointers are handled in the C language. There are many reasons for this change: the C++ approach makes "memory leaks" less likely (there is no explicit use of free(p) or delete p, so programmers don't have to worry about accidentally forgetting the deallocation code or jumping around the deallocation code), the C++ approach makes "dangling references" less likely (if C-like Car* pointers are used, there is a chance that someone will inadvertently access the memory of the Car object after it is deleted), and the C++ approach makes the code "exception safe" (if a C-like Car* were used, any routine that could throw an exception would have to be wrapped in a try...catch block; see FAQ 2.23). |