[C++] vectorへの要素追加と削除の方法

C++のvectorに要素を追加するには、push_back()メソッドを使用します。

これは、指定した要素をベクターの末尾に追加します。

また、emplace_back()を使うと、要素を直接構築しながら追加できます。

要素を削除するには、pop_back()メソッドを使用して末尾の要素を削除します。

特定の位置の要素を削除するには、erase()メソッドを使います。

erase()は、イテレータを引数に取り、その位置の要素を削除します。

範囲を指定して削除することも可能です。

clear()メソッドを使うと、ベクター内のすべての要素を削除できます。

この記事でわかること
  • vectorへの要素追加方法として、push_back()、emplace_back()、insert()の使い方
  • vectorからの要素削除方法として、pop_back()、erase()、clear()の使い方
  • 要素追加と削除に伴うメモリ再配置やイテレータの無効化についての注意点
  • vectorを動的配列、スタック、キューとして応用する方法

目次から探す

vectorへの要素追加方法

C++のstd::vectorは、動的配列として非常に便利なコンテナです。

ここでは、vectorに要素を追加するためのさまざまな方法について解説します。

push_back()メソッドの使い方

push_back()メソッドは、vectorの末尾に新しい要素を追加するための最も基本的な方法です。

#include <iostream>
#include <vector>
int main() {
    std::vector<int> numbers; // 整数型のvectorを宣言
    numbers.push_back(10); // 10を追加
    numbers.push_back(20); // 20を追加
    numbers.push_back(30); // 30を追加
    for (int num : numbers) {
        std::cout << num << " "; // 各要素を出力
    }
    return 0;
}
10 20 30

push_back()は、要素を追加するたびにvectorのサイズを自動的に増やします。

これにより、手動でサイズを管理する必要がありません。

emplace_back()メソッドの使い方

emplace_back()メソッドは、push_back()と似ていますが、オブジェクトを直接構築するための引数を受け取ることができます。

これにより、オブジェクトのコピーを避けることができ、パフォーマンスが向上する場合があります。

#include <iostream>
#include <vector>
#include <string>
int main() {
    std::vector<std::string> words; // 文字列型のvectorを宣言
    words.emplace_back("こんにちは"); // "こんにちは"を追加
    words.emplace_back("世界");     // "世界"を追加
    for (const std::string& word : words) {
        std::cout << word << " "; // 各要素を出力
    }
    return 0;
}
こんにちは 世界

emplace_back()は、コンストラクタの引数を直接渡すことができるため、オブジェクトの構築が効率的に行われます。

insert()メソッドでの要素追加

insert()メソッドは、vectorの任意の位置に要素を追加することができます。

これにより、特定の位置に要素を挿入することが可能です。

#include <iostream>
#include <vector>
int main() {
    std::vector<int> numbers = {10, 20, 30}; // 初期化されたvector
    auto it = numbers.begin(); // イテレータを取得
    numbers.insert(it + 1, 15); // 2番目の位置に15を挿入
    for (int num : numbers) {
        std::cout << num << " "; // 各要素を出力
    }
    return 0;
}
10 15 20 30

insert()を使用すると、指定した位置に要素を挿入でき、既存の要素は後ろにシフトされます。

reserve()メソッドでの容量確保

reserve()メソッドは、vectorの容量を事前に確保するために使用されます。

これにより、要素追加時のメモリ再配置を減らし、パフォーマンスを向上させることができます。

#include <iostream>
#include <vector>
int main() {
    std::vector<int> numbers; // 整数型のvectorを宣言
    numbers.reserve(5); // 5つの要素分の容量を確保
    numbers.push_back(10); // 10を追加
    numbers.push_back(20); // 20を追加
    std::cout << "容量: " << numbers.capacity() << std::endl; // 現在の容量を出力
    return 0;
}
容量: 5

reserve()を使用することで、vectorの容量を事前に設定し、頻繁なメモリ再配置を避けることができます。

これにより、特に大量の要素を追加する場合にパフォーマンスが向上します。

vectorからの要素削除方法

C++のstd::vectorでは、要素を削除するためのさまざまな方法が用意されています。

ここでは、vectorから要素を削除するための基本的なメソッドについて解説します。

pop_back()メソッドの使い方

pop_back()メソッドは、vectorの末尾にある要素を削除します。

このメソッドは、削除する要素を指定する必要がないため、最も簡単な削除方法の一つです。

