> For the complete documentation index, see [llms.txt](https://acezxn.gitbook.io/vex-ji-qi-ren-cheng-shi-jiao-xue/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://acezxn.gitbook.io/vex-ji-qi-ren-cheng-shi-jiao-xue/jin-jie-jiao-xue/jin-jie-c++/pointers.md).

# Pointers

Pointers 代表一個物件在 Memory 的位置。其他的程式可以透過 Pointer 讀取該位置資料。

## traditional pointers

```cpp
int a = 1;

// Declaration
int* ptr = &a;

// print out the actual object inside the pointer
std::cout << *ptr << std::endl; // 1

// print out the address of the pointer
std::cout << ptr << std::endl;  // 0x7ffd5268db54
```

### 透過 Pointer 改變原本的物件

```cpp
#include <iostream>
using namespace std;

int main() {
    int a = 1;
    int* ptr = &a;

    std::cout << a << std::endl; // a is originally 1

    // add the referenced object by 1
    *ptr += 1;

    // a is modified by ptr and becomes 2
    std::cout << *ptr << std::endl;
    std::cout << a << std::endl; 
    return 0;
}
```

### 套用 Pointer 於 Functions 上

```cpp
#include <iostream>
using namespace std;

// swap values of two integers
void swap(int &a, int &b) {
    int tmp = a;
    a = b;
    b = tmp;
}

int main() {
    int a = 1;
    int b = 2;

    std::cout << a << std::endl; // 1
    std::cout << b << std::endl; // 2

    swap(a, b);

    // values of a and b are swapped
    std::cout << a << std::endl;
    std::cout << b << std::endl;
    return 0;
}
```

## smart pointers

pointers 既是 c++ 的精髓，也是 c++ 的危險。不當的使用和一些的過失往往會導致 pointers 沒被清乾淨，被程式錯誤使用，最後導致程式崩潰。透過 smart pointers 可以幫助清理不被需要的 pointer 並加以管理正在使用的 pointer，使程式更安全。

### unique pointer

這種 pointer 裡的物件只存在於它被定義的 scope，一旦離開就會自我刪除。這可以阻止 pointer 的共用，降低錯誤的風險。

```cpp
// Example from https://en.cppreference.com/w/cpp/memory/unique_ptr

#include <cassert>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <memory>
#include <stdexcept>
 
struct D
{
    D() { std::cout << "D::D\n"; }
    ~D() { std::cout << "D::~D\n"; }
 
    void bar() { std::cout << "D::bar\n"; }
};
 
// a function consuming a unique_ptr can take it by value or by rvalue reference
std::unique_ptr<D> pass_through(std::unique_ptr<D> p)
{
    p->bar();
    return p;
}
 

int main()
{
       // Create a (uniquely owned) resource
       std::unique_ptr<D> p = std::make_unique<D>();
       
       // Transfer ownership to `pass_through`,
       // which in turn transfers ownership back through the return value
       std::unique_ptr<D> q = pass_through(std::move(p));
       
       // p is now in a moved-from 'empty' state, equal to nullptr
       assert(!p);
}
```

### shared pointer

這種 pointer 裡的物件在沒有 shared\_ptr reference 的情況會自我刪除。這可以保護系統，使其回收不必要的 pointer，以降低錯誤的風險。

```cpp
// Example from https://en.cppreference.com/w/cpp/memory/shared_ptr

#include <chrono>
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>
 
using namespace std::chrono_literals;
 
struct Base
{
    Base() { std::cout << "Base::Base()\n"; }
 
    // Note: non-virtual destructor is OK here
    ~Base() { std::cout << "Base::~Base()\n"; }
};
 
struct Derived: public Base
{
    Derived() { std::cout << "Derived::Derived()\n"; }
 
    ~Derived() { std::cout << "Derived::~Derived()\n"; }
};
 
void print(auto rem, std::shared_ptr<Base> const& sp)
{
    std::cout << rem << "\n\tget() = " << sp.get()
              << ", use_count() = " << sp.use_count() << '\n';
}
 
void thr(std::shared_ptr<Base> p)
{
    std::this_thread::sleep_for(987ms);
    std::shared_ptr<Base> lp = p; // thread-safe, even though the
                                  // shared use_count is incremented
    {
        static std::mutex io_mutex;
        std::lock_guard<std::mutex> lk(io_mutex);
        print("Local pointer in a thread:", lp);
    }
}
 
int main()
{
    std::shared_ptr<Base> p = std::make_shared<Derived>();
 
    print("Created a shared Derived (as a pointer to Base)", p);
 
    std::thread t1{thr, p}, t2{thr, p}, t3{thr, p};
    p.reset(); // release ownership from main
 
    print("Shared ownership between 3 threads and released ownership from main:", p);
 
    t1.join(); t2.join(); t3.join();
 
    std::cout << "All threads completed, the last one deleted Derived.\n";
}
```

### weak pointer

weak pointer 是一種 pointer，必須轉換成 shared\_ptr 才能讀取資料。可以用於確保取得 reference 物件時物件存在。

<pre class="language-cpp"><code class="lang-cpp"><strong>// Example from https://en.cppreference.com/w/cpp/memory/weak_ptr
</strong><strong>
</strong><strong>#include &#x3C;iostream>
</strong>#include &#x3C;memory>
 
std::weak_ptr&#x3C;int> gw;
 
void observe()
{
    std::cout &#x3C;&#x3C; "gw.use_count() == " &#x3C;&#x3C; gw.use_count() &#x3C;&#x3C; "; ";
    // we have to make a copy of shared pointer before usage:
    if (std::shared_ptr&#x3C;int> spt = gw.lock()) {
        std::cout &#x3C;&#x3C; "*spt == " &#x3C;&#x3C; *spt &#x3C;&#x3C; '\n';
    }
    else {
        std::cout &#x3C;&#x3C; "gw is expired\n";
    }
}
 
int main()
{
    {
        auto sp = std::make_shared&#x3C;int>(42);
        gw = sp;
 
        observe();
    }
 
    observe();
}
</code></pre>
