Pointers are used to access resources outside the program - such as heap memory. Therefore, when accessing heap memory (if anything is created in the heap), you need to use a pointer. When accessing any external resource, we only use a copy of that resource. If we modify it, we will only change the version of the copy. But if we use pointers to access the resource, we will be able to modify the original resource.
Some problems with ordinary pointers in C++ are as follows:
- Memory leak: When the program repeatedly allocates memory but is never released, it will cause memory leaks. This can lead to excessive memory consumption and can eventually lead to system crashes.
- Hanging pointer: A dangling pointer refers to the value of the pointer not being modified after the object is released from memory. At this pointer still points to the freed memory.
- Wild pointer: A wild pointer is a pointer that has been declared and allocated memory, but the pointer is never initialized to point to a valid object or address.
- Inconsistent data: Data inconsistency occurs when some data is stored in memory but is not updated in a consistent manner.
// C++ program demonstrates how pointers work#include <iostream> using namespace std; class Rectangle { private: int length; int breadth; }; void fun() { // Use pointer p and dynamically create a Rectangle object Rectangle* p = new Rectangle(); } int main() { // Infinite loop while (1) { fun(); } }
Output
Memory limit exceeded
explain:
existfun
In the function, a pointer is createdp
, it points to aRectangle
Object. This object contains two integers:length
andbreadth
. whenfun
When the function ends, pointerp
Will be destroyed because it is a local variable. However, the memory it consumes is not released because we forgot to usedelete p;
To delete it. This means that the memory will not be released and cannot be used by other resources. Although we no longer need this variable, we need to free up memory.
existmain
In the function,fun
The function is called infinitely. Created every callp
, but the memory is not released. As the call progresses, the memory continues to increase, but it will not be recycled. Since there is no freed memory, it will eventually lead to a memory leak, and the entire heap memory may become useless as a result.
Smart pointer
As we unconsciously discovered, not releasing a pointer can cause memory leaks and can cause program crashes. Languages such as Java, C# intelligently release unused memory through garbage collection mechanisms. C++ also has its own mechanism:Smart pointer. When an object is destroyed, the smart pointer automatically frees memory. Therefore, we do not need to call manuallydelete
to free up memory.
Smart pointer is a pointer encapsulation class, overloaded like*
and->
etc operator. An object of a smart pointer class looks like a normal pointer, but unlike a normal pointer, it can free up destroyed object memory.
The idea of smart pointers is to create a pointer, destructor, and overloaded operator (such as*
and->
) class. Since the destructor is automatically called when the object is out of scope, the dynamically allocated memory is automatically deleted (or the reference count is reduced).
// C++ program demonstrates how smart pointers work#include <iostream> using namespace std; class SmartPtr { int* ptr; // Actual pointerpublic: // Constructor explicit SmartPtr(int* p = NULL) { ptr = p; } // Destructor ~SmartPtr() { delete (ptr); } // Overload the dereference operator int& operator*() { return *ptr; } }; int main() { SmartPtr ptr(new int()); *ptr = 20; cout << *ptr; // We do not need to call delete ptr: when the object ptr is out of scope // Its destructor will be called automatically, and the destructor will delete ptr. return 0; }
Output
20
The difference between pointers and smart pointers
pointer | Smart pointer |
---|---|
A pointer is a variable that stores the memory address and the memory location data type information. A pointer is a variable that points to a location in memory. | A smart pointer is a stack allocation object encapsulated by a pointer. Simply put, smart pointers are classes that encapsulate pointers. |
It is not destroyed at the end of the scope. | It destroys itself at the end of the scope. |
Pointers have no additional features and are less efficient. | Smart pointers are more efficient because they have additional features for memory management. |
Pointers are managed manually. | Smart pointers are automatically managed. |
Notice:
This only applies toint
type. So do we have to create smart pointers for each object? No, the solution is a template. As shown below,T
Can be of any type.
Example: Use templates to solve problems
// How C++ program demonstrates how templates work and solve pointer problems#include <iostream> using namespace std; // General smart pointer classtemplate <class T> class SmartPtr { T* ptr; // Actual pointerpublic: // Constructor explicit SmartPtr(T* p = NULL) { ptr = p; } // Destructor ~SmartPtr() { delete (ptr); } // Overload the dereference operator T& operator*() { return *ptr; } // Overload the arrow operator so that T members can be accessed like a pointer T* operator->() { return ptr; } }; int main() { SmartPtr<int> ptr(new int()); *ptr = 20; cout << *ptr; return 0; }
Output
20
Notice:
Smart pointers are also very suitable for resource management, such as file handles or network sockets.
Types of smart pointers
The C++ library provides the following types of smart pointer implementations:
auto_ptr
unique_ptr
shared_ptr
weak_ptr
auto_ptr
useauto_ptr
, can be managed throughnew
The object obtained by the expression and inauto_ptr
Delete them when you destroy them. When passingauto_ptr
When describing an object, it stores a pointer to a single allocated object.
Note: Starting from C++11,
auto_ptr
Deprecated.unique_ptr
is a similar feature, but it provides higher security.
unique_ptr
unique_ptr
Only one pointer is stored. We can reassign values by removing the current object and pointing to another object.
Example
// C++ program demonstration of how unique_ptr works// Here we show that unique_ptr points to P1.// But we removed P1 and pointed it to P2, so the pointer is now// Point to P2. #include <iostream> using namespace std; // Dynamic memory management library#include <memory> class Rectangle { int length; int breadth; public: Rectangle(int l, int b) { length = l; breadth = b; } int area() { return length * breadth; } }; int main() { // Smart pointer unique_ptr<Rectangle> P1(new Rectangle(10, 5)); cout << P1->area() << endl; // Print 50 // unique_ptr<Rectangle> P2(P1); unique_ptr<Rectangle> P2; P2 = move(P1); cout << P2->area() << endl; return 0; }
50
50
shared_ptr
passshared_ptr
, multiple pointers can point to the same object at the same time, it will useuse_count()
Method to maintain reference count.
// C++ program demonstrates how shared_ptr works// Here, the smart pointers P1 and P2 point to the same// Object, and they all keep a reference to that object. #include <iostream> using namespace std; // Dynamic memory management library#include <memory> class Rectangle { int length; int breadth; public: Rectangle(int l, int b) { length = l; breadth = b; } int area() { return length * breadth; } }; int main() { // Smart pointer shared_ptr<Rectangle> P1(new Rectangle(10, 5)); cout << P1->area() << endl; shared_ptr<Rectangle> P2; P2 = P1; cout << P2->area() << endl; cout << P1->area() << endl; cout << P1.use_count() << endl; return 0; }
50
50
50
2
weak_ptr
weak_ptr
is a smart pointer that holds a non-owned reference. It is withshared_ptr
Very similar, but does not maintain reference counts. In this way, the pointer will not maintain a strong reference to the object, avoiding passingshared_ptr
Created circular dependency problem.
// C++ program demonstrates how weak_ptr works// Here, the smart pointers P1 and P2 point to the same// Objects, but none of them keep the object's reference. #include <iostream> using namespace std; // Dynamic memory management library#include <memory> class Rectangle { int length; int breadth; public: Rectangle(int l, int b) { length = l; breadth = b; } int area() { return length * breadth; } }; int main() { // Smart pointer shared_ptr<Rectangle> P1(new Rectangle(10, 5)); // Create weak_ptr weak_ptr<Rectangle> P2(P1); cout << P1->area() << endl; cout << P1.use_count() << endl; return 0; }
50
1
Summarize
This is the article about the detailed explanation of smart pointers in C++ and precautions. For more related contents of smart pointers in C++, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!