C++: 練習:ポインタと参照

最終更新:2026-08-31

これまでポインタと参照を学びましたが、実際のプログラムでは組み合わせて使うことが多いです。

このレッスンでは、総合的な実例でポインタと参照を練習します。


1. 実践例:ポインタで文字列を反転

▶ サンプル 1:文字列の反転(難易度 ⭐⭐)

CPP
#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;
}
▶ 試してみよう

出力:

TEXT 📖 参照専用
反転前:Hello, World!
反転後:!dlroW ,olleH


2. 実践例:動的な構造体配列

▶ サンプル 2:動的配列(難易度 ⭐⭐⭐)

CPP
#include <iostream>
#include <string>

struct Student {
    std::string name;
    int age;
    double score;
};

int main() {
    int n;
    std::cout << "学生数を入力:";
    std::cin >> n;
    
    // 動的にn個の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;
    }
    
    // 出力
    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. 実践例:連結リスト(LinkedList)

(1) 3.1 連結リストとは?

連結リストは動的なデータ構造 —— 要素(ノード)と次の要素へのポインタで構成。

特徴 プログラムでの意味
動的なサイズ変更(実行時) 連結リスト

▶ サンプル 3:単方向連結リスト(難易度 ⭐⭐⭐)

CPP
#include <iostream>

struct Node {
    int data;
    Node* next;
};

int main() {
    // 3つのノードを作成
    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;
}
▶ 試してみよう

出力:

TEXT 📖 参照専用
1 2 3
💡 ヒント: 連結リストの操作は、単純なようで実はバグが起きやすい。注意深く実装。



4. 練習:アドレス帳(動的メモリ)

▶ サンプル 4:動的アドレス帳(難易度 ⭐⭐⭐)

CPP
#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

  1. newdelete を必ずペアで書く
  2. 解放後は nullptr を代入
  3. スマートポインタ

📖 まとめ

  • ポインタと参照は組み合わせて使う —— 参照はコードを簡潔に、ポインタは動的メモリに
  • ポインタで動的データ構造を実装(連結リスト、ツリー、グラフ)
  • 動的メモリは必ず解放delete
  • 連結リストは動的なサイズのデータ構造

📝 練習問題

  1. 初級(難易度 ⭐): 関数 void swap(int* a, int* b) を書いてください。ポインタで変数の値を交換。

  2. 中級(難易度 ⭐⭐): プログラムを書いてください。動的メモリで int 配列を確保し、ユーザー入力で配列に値を入れ、配列を反転して出力。

  3. 上級(難易度 ⭐⭐⭐): 「動的アドレス帳」プログラムを完成:

    • 「削除」機能を追加
    • 「検索」機能を追加
    • プログラム終了時に動的メモリをすべて解放


5. 🚀 次のステップ

おめでとう!フェーズ4(ポインタと参照)の学習が完了しました。 次は フェーズ5(オブジェクト指向プログラミング) —— C++の中核、クラスオブジェクト継承ポリモーフィズムを学ぼう!

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%