Home Item 7 (1/2) - 智能指针(smart pointers)(中文)
Post
Cancel

Item 7 (1/2) - 智能指针(smart pointers)(中文)

智能指针

當你看到一個 int* ptr 在你的 c++ code 中使用,用完後要不要去 delete 它 ? 如果要,請問是使用 delete [] ptr or delete ptr ? 若後面的 code 有做 delete , 則 重複 delete 會造成 crush. 如果不要,而後面沒有 code 做 delete ,則造成 memory leak。 上述的困境,你一定遇過.., 而 smart pointer 就是來解決這樣的問題! (太棒了)

在 C++ 中,智能指针(smart pointers)提供了一種安全和自動化的資源管理方式。 C++11 引入了幾種不同類型的智能指针,其中包括 std::unique_ptrstd::shared_ptrstd::weak_ptr。每種智能指针都有其特定的使用情景和優點。

下面是這三種智能指针的使用時機及範例。

std::unique_ptr

std::unique_ptr 是一種獨占所有權的智能指针,確保某一時間只有一個指针擁有該資源。這樣可以防止資源泄漏和重複釋放資源。

使用時機:

  1. 當你希望某個對象有且只有一個所有者時。
  2. 用於實現 RAII(Resource Acquisition Is Initialization)模式。
  3. 避免指针的拷貝和共享。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <memory>

class Resource {
public:
    Resource() { std::cout << "Resource acquired : "<< this << "\n"; }
    ~Resource() { std::cout << "Resource destroyed : "<< this <<"\n"; }
    void sayHello() const { std::cout << "Hello, Resource from : " << this <<"\n"; }
};

int main() {

    std::cout << "~Enter scope" << std::endl;
    {
        std::unique_ptr<Resource> res1(new Resource());
        res1->sayHello();

        // Transfer ownership
        std::unique_ptr<Resource> res2 = std::move(res1);
        if (!res1) {
            std::cout << "res1 is null\n";
        }
        res2->sayHello();
        // Resource will be automatically destroyed when res2 goes out of scope
    }

    std::cout << "~Leave scope" << std::endl;
    std::cout << "------------" << std::endl;

    std::cout << "~Enter scope" << std::endl;
    {
        int size = 3;
        std::unique_ptr<Resource[]> res1 = std::make_unique<Resource[]>(size);

        for (size_t i = 0; i < size; i++)
        {
            res1[i].sayHello();
        }

        // Transfer ownership
        std::unique_ptr<Resource[]> res2 = std::move(res1);
        if (!res1) {
            std::cout << "res1 is null\n";
        }

    }
    std::cout << "~Leave scope" << std::endl;

    return 0;
}

當離開 scope 時,自動釋放資源

c++11 make_unique 支援創建動態數組

1
std::make_unique<Resource[]>(3);

執行結果 Desktop View

std::shared_ptr

std::shared_ptr 是一種共享所有權的智能指针,允許多個指针指向同一個資源。當最後一個指向該資源的指针被銷毀時,資源會被自動釋放。

使用時機:

  1. 當你需要多個所有者共享同一個資源時。
  2. 當資源的生命週期需要在多個對象或函數之間共享時。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <memory>

class Resource {
 public:
     Resource() { std::cout << "Resource acquired : " << this << "\n"; }
     ~Resource() { std::cout << "Resource destroyed : " << this << "\n"; }
     void sayHello() const { std::cout << "Hello, Resource from : " << this << "\n"; }
};

int main() {
     std::shared_ptr<Resource> res1 = std::make_shared<Resource>();
     std::cout << "res1.use_count : " << res1.use_count() << std::endl;

     std::cout << "~Enter scope" << std::endl;
     {
         std::shared_ptr<Resource> res2 = res1;
         res2->sayHello();
         std::cout << "res1.use_count : " << res1.use_count() << std::endl;
         std::cout << "res2.use_count : " << res2.use_count() << std::endl;

         std::cout << "res2 goes out of scope\n";
     }
     std::cout << "~Leave scope" << std::endl;

     std::cout << "res1.use_count : " << res1.use_count() << std::endl;
     res1->sayHello();
     std::cout << "res1 goes out of scope\n";

     // Resource will be automatically destroyed when res1 goes out of scope
     return 0;
}

use_count() 可以看到資源被多少 share pointer 持有。

res2 離開 scope 時,釋放對資源的持有權。

在 c++11 時,make_shared 還不支援創建動態數組

Desktop View

建動態數組會得到以下錯誤

1
std::shared_ptr<Resource[]> res1 = std::make_shared<Resource[]>(3);

Desktop View

☝ツ☝

This post is licensed under CC BY 4.0 by the author.

👈 ツ 👍