演習:ポインタと参照
[これまでの講義では、]ポインタ[と]参照を[別々に]説明してきましたが、[実際の]プログラム[では、それらは][混在して][使われています]。
[このレッスンでは]、[いくつかの総合的な]例を通じて、[ポインタと]参照が[連携して動作する]方法を練習します。
1. インスタンス[一]:[用]ポインタ[実装]文字列[反転]*
▶ サンプル 1: string[反転] (難易度 ⭐⭐)
#include iostream
#include cstring
void reverseString(char* str) {
int len = std::strlen(str);
char* left = str;
char* right = str + len - 1;
while (left < right) {
// left right
char temp = *left;
*left = *right;
*right = temp;
left++;
right--;
}
}
int main() {
char str = "Hello, World!";
std::cout << ":" << str << std::endl;
reverseString(str);
std::cout << ":" << str << std::endl;
return 0;
}
出力:
World!:!dlroW ,olleH
2. インスタンス[二]:[動的]structarray*
▶ サンプル 2: [生徒の動的割り当て]array (難易度 ⭐⭐⭐)
#include iostream
#include string
struct Student {
std::string name;
int age;
double score;
};
int main() {
int n;
std::cout << ":";
std::cin >> n;
// points Student
Student* students = new Student[n];
// ...
for (int i = 0; i < n; i++) {
std::cout << "..." << i + 1 << ":";
std::cin.ignore();
std::getline(std::cin, students[i].name);
std::cout << ":";
std::cin >> students[i].age;
std::cout << ":";
std::cin >> students[i].score;
}
// output
std::cout << "\n========== ==========\n";
for (int i = 0; i < n; i++) {
std::cout << i + 1 << ". " << students[i].name
<< ",:" << students[i].age
<< ",:" << students[i].score << std::endl;
}
// ...
delete students;
return 0;
}
3. 例[三]:[リンクリストの基礎]([選択科目])*
(1) 3.1 [連結リスト]とは何か?
[連結リスト][は動的なデータ構造の一種]であり、[各要素]([ノード])には[データと、次のノードを指す]ポインタが格納されている。
| [生活シーン] | 番組[での対応] |
|---|---|
| [宝探しゲーム]([各紙片は次の紙片の位置を指し示している]) | [連結リスト] |
▶ サンプル 3: [簡単な連結リスト] (難易度 ⭐⭐⭐)
#include iostream
struct Node {
int data;
Node* next;
};
int main() {
// ...
Node* head = new Node{1, nullptr};
Node* second = new Node{2, nullptr};
Node* third = new Node{3, nullptr};
// ...
head->next = second;
second->next = third;
// ...
Node* current = head;
while (current != nullptr) {
std::cout << current->data << " ";
current = current->next;
}
std::cout << std::endl;
// ...
delete head;
delete second;
delete third;
return 0;
}
出力:
1 2 3
💡 [ヒント]: [リンクリストはデータ構造の重要な要素です]、[ここでは簡単に紹介するだけです]。[今後、さらに多くのデータ構造について学びます]。
4. 練習:[アドレス帳](動的メモリ版)*
▶ サンプル 4: [動的アドレス帳] (難易度 ⭐⭐⭐)
#include iostream
#include string
#include cstring
struct Contact {
char name[50];
char phone[20];
Contact* next; // ...
};
Contact* head = nullptr; // ...
void addContact(const std::string& name, const std::string& phone) {
Contact* newContact = new Contact;
std::strcpy(newContact->name, name.c_str());
std::strcpy(newContact->phone, phone.c_str());
newContact->next = head; // ...
head = newContact; // ...
}
void printContacts() {
if (head == nullptr) {
std::cout << "!" << std::endl;
return;
}
std::cout << "\n========== ==========\n";
Contact* current = head;
int index = 1;
while (current != nullptr) {
std::cout << index << ". " << current->name
<< " - " << current->phone << std::endl;
current = current->next;
index++;
}
}
int main() {
addContact("MOTO", "13800138000");
addContact("Alice", "13900139000");
addContact("Bob", "13700137000");
printContacts();
// ()
// ...
return 0;
}
❓ よくある質問
Q:[いつ]ポインタを使い、[いつ]参照を使うのか? A:> - [引数が][変更される可能性がある]場合、[かつ]" [変更されない]"([検索に失敗した場合など])→ ポインタ(
nullptr) > - [引数が][変更される可能性がある]が、[必ず]値がある場合 → 参照 > - [引数が][変更される必要がない]場合 → const参照([推奨]) > - [動的に]メモリを割り当てる必要がある場合 → ポインタ(new) Q:[なぜ連結リストは]配列[より優れている]のか? A:> - 配列:[サイズが固定]、[要素の挿入]/[削除には後続のすべての要素を移動させる必要がある]([遅い]) > - [連結リスト]:[サイズが動的]、[要素の挿入]/[削除にはポインタを変更するだけでよい]([速い])[しかし、リンクドリストには欠点もある]:[ランダムアクセスができない]([i番目の要素]を探すには、[先頭から順に走査しなければならない])。
Q:[どうすれば]メモリリークを回避できますか? A:> 1.
new[と]delete[がペアで出現するように] [確認する] > 2. [解放後すぐに]nullptrに設定する > 3. [スマートポインタ](std::unique_ptr、std::shared_ptr、[後ほど学習します])を使用する
Q:practice pointersについて最も重要なことは何ですか? A:まず核心概念を理解し、その後実践的な例で練習することが重要です。
📖 まとめ
- ポインタ[と]参照[は][併用可能]——参照[により]コード[が簡潔]になり、ポインタ[は]動的メモリ[の処理]に用いられる
- [ポインタ]を使用することで、[動的データ構造]([連結リスト]、[木]、[グラフ]など)を実現できる
- [動的割り当て]されたメモリは、[必ず解放することを忘れないでください](
delete) - [連結リストは][動的データ構造][の基礎]
📝 練習問題
-
初心者(難易度 ⭐): [関数]
void swap(int* a, int* b)を [作成]し、[ポインタ] を使って [2つの] 変数の [値を] 入れ替える。 -
中級(難易度 ⭐⭐): [プログラム]を作成し、[動的メモリ][を使用して]
int配列を[割り当て]、[ユーザーに]配列の[サイズと内容]を入力させ、[その後、配列を逆順にして]出力する。 -
上級(難易度 ⭐⭐⭐): [拡張]「[動的アドレス帳]」プログラム:
-
- [追加]「[連絡先を削除]」「[機能]」
-
- [追加]「[連絡先を検索]」[機能]
-
- プログラム[終了時に動的に割り当てられたすべての]メモリを解放する
-
ポインタ関数[引数]:[外部の]変数[の]値を変更する
-
[動的]配列:実行時[サイズ確定]、[使用後に解放]
-
関数[戻り値]ポインタ[が]メモリ[が解放されないよう]確保する必要がある
-
参照渡し[比]ポインタ[構文がより簡潔]
-
nullptr [チェックによる回避策] 参照ヌルポインタ
5. 🚀 次は
[おめでとう]!フェーズ4(ポインタ[と]参照)の[すべてのレッスンを修了しました]。 [次に] フェーズ5(オブジェクト指向[プログラミング])に進みます――C++の[最も重要な特徴]を[学び]、class、object、継承、多態性を[理解]しましょう!



