C++におけるポインタ
[前の授業で]、変数はメモリのどこかに存在します。
[でも、その]「[場所]」は「一体どこにある」の?「[直接アクセスできる]?」
ポインタ[とは、アドレス[を格納するための]変数であり――[これを使えば、メモリを直接操作することができる]。
1. ポインタとは何か?
(1) 1.1 [日常生活における]ポインタ
| [生活シーン] | 番組[での対応] |
|---|---|
| [あなたの家の]住所([例]「[北京市朝陽区]...」など) | ポインタ([その]住所) |
| [あなたの家](アドレス[が指す実際の建物]) | 変数(アドレス[が指す]メモリ[領域]) |
ポインタ[の本質]: [アドレスを][格納する][変数]。**
(2) 1.2 なぜポインタが必要なのか?
- 動的メモリ[割り当て]([後述]
new/delete) - 関数[外部の変更が必要]変数([関数に]ポインタ[を渡す])
- [処理]array(array[名]はポインタである)
- [複雑なデータ構造の実装]([連結リスト]、[木]、[グラフ])
2. ポインタの宣言と初期化
(1) 2.1 ポインタの宣言
[文法]:
▶ サンプル 2: codeexample (難易度 ⭐)
* ;
例:
#include iostream
int main() {
int* pInt; // int
double* pDouble; // double
char* pChar; // char
return 0;
}
💡 [要点]: type* [表示]「[その]type[を指す]ポインタ」。
(2) 2.2 [取得]アドレス演算子(&)
& [変数の]アドレスを取得するために使用します。
#include iostream
int main() {
int x = 5;
std::cout << "x:" << x << std::endl;
std::cout << "x:" << &x << std::endl; // output 0x7ffd4a3b
return 0;
}
出力(例):
x:5
x:0x7ffd4a3b
💡 [ヒント]: address[の具体的な形式は、システムや]コンパイラによって異なります。
(3) 2.3 ポインタの初期化
#include iostream
int main() {
int x = 5;
int* p = &x; // p x(p 's x 's)
std::cout << "x:" << &x << std::endl;
std::cout << "p:" << p << std::endl; // &x
return 0;
}
3. [解]参照(参照解除)
(1) 3.1 [解]参照演算子(*)
* [を使用して][ポインタが][指す]値にアクセスする。
#include iostream
int main() {
int x = 5;
int* p = &x; // p x
std::cout << "x = " << x << std::endl; // 5
std::cout << "*p = " << *p << std::endl; // 5(reference)
return 0;
}
💡 [要点]: *p [こそが] x!
(2) 3.2 [ポインタを介して]変数の値を[変更する]
#include iostream
int main() {
int x = 5;
int* p = &x;
std::cout << ":x =" << x << std::endl; // 5
*p = 100; // x
std::cout << ":x =" << x << std::endl; // 100
return 0;
}
4. ポインタ[のサイズ]
(1) 4.1 ポインタのsizeof
#include iostream
int main() {
int* pInt;
double* pDouble;
char* pChar;
std::cout << "int*:" << sizeof(pInt) << "..." << std::endl;
std::cout << "double*:" << sizeof(pDouble) << "..." << std::endl;
std::cout << "char*:" << sizeof(pChar) << "..." << std::endl;
return 0;
}
出力(64[ビットシステム]):
int*:8
double*:8
char*:8
💡 [要点]: [すべての]ポインタ[のサイズは同じ](64[ビットシステムでは] 8 [バイト]、32[ビットシステムでは] 4 [バイト])——[それらはすべて]アドレスを格納しているからである。
5. nullポインタ(nullptr)
(1) 5.1 nullポインタとは何か?
nullポインタとは、[いかなる]オブジェクト[も]指していないポインタのことです。
#include iostream
int main() {
int* p = nullptr; // (C++11 )
if (p == nullptr) {
std::cout << "p" << std::endl;
}
return 0;
}
💡 [ヒント]: C++11 [以前は] NULL([実際には] 0)が使用されていましたが、[現在は] nullptrの使用が推奨されています。
(2) 5.2 [解]参照ヌルポインタ[クラッシュする]
#include iostream
int main() {
int* p = nullptr;
std::cout << *p << std::endl; // ❌ Definebehavior!
return 0;
}
[実行結果]:
Segmentation fault (core dumped) // Linux
[あるいは]
Process finished with exit code -1073741819 // Windows
⚠️ [絶対に]参照ヌルポインタを解除してはいけません!
6. ポインタ[としての]関数[の引数]
(1) 6.1 [問題]:関数[外部変数の修正が必要]
#include iostream
void modifyValue(int x) {
x = 100; // ❌ modify's,
}
int main() {
int a = 5;
modifyValue(a);
std::cout << "a = " << a << std::endl; // 5()
return 0;
}
(2) 6.2 [解決策]:[ポインタの渡し方]
#include iostream
void modifyValue(int* p) {
*p = 100; // ✅ pointermodify
}
int main() {
int a = 5;
modifyValue(&a); // ...
std::cout << "a = " << a << std::endl; // 100(!)
return 0;
}
7. 演習:[2つの]変数[の]値を交換する
▶ サンプル 1: [ポインタ]を使って swap を実装する (難易度 ⭐)
#include iostream
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 3, y = 5;
std::cout << ":x =" << x << ", y = " << y << std::endl;
swap(&x, &y); // ...
std::cout << ":x =" << x << ", y = " << y << std::endl;
return 0;
}
出力:
= 3, y = 5:x = 5, y = 3
💡 [ヒント]: [後ほど学習する]reference——[reference]を使って[swap]を実装すると[より簡潔]になる。
8. [よくある]エラー
(1) 8.1 [解]参照[未]初期化[された]ポインタ
#include iostream
int main() {
int* p; // ❌ (pointer)
std::cout << *p << std::endl; // ❌ Definebehavior!
return 0;
}
[修正]: [初期値を] nullptr に設定するか、[既存の]変数を指定してください。
(2) 8.2 pointertype[不一致]
#include iostream
int main() {
int x = 5;
double* p = &x; // ❌:int* int
return 0;
}
コンパイルエラー[詳細]:
error: cannot convert 'int*' to 'double*' in initialization
❓ よくある質問
nullptrを指すことができますが、参照[は初期化する必要があります] > - ポインタ[は他の]変数を指し直すことができますが、参照[は一度バインドされると変更できません] > - ポインタ[は] *p [を使って]参照を解除する必要がありますが、参照は[変数名を直接]使用できますQ:pointers basicsについて最も重要なことは何ですか? A:まず核心概念を理解し、その後実践的な例で練習することが重要です。
📖 まとめ
- ポインタ[は、]アドレス[を持つ]変数
- [声明]:
type* pointer[名]; - [取]住所:
&variable name - [解]出典:
*pointer[名] - ヌルポインタ:
nullptr - [決して]参照ヌルポインタ[または]ポインタ
📝 練習問題
-
初心者(難易度 ⭐): [1つ目を宣言]
int変数x = 10、[さらに1つ宣言]int*ポインタp[が指す先]x。出力x[の]値[と]*p[の]値。 -
中級(難易度 ⭐⭐): [関数]
void addTen(int* p)を [作成] し、[ポインタが] [指す] 変数に 10 を [加える]。main[内で] [テスト] する。 -
上級(難易度 ⭐⭐⭐): [1つの]プログラムを作成し、[3つの]
int変数a, b, cを宣言し、[さらに3つの]ポインタを[それぞれそれらを指すように]宣言する。[ポインタを介して]3つの変数の値をすべて100に変更し、[その後]出力する。
- ポインタ[は、メモリアドレスを格納する]変数
- & [取得]アドレス,* [取得]参照[が指す]値
- [宣言形式]:type* pointer[名](int* p;)
- ヌルポインタ nullptr(C++11)[代替] NULL
- ポインタ[同一のメモリ領域を指す]、[一方を変更すると他方も影響を受ける]
9. 🚀 次は
[ポインタの基礎]を学んだので、[次は] ポインタと配列([第]23[課])について学びます―― [配列]とは[ポインタ]の一種であることを理解し、[ポインタ演算]についても学びます。



