vector

[C++] vectorの使い方について詳しく解説

C++のvectorは、動的配列を提供するSTL(標準テンプレートライブラリ)のコンテナです。

サイズが自動的に調整され、要素の追加や削除が容易です。

イテレータを使って要素を操作することもできます。

vectorとは何か

C++のvectorは、標準テンプレートライブラリ(STL)の一部であり、動的配列を実現するためのコンテナです。

vectorは、要素の追加や削除が容易で、サイズが自動的に調整されるため、メモリ管理が簡単です。

以下に、vectorの主な特徴を示します。

特徴説明
動的サイズ要素の追加や削除に応じてサイズが変化する
ランダムアクセスインデックスを使用して要素にアクセス可能
メモリ管理自動的にメモリを管理し、必要に応じて再割り当てを行う
STLとの互換性他のSTLアルゴリズムやコンテナと組み合わせて使用可能

vectorは、特に要素数が不明な場合や、頻繁に要素の追加・削除が行われる場合に非常に便利です。

次のセクションでは、vectorの基本操作について詳しく解説します。

vectorの基本操作

vectorの基本操作には、要素の追加、削除、アクセス、サイズの取得などがあります。

以下に、これらの操作を示すサンプルコードを紹介します。

#include <iostream>
#include <vector>
int main() {
    // vectorの宣言
    std::vector<int> numbers;
    // 要素の追加
    numbers.push_back(10); // 10を追加
    numbers.push_back(20); // 20を追加
    numbers.push_back(30); // 30を追加
    // 要素へのアクセス
    std::cout << "最初の要素: " << numbers[0] << std::endl; // 10を表示
    std::cout << "2番目の要素: " << numbers.at(1) << std::endl; // 20を表示
    // サイズの取得
    std::cout << "要素の数: " << numbers.size() << std::endl; // 3を表示
    // 要素の削除
    numbers.pop_back(); // 最後の要素を削除
    // 削除後のサイズの取得
    std::cout << "削除後の要素の数: " << numbers.size() << std::endl; // 2を表示
    return 0;
}
最初の要素: 10
2番目の要素: 20
要素の数: 3
削除後の要素の数: 2

基本操作の解説

  • 要素の追加: push_backメソッドを使用して、vectorの末尾に要素を追加します。
  • 要素へのアクセス: インデックス演算子[]atメソッドを使用して、特定の要素にアクセスできます。

atメソッドは範囲外アクセス時に例外を投げるため、安全性が高いです。

  • サイズの取得: sizeメソッドを使用して、現在の要素数を取得できます。
  • 要素の削除: pop_backメソッドを使用して、vectorの末尾の要素を削除します。

これらの基本操作を理解することで、vectorを効果的に活用できるようになります。

次のセクションでは、vectorの応用操作について解説します。

vectorの応用操作

vectorは基本操作に加えて、さまざまな応用操作が可能です。

ここでは、要素の挿入、削除、ソート、検索、クリアなどの操作を紹介します。

以下にサンプルコードを示します。

#include <iostream>
#include <vector>
#include <algorithm> // sort関数を使用するために必要
int main() {
    // vectorの宣言と初期化
    std::vector<int> numbers = {30, 10, 20, 50, 40};
    // 要素の挿入
    numbers.insert(numbers.begin() + 2, 25); // インデックス2に25を挿入
    // 要素の削除
    numbers.erase(numbers.begin() + 1); // インデックス1の要素を削除
    // ソート
    std::sort(numbers.begin(), numbers.end()); // 昇順にソート
    // 検索
    auto it = std::find(numbers.begin(), numbers.end(), 25); // 25を検索
    if (it != numbers.end()) {
        std::cout << "25は見つかりました。" << std::endl;
    } else {
        std::cout << "25は見つかりませんでした。" << std::endl;
    }
    // vectorの内容を表示
    std::cout << "vectorの内容: ";
    for (const auto& num : numbers) {
        std::cout << num << " "; // 各要素を表示
    }
    std::cout << std::endl;
    // vectorのクリア
    numbers.clear(); // すべての要素を削除
    // クリア後のサイズの取得
    std::cout << "クリア後の要素の数: " << numbers.size() << std::endl; // 0を表示
    return 0;
}
25は見つかりました。
vectorの内容: 10 25 20 30 40 50 
クリア後の要素の数: 0

応用操作の解説

  • 要素の挿入: insertメソッドを使用して、指定した位置に要素を挿入できます。

位置はイテレータで指定します。

  • 要素の削除: eraseメソッドを使用して、指定した位置の要素を削除できます。
  • ソート: std::sort関数を使用して、vectorの要素を昇順または降順にソートできます。
  • 検索: std::find関数を使用して、特定の要素を検索できます。

見つかった場合は、そのイテレータが返されます。

  • クリア: clearメソッドを使用して、vector内のすべての要素を削除できます。

