Smart Pointer
The c++ STL incluce smart pointer, whick is used to make sure the program’s memory and resource safe.
Smart pointer definded in std header file’s “<” namespance.
Example:
void UseRawPointer() {
  Song* pSoing = new Song(L"Nothing on You", L"Bruno Mars");
  delete pSong;
}
void UseSmartPointer() {
  unique_ptr<Song> song2(new Song(L"Nothing on You", L"Bruno Mars"));
  wstring s = song2 -> duration;
}
Main step of execute smart pointer
- 
Declare a smart pointer to a auto (local) variable. (Do not use newormallocexpr)
 
- 
Write a type into the type param. 
- 
In the smart pointer constructor, the raw pointer is passed to the new object. 
- 
Use overwrite ->and*operaters to assess object.
 
- 
Allow smart pointer to delete object. 
1. unique_ptr
unique_ptr doesn’t share its pointer. it cannot copy to another unique_ptr, and it cannot pass to function through value.
The unique_ptr only can be moved, which means memory resource overship will move to another unique_ptr, and the source of unique_ptr will lost this pointer resource.
We can use move for moving unique_ptr

Example:
unique_ptr<Song> SongFactory(const std::wstring& artist, const std::wstring& title) {
  return make_unique<Song>(artist, title);
}
void MakeSongs() {
  auto song = make_unique<Song>(L"Mr. Children", L"Namonaki Uta");
  vector<wstring> titles = { song -> title };
  unique_ptr<Song> song2 = std::move(song);
  ato song3 = SongFactory(L"Michael Jackson", L"Beat It");
}
2. shared_ptr
shared_ptr can be copied, pass to function parameter through value, and then assign to another shared_ptr instance.
All of the instance are fordward to one object and share each "control block"s access permission.
When reference counting is 0, the control block will delete memory resource and itself.

Example:
auto sp1 = make_shared<Song>(L"The Beatles", L"Im Happy Just to Dance With You");
shared_ptr<Song> sp2(new Song(L"Lady Gaga", L"Just Dance"));
shared_ptr<Song> sp5(nullptr);
sp5 = make_shared<Song>(L"Elton John", L"I'm Still Standing");
auto sp3(sp2);
auto sp4 = sp2;
shared_ptr<Song> sp7(nullptr);
sp1.swap(sp2);
3. weak_ptr
Sometimes, an object must store a way to access the underlying object of a shared_ptr without incrementing the reference count. This typically occurs when there are circular references between shared_ptr instances.
Best design practice is to avoid shared ownership of pointers whenever possible. However, if shared ownership of shared_ptr instances is unavoidable, or even preferable for some reason, avoid circular references between them. If circular references are unavoidable, or even preferable for some reason, use a weak_ptr to provide one or more owners with weak references to another shared_ptr owner. By using a weak_ptr, you can create a shared_ptr linked to an existing set of related instances, provided the underlying memory resource is still valid. The weak_ptr itself does not participate in reference counting, so it cannot prevent the reference count from becoming zero. However, you can use a weak_ptr to attempt to acquire a new copy of the shared_ptr that initialized that copy. If the memory has been deleted, the bool operator of the weak_ptr returns false. If the memory is still valid, the new shared pointer increments the reference count, and the memory is guaranteed to be valid as long as the shared_ptr variable remains in scope.
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class Controller
{
public:
   int Num;
   wstring Status;
   vector<weak_ptr<Controller>> others;
   explicit Controller(int i) : Num(i), Status(L"On")
   {
      wcout << L"Creating Controller" << Num << endl;
   }
   ~Controller()
   {
      wcout << L"Destroying Controller" << Num << endl;
   }
   
   
   void CheckStatuses() const
   {
      for_each(others.begin(), others.end(), [](weak_ptr<Controller> wp) {
         auto p = wp.lock();
         if (p)
         {
            wcout << L"Status of " << p->Num << " = " << p->Status << endl;
         }
         else
         {
            wcout << L"Null object" << endl;
         }
      });
   }
};
void RunTest()
{
   vector<shared_ptr<Controller>> v{
       make_shared<Controller>(0),
       make_shared<Controller>(1),
       make_shared<Controller>(2),
       make_shared<Controller>(3),
       make_shared<Controller>(4),
   };
   
   
   for (int i = 0; i < v.size(); ++i)
   {
      for_each(v.begin(), v.end(), [&v, i](shared_ptr<Controller> p) {
         if (p->Num != i)
         {
            v[i]->others.push_back(weak_ptr<Controller>(p));
            wcout << L"push_back to v[" << i << "]: " << p->Num << endl;
         }
      });
   }
   for_each(v.begin(), v.end(), [](shared_ptr<Controller> &p) {
      wcout << L"use_count = " << p.use_count() << endl;
      p->CheckStatuses();
   });
}
int main()
{
   RunTest();
   wcout << L"Press any key" << endl;
   char ch;
   cin.getline(&ch, 1);
}
4. CComPtr and CComQIPtr
https://learn.microsoft.com/zh-cn/cpp/cpp/how-to-create-and-use-ccomptr-and-ccomqiptr-instances?view=msvc-170