unique_ptr

unique_ptr儲存在stack中記憶體,當unique_ptr離開有效的範圍(例如:離開main函式),就會啟動unique_ptr的解構子,解構子會去刪除unique_ptr指向的指標,就可以防止new出來的物件,但沒delete它,記憶體沒被釋放的問題。
unique_ptr只指向一個指標,沒有辦法指向多個指標。

建立

要include memory

#include <memory>

以下建立方式有註解。

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
#include <iostream>
#include <memory>
using namespace std;
class Student {
 public:
  string name_;
  Student() {
    cout << "Student 建構子" << endl;
  }
  Student(const string& name) : name_(name){
    cout << "Student一個參數 建構子" << endl;
  }
  ~Student() {
    cout << "Student 解構子" << endl;
  }
};
int main() {
  // 方式一:使用指標作為unique_ptr建構子參數
  Student* s = new Student("Mary");
  unique_ptr<Student> ptr1(s);  
  // 方式二:使用匿名物件作為unique_ptr建構子參數
  unique_ptr<Student> ptr2(new Student);
  // 方式二:使用make_unique c++14含以上才能用
  unique_ptr<Student> ptr3 = make_unique<Student>();
  // 方式二:使用make_unique一個參數的使用方法
  unique_ptr<Student> ptr4 = make_unique<Student>("Alice");
  return 0;
}
Student一個參數 建構子
Student 建構子
Student 建構子
Student一個參數 建構子
Student 解構子
Student 解構子
Student 解構子
Student 解構子

不支援assign=運算子與拷貝函式

以下會編譯失敗

1
2
3
4
5
6
7
8
9
10
11
int main() {
  Student* s = new Student("Mary");
  // 以下會編譯失敗,unique_ptr不支援拷貝函式
  unique_ptr<Student> ptr3 = s;
  unique_ptr<Student> ptr4 = new Student("Mary");
  unique_ptr<Student> ptr5 = ptr3;
  // 以下會編譯失敗,unique_ptr不支援assign運算子=
  unique_ptr<Student> ptr6;
  ptr6 = ptr3;
  return 0;
}

取值運算子

1
2
3
4
5
6
7
8
int main() {
  Student* s = new Student("Mary");
  unique_ptr<Student> ptr1(s);
  // 使用*取值運算子
  cout << "*s.name = " << (*s).name_ << endl;
  cout << "*ptr1.name = " << (*ptr1).name_ << endl;
  return 0;
}
Student一個參數 建構子
*s.name = Mary
*ptr1.name = Mary
Student 解構子

箭頭運算子

1
2
3
4
5
6
7
8
int main() {
  Student* s = new Student("Mary");
  unique_ptr<Student> ptr1(s);
  // 使用->箭頭
  cout << "s->name = " << s->name_ << endl;
  cout << "ptr1->name = " << ptr1->name_ << endl;
  return 0;
}
Student一個參數 建構子
s->name = Mary
ptr1->name = Mary
Student 解構子

記憶體位址

get()函式可以取得物件記憶體位址。

1
2
3
4
5
6
7
8
9
10
int main() {
  Student* s = new Student("Mary");
  unique_ptr<Student> ptr1(s);
  // 記憶體位址
  cout << "s的位址 = " << s << endl;
  cout << "ptr1 = " << ptr1 << endl;
  cout << "get() = " << ptr1.get() << endl;
  cout << "ptr1的位址 = " << &ptr1 << endl;
  return 0;
}
Student一個參數 建構子
s的位址 = 0x60000020c720
ptr1 = 0x60000020c720
get() = 0x60000020c720
ptr1的位址 = 0x7ff7bfeff2b0
Student 解構子

函式

函式參數只能參考,不能值(因為unique_ptr不支援assign=與拷貝函式)

1
2
3
4
5
6
7
8
9
10
void func(unique_ptr<Student> &ptr) {
  cout << "func name = " << ptr->name_ << endl;
}
int main() {
  Student* s = new Student("Mary");
  unique_ptr<Student> ptr1(s);
  // 函式參數,只能傳參考,不能傳值(因為unique_ptr不支援assign=與拷貝函式)
  func(ptr1);
  return 0;
}
Student一個參數 建構子
func name = Mary
Student 解構子

一個unique_ptr指向一個指標

1
2
3
4
5
6
7
8
int main() {
  Student* s = new Student("Mary");
  // 不能使用多個unique_ptr指向同一個物件,因為多個unique_ptr對同一個記憶體位址釋放多次
  // unique_ptr<Student> ptr5(s);
  // unique_ptr<Student> ptr6(s);
  // unique_ptr<Student> ptr7(s);
  return 0;
}

完整程式碼

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
51
52
53
54
55
#include <iostream>
#include <memory>
using namespace std;
class Student {
 public:
  string name_;
  Student() {
    cout << "Student 建構子" << endl;
  }
  Student(const string& name) : name_(name){
    cout << "Student一個參數 建構子" << endl;
  }
  ~Student() {
    cout << "Student 解構子" << endl;
  }
};
void func(unique_ptr<Student> &ptr) {
  cout << "func name = " << ptr->name_ << endl;
}
int main() {
  // 方式一:使用指標作為unique_ptr建構子參數
  Student* s = new Student("Mary");
  unique_ptr<Student> ptr1(s);
  // 使用*取值運算子
  cout << "*s.name = " << (*s).name_ << endl;
  cout << "*ptr1.name = " << (*ptr1).name_ << endl;
  // 使用->箭頭
  cout << "s->name = " << s->name_ << endl;
  cout << "ptr1->name = " << ptr1->name_ << endl;
  // 記憶體位址
  cout << "s的位址 = " << s << endl;
  cout << "ptr1 = " << ptr1 << endl;
  cout << "get() = " << ptr1.get() << endl;
  cout << "ptr1的位址 = " << &ptr1 << endl;
  // 函式參數,只能傳參考,不能傳值(因為unique_ptr不支援assign=與拷貝函式)
  func(ptr1);
  // 方式二:使用匿名物件作為unique_ptr建構子參數
  unique_ptr<Student> ptr2(new Student);
  // 方式二:使用make_unique c++14含以上才能用
  unique_ptr<Student> ptr3 = make_unique<Student>();
  // 方式二:使用make_unique一個參數的使用方法
  unique_ptr<Student> ptr4 = make_unique<Student>("Alice");
  // 以下會編譯失敗,unique_ptr不支援拷貝函式
  // unique_ptr<Student> ptr4 = s;
  // unique_ptr<Student> ptr4 = new Student("Mary");
  // unique_ptr<Student> ptr4 = ptr3;
  // 以下會編譯失敗,unique_ptr不支援assign運算子=
  // unique_ptr<Student> ptr4;
  // ptr4 = ptr3;
  // 不能使用多個unique_ptr指向同一個物件,因為多個unique_ptr對同一個記憶體位址釋放多次
  // unique_ptr<Student> ptr5(s);
  // unique_ptr<Student> ptr6(s);
  // unique_ptr<Student> ptr7(s);
  return 0;
}

results matching ""

    No results matching ""