C++初心者でも理解できる!vector::eraseの使い方5選 – JPSM

C++初心者でも理解できる!vector::eraseの使い方5選

C++におけるvector::eraseの使い方を解説する記事のイメージC++

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

このサービスは複数のSSPによる協力の下、運営されています。

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

また、理解しにくい説明や難しい問題に躓いても、JPSMがプログラミングの解説に特化してオリジナルにチューニングした画面右下のAIアシスタントに質問していだければ、特殊な問題でも指示に従い解決できるように作ってあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

この記事では、C++の基本的なデータ構造であるベクター(vector)と、その中で非常に重要なメソッドであるvector::eraseについて詳しく解説します。

この記事を読むことで、初心者の方でもC++のベクター操作を理解し、vector::eraseメソッドを使いこなすことができるようになります。

●C++とvectorについての基本

C++は、システムプログラミングやアプリケーション開発に広く使われているプログラミング言語です。

高いパフォーマンスと柔軟性を持ち、オブジェクト指向プログラミングをサポートしています。

C++では、データを効率的に管理するために様々なデータ構造が利用されます。

その中でも、ベクターは動的配列を提供し、サイズが変更可能な配列として広く使われています。

○C++とは何か?

C++は、C言語をベースにオブジェクト指向機能を加えた言語で、複雑なプログラムや大規模なシステムの開発に適しています。

強力な型システム、クラスと継承、例外処理、テンプレートといった特徴を持ち、ソフトウェア開発において柔軟かつ強力な手段を提供します。

○vectorとは何か?

vectorは、C++の標準テンプレートライブラリ(STL)の一部として提供されているコンテナクラスです。

配列と似ていますが、サイズが動的に変更可能で、要素の追加や削除が容易です。

インデックスによる要素へのアクセス、イテレータを使った要素の走査など、多様な操作が可能です。

また、自動的にメモリ管理を行うため、使いやすく効率的なデータ構造として多くの開発者に採用されています。

●vector::eraseの基本

C++のvectorクラスにおけるeraseメソッドは、ベクターから特定の要素を削除するための重要な機能です。

このメソッドを使うことで、ベクター内の不要な要素を効率的に取り除き、コレクションのサイズを動的に調整することができます。

eraseメソッドは、ベクターの特定の位置にある要素を削除するだけでなく、指定された範囲の要素を一括で削除することも可能です。

これにより、プログラマはベクターをより柔軟に制御できるようになります。

○vector::eraseとは何か?

vector::eraseメソッドは、STL(Standard Template Library)の一部として提供されているメソッドです。

このメソッドの主な役割は、ベクターから一つまたは複数の要素を削除することです。

削除操作は、ベクターのイテレータを使用して行われます。

イテレータは、ベクター内の特定の位置を指すオブジェクトであり、eraseメソッドを使用する際には、削除したい要素の位置を指定するために使用されます。

○vector::eraseの基本的な構文

vector::eraseメソッドの基本的な構文は下記のとおりです。

iterator erase(iterator position);
iterator erase(iterator first, iterator last);
  • 最初の形式は、指定されたpositionにある単一の要素を削除します
  • 第二の形式では、firstlastの間にある範囲の要素(lastを含まず)を削除します

これらのメソッドは、削除された要素の次の要素を指すイテレータを返します。

これは、連続した削除操作を行う際に特に便利です。

また、eraseメソッドを使用すると、ベクターのサイズが自動的に更新され、削除された要素の分だけサイズが減少します。

●vector::eraseの使い方

vector::eraseメソッドの使い方を理解するために、実際のサンプルコードを通じてその使い方を学びましょう。

ここでは、特定の要素の削除、範囲指定による削除、条件に基づく削除という3つの異なる使い方を紹介します。

○サンプルコード1:特定の要素を削除する

まず、ベクターから特定の要素を削除する基本的な方法を見てみましょう。

下記のコードでは、ベクターから第3の要素(インデックス2)を削除しています。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {10, 20, 30, 40, 50};

    // インデックス2の要素を削除
    v.erase(v.begin() + 2);

    // 結果の表示
    for (int i : v) {
        std::cout << i << " ";
    }

    return 0;
}

このコードを実行すると、30が削除され、結果として10 20 40 50が出力されます。

eraseメソッドは、削除された要素の次の要素を指すイテレータを返すため、削除後のベクターの状態を確認することができます。

○サンプルコード2:範囲を指定して削除する

次に、ベクターの特定の範囲の要素を削除する方法です。

