Smart pointers in C/C++ study notes C++

I. Overview

        In modern C++ programming, the standard library includes smart pointers to help ensure that programs are free of memory and resource leaks and are exception-safe.

        Smart pointers are a composite class designed to manage dynamically allocated memory and ensure that memory is deleted when the smart pointer object goes out of scope. Smart pointers are just classes that wrap raw pointers and overload the ->and* operator; this allows them to provide the same syntax as raw pointers.

        Smart pointers are defined in the std namespace of the <memory> header file. They are essential for RAII (Object Lifecycle and Resource Management) or Resource Acquisition Is Initialization programming habits. The main goal of this idiom is to ensure that the resources are acquired at the same time as the object is initialized, so that all the resources of the object are created and ready in one line of code. In fact, the main principle of RAII is to grant ownership of any heap-allocated resource (for example, dynamically allocated memory or a system object handle) to a stack-allocated object whose destructor contains code that deletes or frees the resource and any Related cleanup code.

        A comparison of raw pointers and smart pointers.

void UseRawPointer()
{
    // 使用原始指针——不推荐。
    Song* pSong = 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_;
    //...

} // song2 在这里被自动删除。

Second, the type of smart pointer

        C++11 defines three types of smart pointers in the <memory> header file of the standard library. they are:

1、unique_ptr

        A unique_ptr has exclusive ownership of the object it points to, and will destroy the object when the pointer goes out of scope. unique_ptr explicitly prevents the pointer it contains from being copied. However, a std::movefunction must be used to transfer ownership of a contained pointer to anotherunique_ptr。

         sample code

#include <iostream>
using namespace std;
#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(){

	unique_ptr<Rectangle> P1(new Rectangle(10, 5));
	cout << P1->area() << endl; // This'll print 50

	// unique_ptr<Rectangle> P2(P1);
	unique_ptr<Rectangle> P2;
	P2 = move(P1);

	// This'll print 50
	cout << P2->area() << endl;

	// cout<<P1->area()<<endl;
	return 0;
}

2,shared_ptr

        Reference counted smart pointers. Use when you want to assign a raw pointer to multiple owners, for example when you return a copy of the pointer from the container but want to keep the original pointer. shared_ptr doesn't delete the raw pointer until all owners go out of scope or otherwise relinquish ownership. The size is two pointers; one for the object and one for the shared control block containing the reference count.

         sample code

#include <iostream>
#include <memory>
using namespace std;

int main() {
  // 
  std::shared_ptr<int> p0(new int(24));  
  std::shared_ptr<int> p1(new int(20));  

  // 两个指针现在都指向同一个内存
  std::shared_ptr<int> p2 = p1; 
  
  p1.reset();  
  // p2 仍然指向内存,因此可以打印它。
  cout<<*p2<<endl;

  // 删除内存,因为没有其他人拥有该内存。
  p2.reset(); 
}

3、weak_ptr

        One weak_ptrprovides access to an object owned by one or more shared_ptrinstances, but does not participate in reference counting.

        sample code

#include <iostream>
#include <memory>
using namespace std;

int main() {
  std::shared_ptr<int> p1(new int(23));
  // 做一个指向 p1 的弱指针
  std::weak_ptr<int> wp1 {p1};

  {
    std::shared_ptr<int> p2 = wp1.lock();
    if (p2) {
      cout<<*p2<<endl;
    }
  }
  // p2 由于超出范围而被销毁。
  // 现在只有 p1 持有内存

  // 删除 p1.
  p1.reset();  

  std::shared_ptr<int> p3 = wp1.lock(); 
  // 代码不会执行,因为 p3 没有指向任何东西
  if (p3) {
      cout<<*p3<<endl;    
  }
  else{
    cout<<"p3 无法打印,因为 p1 不再拥有内存"<<endl;
  }
}

        The main usage scenario of weak_ptr is to detect whether the memory space is valid. Users can check the validity of data through expired() or lock() to avoid null pointers. The second is that it can be used to break circular references.

3. Atomic smart pointers in c++20

        Smart pointer counters are thread-safe, but the objects they point to are not. If multiple thread operations are required, in order to ensure safety, you can

        1. Directly call the lock / unlock function of the mutex.

        2. Use lock_guard to automatically lock and unlock.

        The atomic smart pointers provided in c++20 are thread-safe. I don’t know the specific implementation details. I will briefly record them here. I will take a closer look when I have time. Recently, I always feel that these languages ​​c++, java, etc. are getting more and more like...

template<class U>
struct atomic<std::shared_ptr<U>>; (C++20 起)
template<class U>
struct atomic<std::weak_ptr<U>>;   (C++20 起)

Guess you like

Origin blog.csdn.net/bashendixie5/article/details/127185155