#include <iostream>
#include <vector>
int main() {
    std::vector<int> numbers = {10, 20, 30}; // 初期化されたvector
    numbers.pop_back(); // 末尾の要素を削除
    for (int num : numbers) {
        std::cout << num << " "; // 各要素を出力
    }
    return 0;
}
10 20

pop_back()は、vectorの末尾の要素を削除するため、サイズが1減少しますが、容量は変わりません。

erase()メソッドでの要素削除

erase()メソッドは、vectorの任意の位置にある要素を削除することができます。

これにより、特定の要素や範囲を削除することが可能です。

単一要素の削除

単一の要素を削除する場合、削除したい要素のイテレータを指定します。

#include <iostream>
#include <vector>
int main() {
    std::vector<int> numbers = {10, 20, 30, 40}; // 初期化されたvector
    auto it = numbers.begin(); // イテレータを取得
    numbers.erase(it + 1); // 2番目の要素を削除
    for (int num : numbers) {
        std::cout << num << " "; // 各要素を出力
    }
    return 0;
}
10 30 40

erase()を使用すると、指定した位置の要素が削除され、後続の要素が前にシフトされます。

範囲指定での削除

範囲を指定して削除する場合、開始位置と終了位置のイテレータを指定します。

#include <iostream>
#include <vector>
int main() {
    std::vector<int> numbers = {10, 20, 30, 40, 50}; // 初期化されたvector
    auto start = numbers.begin() + 1; // 開始位置のイテレータ
    auto end = numbers.begin() + 4;   // 終了位置のイテレータ
    numbers.erase(start, end); // 2番目から4番目の要素を削除
    for (int num : numbers) {
        std::cout << num << " "; // 各要素を出力
    }
    return 0;
}
10 50

範囲指定でerase()を使用すると、指定した範囲内の要素がすべて削除されます。

clear()メソッドでの全要素削除

clear()メソッドは、vector内のすべての要素を削除します。

これにより、vectorは空になりますが、容量はそのまま保持されます。

#include <iostream>
#include <vector>
int main() {
    std::vector<int> numbers = {10, 20, 30}; // 初期化されたvector
    numbers.clear(); // 全要素を削除
    std::cout << "サイズ: " << numbers.size() << std::endl; // 現在のサイズを出力
    return 0;
}
サイズ: 0

clear()を使用すると、vectorのサイズが0になり、すべての要素が削除されますが、メモリの容量は解放されません。

vectorの要素追加と削除の注意点

C++のstd::vectorは便利なコンテナですが、要素の追加や削除に伴ういくつかの注意点があります。

これらを理解することで、より効率的にvectorを使用することができます。

メモリ再配置の影響

vectorは動的にサイズを変更できるため、要素を追加する際にメモリの再配置が発生することがあります。

再配置が発生すると、以下のような影響があります。

  • パフォーマンスの低下: 再配置は新しいメモリ領域を確保し、既存の要素をコピーするため、時間がかかります。
  • ポインタやイテレータの無効化: 再配置が発生すると、以前のメモリ領域に対するポインタやイテレータは無効になります。

再配置を最小限に抑えるためには、reserve()メソッドを使用して事前に必要な容量を確保することが推奨されます。

イテレータの無効化

vectorの要素を追加または削除すると、イテレータが無効化されることがあります。

特に、以下の操作でイテレータが無効化される可能性があります。

  • 要素の追加: push_back()insert()で再配置が発生した場合、すべてのイテレータが無効になります。
  • 要素の削除: erase()pop_back()を使用すると、削除された要素以降のイテレータが無効になります。

無効化されたイテレータを使用すると、未定義の動作を引き起こす可能性があるため、イテレータを再取得することが重要です。

パフォーマンスへの影響

vectorの要素追加と削除は、パフォーマンスに影響を与えることがあります。

以下の点に注意することで、パフォーマンスを最適化できます。

  • 追加時の再配置: 頻繁な再配置を避けるために、reserve()を使用して必要な容量を事前に確保します。
  • 削除時のシフト操作: erase()で要素を削除すると、後続の要素がシフトされるため、削除操作が多い場合はstd::listなどの他のコンテナを検討することも一案です。
  • メモリの効率的な使用: shrink_to_fit()メソッドを使用して、不要なメモリを解放することができますが、これは必ずしもメモリを解放することを保証するものではありません。

これらの注意点を理解し、適切に対処することで、vectorをより効率的に使用することができます。

vectorの応用例

C++のstd::vectorは、柔軟で強力なコンテナであり、さまざまな用途に応用することができます。

