Smart pointers are very useful feature of modern C++ programming model.
They are defined in the std namespace in the <memory> header file.
Let’s see the raw and smart pointer in action:
void rawPointer() { sql::Driver * driver = sql::mysql::get_driver_instance(); sql::Connection* connection = driver->connect(host, user, pass); //use connection //remember delete driver; delete connection; } void smartPointer() { std::shared_ptr<sql::Driver> driver(sql::mysql::get_driver_instance()); std::shared_ptr< sql::Connection > con(driver->connect(host, user, pass)); //use connection } //shared pointers are deleted when all pointer owners have gone out of their scope or given up ownership
As we can see there is a clear advantage of using smart pointers instead of the raw ones.
The standard library provide three smart pointer types which should be replacement for raw pointers as long as new code is developed:
- unique_ptr
- allows one and only one owner of the underlying pointer
- deleted when the owner goes out of scope it is defined in
- cannot be shared
- cannot be copied
- small and efficient
- shared_ptr
- underlying pointer can be shared between multiple owners
- not deleted till all owners have gone out of scope or given up ownership
- can be shared
- the size is equal to two pointers: one for the raw pointer, one for the block containing the reference count
- weak_ptr
- use in conjunction with shared_ptr
- provides access to a raw pointer which is owned by one or more shared pointer instances but does not take part in reference counting
- deleted when the only reference to the object is weak_ptr reference
I firstly realized the difference between unique_ptr and shared_ptr when tried to create a unique_ptr and share it among two different objects:
std::shared_ptr<sql::Driver> driver(sql::mysql::get_driver_instance()); std::unique_ptr< sql::Connection > con(driver->connect(host, user, pass)); std::unique_ptr< sql::Statement > stmt(con->createStatement()); stmt->execute("USE " + db); studentsDAO.setConnection(con); groupsDAO.setConnection(con);
Obviously, it cannot be done and the error is raised.
When unique_ptr is replaced by shared_ptr everything works all right. Connection object can be shared between two DAO objects and we are assured that the pointer is deleted when it is not needed by any of the owners:
std::shared_ptr<sql::Driver> driver(sql::mysql::get_driver_instance()); std::shared_ptr< sql::Connection > con(driver->connect(host, user, pass)); std::shared_ptr< sql::Statement > stmt(con->createStatement()); stmt->execute("USE " + db); studentsDAO.setConnection(con); groupsDAO.setConnection(con);