クリア後はサイズが0になります。

これらの応用操作を活用することで、vectorをさらに効果的に利用できるようになります。

次のセクションでは、vectorのパフォーマンスと注意点について解説します。

vectorのパフォーマンスと注意点

vectorは非常に便利なコンテナですが、使用する際にはパフォーマンスや注意点を理解しておくことが重要です。

以下に、vectorのパフォーマンス特性と注意すべき点を示します。

パフォーマンス特性

操作平均時間計算説明
要素の追加O(1)push_backで末尾に追加する場合、平均的には定数時間で済む。
要素の削除O(1)pop_backで末尾の要素を削除する場合、定数時間で済む。
要素の挿入O(n)中間に要素を挿入する場合、後ろの要素を移動させる必要があるため、線形時間がかかる。
要素へのアクセスO(1)インデックスを使用したアクセスは定数時間で行える。
ソートO(n log n)std::sortを使用する場合、平均的にはO(n log n)の時間がかかる。

注意点

  1. メモリの再割り当て: vectorは動的にサイズを変更しますが、要素数が増加すると、内部の配列が再割り当てされることがあります。

この際、既存の要素が新しいメモリにコピーされるため、パフォーマンスが低下する可能性があります。

予めreserveメソッドを使用して、必要なサイズを確保しておくと良いでしょう。

  1. イテレータの無効化: vectorの要素を追加・削除すると、イテレータが無効になることがあります。

特に、inserteraseを使用した場合、影響を受ける可能性があるため、注意が必要です。

  1. メモリ使用量: vectorは、要素数が増えるとメモリを再割り当てするため、メモリの使用量が増加します。

特に、大量のデータを扱う場合は、メモリの効率を考慮する必要があります。

  1. スレッドセーフではない: vectorは、複数のスレッドから同時にアクセスされる場合、スレッドセーフではありません。

スレッド間でのデータ競合を避けるために、適切な同期機構を使用する必要があります。

これらのパフォーマンス特性と注意点を理解することで、vectorをより効果的に活用し、プログラムの効率を向上させることができます。

次のセクションでは、他のSTLコンテナとの比較について解説します。

他のSTLコンテナとの比較

C++の標準テンプレートライブラリ(STL)には、vector以外にもさまざまなコンテナが存在します。

ここでは、vectorと他の主要なSTLコンテナであるlistdequesetmapとの比較を行います。

各コンテナの特性を理解することで、適切なコンテナを選択する助けになります。

コンテナの比較表

コンテナ名特徴使用例
vector動的配列。ランダムアクセスが高速。要素数が不明な場合や、頻繁に追加・削除が行われる場合。
list双方向リスト。要素の挿入・削除が高速。頻繁に要素の挿入・削除が行われる場合。
deque両端キュー。両端からの追加・削除が高速。両端からの操作が多い場合。
set重複を許さない集合。自動的にソートされる。一意な要素を保持したい場合。
mapキーと値のペアを保持する連想配列。キーに基づいて値を検索したい場合。

各コンテナの詳細

  • vector:
  • メモリを連続的に確保するため、ランダムアクセスが非常に高速です。

要素の追加は末尾でO(1)ですが、中間に挿入する場合はO(n)かかります。

サイズが変更されると、メモリの再割り当てが発生することがあります。

  • list:
  • 要素の挿入や削除がO(1)で行えるため、頻繁に要素を追加・削除する場合に適しています。

ただし、ランダムアクセスはO(n)かかるため、インデックスを使用したアクセスには向いていません。

  • deque:
  • 両端からの要素の追加・削除がO(1)で行えるため、キューやスタックとして使用するのに適しています。

vectorと同様にランダムアクセスも可能ですが、メモリの管理が異なります。

  • set:
  • 自動的にソートされ、重複を許さない集合です。

要素の追加、削除、検索はO(log n)で行えます。

順序を保ちながら一意な要素を管理したい場合に便利です。

  • map:
  • キーと値のペアを保持する連想配列で、キーに基づいて値を効率的に検索できます。

要素の追加、削除、検索はO(log n)で行えます。

キーの重複を許さないため、一意なキーでデータを管理したい場合に適しています。

これらのコンテナの特性を理解し、用途に応じて適切なコンテナを選択することで、プログラムの効率を向上させることができます。

まとめ

この記事では、C++のvectorについて、その基本的な使い方から応用操作、パフォーマンス特性、他のSTLコンテナとの比較まで幅広く解説しました。

vectorは動的配列として非常に便利で、特に要素の追加や削除が頻繁に行われる場合に適していますが、使用する際にはその特性や注意点を考慮することが重要です。

今後は、実際のプログラムでvectorを活用し、さまざまなデータ構造との違いを体験してみてください。

関連記事

Back to top button