Pointers
Raw Pointers
// As defined in C
int *p = new int(); //p is raw pointer.
Smart pointers
-
Automatically deletes the allocated memory when goes out of scope.
How? Allocate memory in ctr, Delete memory in dtr. Bcoz Destructors are automatically executed when Object goes out of scope.
Why? Programmer may allocate memory using new() & later might forget to use delete().
- Smart Pointer Implementation Example
template <class T>
class A{ //This class is Smart pointer
T *a; //int *a;
public:
A(T *r) : a(r) { cout << "Allocated\n"; } //A(int *r):a(r)
~A(){
delete a;
cout << "Freed\n";
}
T &operator *(){ //int &operator *() //& returns a only, does not create new copy
return *a;
}
};
int main(){
//Automatic template type deduction => Provided in C++17
A <int> obj(new int()); //obj is my pointer now. I can carry all pointer operations
*obj = 10;
cout << *obj;
A <float> obj1(new float());
}
# g++ smart_pointers
Allocated
10
Allocated
Freed
Freed
Unique vs Smart pointer
| Unique | Shared | |
|---|---|---|
| What | Only 1 Owner of memory, ie only 1 pointer to an object | Multiple owners of a resource |
| Copy Constructible | No, any attempt to make a copy of a unique_ptr will cause a compile-time error. copy ctr, assignment operator are deleted | Yes |
| Move Constructible | Yes,can be moved using the new move semantics | Yes |
Unique pointer (type of smart pointer)
Copy Constructible(No)
-
There can be only one unique_ptr to any resource, any attempt to make a copy of a
unique_ptr will cause a compile-time error.
unique_ptr<int> p(new int(5)) // Okay
unique_ptr<T> c = p; // Error: Can't copy unique_ptr
Move Constructible(Yes)
unique_ptr<int> p(new int(5)) // Okay
unique_ptr<T> cptr = std::move(ptr); // Okay, resource now stored in cptr
Creating unique_ptr using make_unique
make_unique <T>()
- Avoid use of new operator
- Provides exception safety, as new and delete internally handled by compiler.
- Memory is allocated to 0.
struct Config {
int a;
Config() {
a = g;
}
};
int main() {
shared_ptr <Config> ptr = make_unique (); //Call default constructor of class Config
cout << ptr->a; //15
}
Shared pointer (type of smart pointer)
Copy Constructible(Yes)
-
Multiple pointers can point to same resource,
Owner count is maintained using reference counting
When none is referencing the memory, it's deleted automatically.
shared_ptr <int> p = int* p //We can think like this
shared_ptr <T> ptr(new int(2)); // Okay
shared_ptr <T> cptr = ptr; // Okay. Are Copy Constructible
Copy Initialization(No)
-
When we initialise with =, we invoke copy-initialisation
Why CI not allowed? Because shared_ptr constructor is explicit and a explicit construtor is not copy-assignable
int* b = new int;
shared_ptr <int> a = b; //Error
Create shared pointer using make_shared
#include <memory>
#include <iostream>
using namespace std;
constexpr int g = 15;
struct Config {
int a;
Config() {
a = g;
}
};
int main() {
shared_ptr <Config> ptr = make_shared <Config>(); //Call default constructor of class Config
cout << ptr->a; //15
}
How shared_ptr is implemented internally?
-
shared_ptr maintains 2 things.
Creation of shared_ptr: reference_count=1
On every new shared_ptr creation: reference_count++
Deletion/Reset: reference_count--
int reference_count;
T* data; //and a pointer to the object being shared
template <typename T>
class shared_ptr {
struct ControlBlock { //stores a pointer to the object being shared (T* ptr_) and a reference count (int ref_count_).
T* ptr_;
int ref_count_;
};
ControlBlock* data_;
public:
shared_ptr(T* ptr) {
data_ = new ControlBlock;
data_->ptr_ = ptr;
data_->ref_count_ = 1;
}
shared_ptr(const shared_ptr& other) {
data_ = other.data_;
data_->ref_count_++;
}
~shared_ptr() {
if (--data_->ref_count_ == 0) {
delete data_->ptr_;
delete data_;
}
}
};