下記のコードでは、ベクターの第2の要素から第4の要素まで(インデックス1から3)を削除しています。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {10, 20, 30, 40, 50};

    // インデックス1から3までの要素を削除
    v.erase(v.begin() + 1, v.begin() + 4);

    // 結果の表示
    for (int i : v) {
        std::cout << i << " ";
    }

    return 0;
}

このコードを実行すると、20 30 40が削除され、結果として10 50が出力されます。

範囲を指定することで、一度に複数の要素を効率的に削除することができます。

○サンプルコード3:条件に基づいて削除する

最後に、条件に基づいてベクターから要素を削除する方法を見てみましょう。

この方法では、std::remove_if関数と組み合わせて使用します。

下記のコードでは、ベクターから偶数の要素を全て削除しています。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> v = {10, 21, 32, 43, 54, 65};

    // 偶数の要素を削除
    v.erase(std::remove_if(v.begin(), v.end(), [](int n){ return n % 2 == 0; }), v.end());

    // 結果の表示
    for (int i : v) {
        std::cout << i << " ";
    }

    return 0;
}

このコードを実行すると、10 32 54が削除され、結果として21 43 65が出力されます。

ラムダ式を使って削除条件を指定しています。

○サンプルコード4:削除後のイテレータを活用する

vector::eraseメソッドを使用する際、削除操作が完了した後のイテレータを受け取ることができます。

これは、削除後の要素にアクセスしたり、続けて別の操作を行う際に非常に便利です。

下記のサンプルコードでは、特定の要素を削除した後、その次の要素を表示しています。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {10, 20, 30, 40, 50};

    // 第3の要素を削除し、次の要素のイテレータを取得
    auto it = v.erase(v.begin() + 2);

    // 削除後の次の要素を表示
    if (it != v.end()) {
        std::cout << "次の要素: " << *it << std::endl;
    } else {
        std::cout << "要素はもうありません。" << std::endl;
    }

    return 0;
}

このコードでは、インデックス2の要素(値30)が削除された後、次の要素(値40)が出力されます。

削除によってイテレータが無効になることはなく、安全に続けて処理を行うことができます。

○サンプルコード5:複数のvectorでのeraseの使い分け

異なるタイプのvectoreraseを使う場合、それぞれのvectorの特性に合わせた使い方をすることが重要です。

例えば、下記のサンプルコードでは、整数型のvectorと文字列型のvectoreraseメソッドを使用しています。

#include <iostream>
#include <vector>
#include <string>

int main() {
    std::vector<int> v1 = {10, 20, 30, 40, 50};
    std::vector<std::string> v2 = {"Apple", "Banana", "Cherry", "Date"};

    // 整数型のvectorから要素を削除
    v1.erase(v1.begin() + 2);

    // 文字列型のvectorから要素を削除
    v2.erase(v2.begin() + 1);

    // 結果の表示
    std::cout << "整数型のvector: ";
    for (int i : v1) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    std::cout << "文字列型のvector: ";
    for (const auto& s : v2) {
        std::cout << s << " ";
    }
    std::cout << std::endl;

    return 0;
}

このコードでは、整数型のvectorからは値30が、文字列型のvectorからは”Banana”が削除されています。

それぞれのvectorの要素の型に応じて、eraseメソッドの使い方を適切に調整することが重要です。

●vector::eraseの応用例

vector::eraseメソッドは、基本的な使用方法だけでなく、さまざまな応用が可能です。

パフォーマンスを考慮した削除方法や、他のSTLコンテナとの連携など、具体的な応用例を見ていきましょう。

○サンプルコード6:パフォーマンスを考慮した削除方法

大きなデータセットを扱う場合、eraseメソッドの使用方法によってはパフォーマンスの問題が発生することがあります。

例えば、下記のコードは、条件に合致する要素を効率的に削除する方法を表しています。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // 値が5より大きい要素を全て削除
    v.erase(std::remove_if(v.begin(), v.end(), [](int n){ return n > 5; }), v.end());

    // 結果の表示
    for (int i : v) {
        std::cout << i << " ";
    }

    return 0;
}

このコードでは、remove_iferaseを組み合わせることで、一度に複数の要素を効率的に削除しています。

これにより、削除する要素の数に比例してパフォーマンスが向上します。

○サンプルコード7:他のSTLコンテナとの連携

vector::eraseは、他のSTLコンテナとも連携して使用することができます。

下記のサンプルコードでは、vectorlistを組み合わせた使い方を表しています。

#include <iostream>
#include <vector>
#include <list>

