Con trỏ là một chủ đề lớn trong C++. Hầu như khi code trong C++, ta không thể tránh khỏi việc sử dụng con trỏ và iterator cho các CTDL. Trước tiên, hãy tìm hiểu cách giá trị được lưu trong C++.
## **Địa chỉ**
Địa chỉ (address) của một biến hay giá trị nào đó là vị trí của nó trong bộ nhớ. Mỗi một biến hay object đều có địa chỉ của riêng nó.
Syntax: `&variable_name`
với & trong trường hợp này là reference operator (toán tử tham chiếu).
Example:
```cpp
int a = 5;
cout << "value of a: " << a << endl; // 5
cout << "address of a: " << &a << endl;
```
Ta để ý thấy rằng địa chỉ của a khi in ra là một số ở hệ cơ số 16 (hexadecimal), vì thế về cơ bản địa chỉ cũng là một con số.
## **Con trỏ**
Con trỏ chỉ đơn giản là một biến chứa địa chỉ của một biến khác.
Khai báo: `type& name`
Example:
```cpp!
int a = 5;
int* p = &a;
cout << p << endl; // p == &a
cout << *p << endl; // *p == 5, dereference operator, trả về giá trị chứa trong địa chỉ đó
*p = 2; // *p == a == 2
int** p1 = &p; // do p cũng chỉ là một biến nhưng kiểu của nó là con trỏ nên vẫn có địa chỉ riêng, và p1 là con trỏ chỉ tới con trỏ
cout << p1 << endl; // p1 == &p
cout << *p1 << endl; // *p1 == p == &a
cout << **p1 << endl; // **p1 == *p == a == 2
```
:::info
**Lưu ý:**
Địa chỉ (giá trị của pointer) tuy là một số ở dạng hex, nhưng các toán tử của pointer khá khác so với các kiểu số bình thường.
Example:
```cpp!
int a;
int* p = &a;
cout << p << endl; // VD: 0xf5789ffcc4
cout << p+1 << endl; // 0xf5789ffcc8
```
Để ý giá trị của p tăng lên 4 thay vì 1, đó là vì độ lớn của kiểu int là 4 bytes. +1 vào một pointer kiểu int mang nghĩa di chuyển tới int tiếp theo trong bộ nhớ, cho nên địa chỉ +4 (bytes). Tương tự, +2 sẽ di chuyển tiếp theo 2 int nên địa chỉ được +8 (2 int * 4 bytes), và -3 sẽ di chuyển ngược về 3 int nên địa chỉ -12 (-3 int * 4 bytes). Các toán tử ++, --, +=, -= hoạt động tương tự.
Tương tự với các kiểu khác cũng vậy, để biết số bytes của một kiểu ta có thể dùng hàm sizeof():
```cpp!
cout << sizeof(int) << endl; // 4;
```
Ngoài ra, ta có thể dùng hàm advance(). Syntax là advance(p, n), với p là pointer và n là số lần di chuyển:
```cpp!
advance(p, 2); // p += 2
advance(p, -5); // p -= 5
```
:::
Vậy tổng kết lại, mỗi một biến chứa một giá trị nào đó, có địa chỉ (vị trí) của riêng nó trong bộ nhớ. Con trỏ là một biến có kiểu đặc biệt (vẫn là biến nên vẫn có địa chỉ của nó) và giá trị của nó là địa chỉ của một biến khác.
## **Iterator**
Iterator là một loại con trỏ đặc biệt. Iterator sẽ chỉ vào địa chỉ của những phần tử của một CTDL (trong STL: array, vector, set, map, list, ...).
Khai báo: `type::iterator name`
Example:
```cpp!
#include <bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
vector<int> v = {1, 2, 3, 4, 5, 6};
vector<int>::iterator it = v.begin();
advance(it, 4);
cout << *it << endl; // 5, vì ở vị trí thứ 4 là 5
it -= 2;
cout << *it << endl; // 3
return 0;
}
```