1. What exactly is the weakou PTR?
In short, we can say that we can PTR is an assistant of shared PTR. It is an intelligent pointer introduced to cooperate with shared PTR. It points to an object managed by shared PTR without affecting the life cycle of the object. That is to say, binding a weak PTR to a shared PTR will not change the reference count of shared PTR. No matter whether there is a leak UU PTR pointing or not, once the last shared UU PTR pointing to the object is destroyed, the object will be released.
2. Why do we need a weak uuptr?
Multiple shared PTR instances can point to the same dynamic object and maintain a shared reference counter. For the counting implemented by the reference counting method, the problem of circular reference (or circular reference) is always unavoidable, and the intelligent pointer weak PTR is needed at this moment
Example:
#include <iostream> #include <memory> #include <vector> using namespace std; class ClassA { public: ClassA() { cout << "ClassA Constructor..." << endl; } ~ClassA() { cout << "ClassA Destructor..." << endl; } shared_ptr<ClassB> pb; // Reference B in A }; class ClassB { public: ClassB() { cout << "ClassB Constructor..." << endl; } ~ClassB() { cout << "ClassB Destructor..." << endl; } shared_ptr<ClassA> pa; // Reference A in B }; int main() { shared_ptr<ClassA> spa = make_shared<ClassA>(); shared_ptr<ClassB> spb = make_shared<ClassB>(); spa->pb = spb; spb->pa = spa; }
Result of code:
ClassA Constructor...
ClassB Constructor...
Program ended with exit code: 0
There is an obvious error in this example. When the main function is finished, the dynamic resources managed by spa and spb are not released, resulting in a memory leak.
There is a circular reference between ClassA and ClassB
At this moment, we need a weak aputr smart pointer to break this circular reference.
3. How to use the weak_ptr?
To create a weaku PTR instance:
When we create a weak apuptr, we need to initialize the weak apuptr with a shared apuptr instance. Because of weak sharing, the creation of the weak apuptr will not affect the reference count value of the shared apuptr.
Example:
int main() {
shared_ptr<int> sp(new int(5));
cout << "Before creation sp Reference count for:" << sp.use_count() << endl; // use_count = 1weak_ptr<int> wp(sp);
cout << "After creation sp Reference count for:" << sp.use_count() << endl; // use_count = 1
}
How to determine the existence of the object pointed to by the weakou PTR:
Since it does not change the reference count of the shared PTR instance, it is possible that the object pointed to by it is released. At this point, we can't directly access the object with the use of weakapuptr. So how can we judge whether the object pointed to by the weakou PTR exists? The lock function is provided in C + + to implement this function. If the object exists, the lock() function returns a shared uuptr pointing to the shared object, otherwise it returns an empty shared uuptr.
Example:
class A
{
public:
A() : a(3) { cout << "A Constructor..." << endl; }
~A() { cout << "A Destructor..." << endl; }int a;
};int main() {
shared_ptr<A> sp(new A());
weak_ptr<A> wp(sp);if (shared_ptr<A> pa = wp.lock())
{
cout << pa->a << endl;
}
else
{
cout << "wp Null pointing object" << endl;
}
}
In addition, the week UU PTR provides the expired() function to determine whether the object in question has been destroyed.
Example:
class A
{
public:
A() : a(3) { cout << "A Constructor..." << endl; }
~A() { cout << "A Destructor..." << endl; }int a;
};int main() {
shared_ptr<A> sp(new A());
weak_ptr<A> wp(sp);
sp.reset(); // At this time, sp is destroyed
cout << wp.expired() << endl; // true means it has been destroyed, otherwise it is false
}
Code input is as follows:
A Constructor...
A Destructor...
How to use the weakou PTR
It does not overload operator - > and operator * operators, so it is not allowed to use objects directly through the weakaputr. The typical use is to call its lock function to obtain the shared aputr example, and then access the original object.
Finally, let's take a look at how to use the weakapuptr to transform the first code and break the circular reference problem.
class ClassB;
class ClassA
{
public:
ClassA() { cout << "ClassA Constructor..." << endl; }
~ClassA() { cout << "ClassA Destructor..." << endl; }
weak_ptr<ClassB> pb; // Reference B in A
};class ClassB
{
public:
ClassB() { cout << "ClassB Constructor..." << endl; }
~ClassB() { cout << "ClassB Destructor..." << endl; }
weak_ptr<ClassA> pa; // Reference A in B
};int main() {
shared_ptr<ClassA> spa = make_shared<ClassA>();
shared_ptr<ClassB> spb = make_shared<ClassB>();
spa->pb = spb;
spb->pa = spa;
// At the end of the function, consider: will spa and spb release resources?
}
The output results are as follows:
ClassA Constructor...
ClassB Constructor...
ClassA Destructor...
ClassB Destructor...
Program ended with exit code: 0
From the running results, we can see that the objects pointed by spa and spb are released!