int main() {
    std::vector<int> v = {10, 20, 30, 40, 50};
    std::list<int> l = {15, 25, 35, 45, 55};

    // vectorの特定の要素を削除
    v.erase(v.begin() + 2);

    // listの特定の要素を削除
    auto it = l.begin();
    std::advance(it, 2);
    l.erase(it);

    // vectorの結果を表示
    std::cout << "vector: ";
    for (int i : v) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    // listの結果を表示
    std::cout << "list: ";
    for (int i : l) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}

このコードでは、vectorからはインデックス2の要素が、listからは3番目の要素が削除されています。

それぞれのコンテナの特性に合わせてeraseメソッドを使い分けることで、様々なデータ構造でのデータ操作が可能になります。

●注意点と対処法

vector::eraseを使用する際には、いくつかの注意点があります。

特に、イテレータの扱い、パフォーマンスへの影響、エラー処理の方法に注意を払う必要があります。

○削除時のイテレータの扱い

vector::eraseメソッドを使用すると、削除された要素以降のイテレータが無効になる可能性があります。

そのため、削除操作後はイテレータを更新する必要があります。

下記のサンプルコードでは、イテレータを正しく更新する方法を表しています。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {10, 20, 30, 40, 50};

    // イテレータを用いて要素を削除
    for (auto it = v.begin(); it != v.end(); ) {
        if (*it == 30) {
            it = v.erase(it);
        } else {
            ++it;
        }
    }

    // 結果の表示
    for (int i : v) {
        std::cout << i << " ";
    }

    return 0;
}

このコードでは、値が30の要素を削除しています。

削除後にeraseから返される新しいイテレータを使用してループを継続しています。

○パフォーマンスへの影響

vector::eraseは要素の削除に伴い、残りの要素をシフトする必要があるため、大きなベクターで多数の要素を削除する場合、パフォーマンスの問題が発生することがあります。

このような場合、必要な要素を別のコンテナにコピーした後、元のベクターをクリアして新しい要素を再度コピーするといった方法が効果的です。

○エラー処理の方法

vector::eraseを使用する際には、存在しない要素を指すイテレータを渡すとランタイムエラーが発生する可能性があります。

削除を行う前に、イテレータがベクターの有効な範囲を指していることを確認することが重要です。

例えば、下記のようにイテレータがベクターのendを超えていないことを確認します。

if (it != v.end()) {
    v.erase(it);
}

これらの注意点を考慮することで、vector::eraseを安全かつ効率的に使用することができます。

●カスタマイズ方法

vector::eraseメソッドは、様々なカスタマイズが可能です。

これにより、プログラマは特定の要件に合わせてeraseメソッドの動作を調整できます。

ここでは、独自の削除条件の作成と、vector以外のコンテナでの応用について見ていきます。

○独自の削除条件の作成

プログラムにおける特定の条件に基づいて要素を削除したい場合、ラムダ式やカスタム関数を用いて条件を指定することができます。

下記のサンプルコードでは、特定の条件を満たす要素のみをvectorから削除しています。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // 値が偶数の要素を削除
    v.erase(std::remove_if(v.begin(), v.end(), [](int n) { return n % 2 == 0; }), v.end());

    // 結果の表示
    for (int i : v) {
        std::cout << i << " ";
    }

    return 0;
}

このコードでは、ラムダ式を使って偶数の要素を削除しています。

この方法を用いることで、柔軟かつ効率的に特定の条件に基づく要素の削除が可能となります。

○vector以外のコンテナでの応用

vector::eraseメソッドはvector専用ですが、同様の削除機能は他のSTLコンテナにも存在します。

たとえば、listdequeなどのコンテナにも、イテレータを使用した削除メソッドがあります。

下記のサンプルコードでは、listコンテナでの要素削除を表しています。

#include <iostream>
#include <list>

int main() {
    std::list<int> l = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // 値が5より大きい要素を削除
    for (auto it = l.begin(); it != l.end(); ) {
        if (*it > 5) {
            it = l.erase(it);
        } else {
            ++it;
        }
    }

    // 結果の表示
    for (int i : l) {
        std::cout << i << " ";
    }

    return 0;
}

このコードでは、listから条件に合致する要素を効率的に削除しています。

vectorと異なり、listは要素の削除において要素のシフトが発生しないため、特定のシナリオではlistを使う方が効率的な場合があります。

まとめ

本記事では、C++のvector::eraseメソッドの基本的な使い方から応用例、注意点と対処法までを詳細に解説しました。

イテレータの正しい扱いや、パフォーマンスへの影響を考慮しつつ、独自の削除条件を作成することで、より柔軟にvectorの操作が可能になります。

この知識を活用して、C++プログラミングのスキルをさらに高めていきましょう。