ここでは、vectorの代表的な応用例について解説します。

動的配列としての利用

vectorは、動的にサイズを変更できる配列として利用できます。

配列のサイズが事前にわからない場合や、要素の追加・削除が頻繁に行われる場合に便利です。

#include <iostream>
#include <vector>
int main() {
    std::vector<int> numbers; // 動的配列としてのvector
    for (int i = 0; i < 5; ++i) {
        numbers.push_back(i * 10); // 要素を追加
    }
    for (int num : numbers) {
        std::cout << num << " "; // 各要素を出力
    }
    return 0;
}
0 10 20 30 40

この例では、vectorを動的配列として使用し、要素を追加しています。

vectorはサイズを自動的に調整するため、配列のサイズを事前に決定する必要がありません。

スタックとしての利用

vectorは、LIFO(Last In, First Out)構造のスタックとしても利用できます。

push_back()で要素を追加し、pop_back()で要素を削除することで、スタックの操作を実現できます。

#include <iostream>
#include <vector>
int main() {
    std::vector<int> stack; // スタックとしてのvector
    stack.push_back(10); // 要素を追加
    stack.push_back(20);
    stack.push_back(30);
    while (!stack.empty()) {
        std::cout << stack.back() << " "; // 末尾の要素を出力
        stack.pop_back(); // 末尾の要素を削除
    }
    return 0;
}
30 20 10

この例では、vectorをスタックとして使用し、要素を追加および削除しています。

back()メソッドで末尾の要素を取得し、pop_back()で削除することで、スタックの動作を模倣しています。

キューとしての利用

vectorは、FIFO(First In, First Out)構造のキューとしても利用できます。

push_back()で要素を追加し、erase()で先頭の要素を削除することで、キューの操作を実現できます。

#include <iostream>
#include <vector>
int main() {
    std::vector<int> queue; // キューとしてのvector
    queue.push_back(10); // 要素を追加
    queue.push_back(20);
    queue.push_back(30);
    while (!queue.empty()) {
        std::cout << queue.front() << " "; // 先頭の要素を出力
        queue.erase(queue.begin()); // 先頭の要素を削除
    }
    return 0;
}
10 20 30

この例では、vectorをキューとして使用し、要素を追加および削除しています。

front()メソッドで先頭の要素を取得し、erase()で削除することで、キューの動作を模倣しています。

これらの応用例を通じて、vectorの柔軟性と多様な用途を理解することができます。

用途に応じて適切な操作を選択することで、効率的なプログラムを作成することが可能です。

よくある質問

vectorのサイズと容量の違いは?

vectorのサイズと容量は、異なる概念です。

サイズは、vectorに現在格納されている要素の数を示します。

一方、容量は、再配置なしでvectorが格納できる要素の最大数を示します。

サイズはsize()メソッドで取得でき、容量はcapacity()メソッドで取得できます。

容量はサイズ以上であり、要素が追加されると自動的に増加することがあります。

vectorの要素を削除するときの注意点は?

vectorの要素を削除する際には、いくつかの注意点があります。

まず、erase()pop_back()を使用すると、削除された要素以降のイテレータが無効化されるため、削除後にイテレータを再取得する必要があります。

また、erase()で要素を削除すると、後続の要素が前にシフトされるため、削除操作が多い場合はパフォーマンスに影響を与える可能性があります。

頻繁な削除が必要な場合は、std::listなどの他のコンテナを検討することも一案です。

vectorの要素追加でエラーが発生する原因は?

vectorに要素を追加する際にエラーが発生する原因として、以下の点が考えられます。

  • メモリ不足: システムのメモリが不足している場合、vectorの容量を増やすことができず、エラーが発生することがあります。
  • イテレータの無効化: 再配置が発生した場合、以前のイテレータが無効化され、無効なイテレータを使用するとエラーが発生することがあります。
  • 例外処理の不足: vectorの操作中に例外が発生した場合、適切に例外処理を行わないとエラーが発生することがあります。

例外処理を適切に実装することで、エラーを防ぐことができます。

これらの原因を理解し、適切に対処することで、vectorの要素追加時のエラーを防ぐことができます。

まとめ

この記事では、C++のstd::vectorにおける要素の追加と削除の方法について詳しく解説しました。

vectorの基本的な操作から応用例までを通じて、その柔軟性と利便性を確認できたことでしょう。

これを機に、vectorを活用したプログラムを実際に作成し、さらなるスキルアップを目指してみてください。

  • URLをコピーしました!
目次から探す