std::vector を試してみます。
ja.cppreference.com に記載されているサンプルプログラムから作成してみます。
push_back() を使う例です。
https://ja.cppreference.com/w/cpp/container/vector
void push_back( const T& value ); | (1) |
void push_back( T&& value ); | (2)(c++11以上) |
指定された要素 value をコンテナの終端に追加します。
(1) 新しい要素は value のコピーとして初期化されます。
(2) value
が新しい要素にムーブされます。
新しい size() が capacity() より大きい場合は、すべてのイテレータおよび参照(終端イテレータを含む)が無効化されます。そうでなければ、終端イテレータのみが無効化されます。
value | - | 追加する要素の値 |
(なし) |
コンパイラ : | Visual Studio 2019 pro., | Version 16.7.0 |
OS: | Windows10 home, | Version 1909 |
#include <iostream> #include <vector> int main() { // Create a vector containing integers std::vector<int> v = {7, 5, 16, 8}; // Add two more integers to vector v.push_back(25); v.push_back(13); // Iterate and print values of vector for(int n : v) { std::cout << n << '\n'; } }
7 5 16 8 25 13
同じく ja.cppreference.com に記載されているサンプルプログラムから insert() による要素の挿入を行うサンプルを作成してみます。
https://ja.cppreference.com/w/cpp/container/vector/insert
iterator insert( iterator pos, const T& value ); | (1) (c++11 未満) |
iterator insert( const_iterator pos, const T& value ); | (2) (c++11 以上) |
iterator insert( const_iterator pos, const T&& value ); | (3) (c++11 以上) |
void insert( iterator pos, size_type count, const T& value ); | (4) (c++11 未満) |
iterator insert( const_iterator pos, size_type count, const T& value ); | (5) (c++11 以上) |
template< class InputIt > void insert( const_iterator pos, InputIt first, InputIt last ); |
(6) (c++11 未満) |
template< class InputIt > iterator insert( const_iterator pos, InputIt first, InputIt last ); |
(7) (c++11 以上) |
iterator insert( const_iterator pos, std::initializer_list<T> ilist ); | (8) (c++11 以上) |
コンテナ内の指定された位置に要素を挿入します。
(1-3) pos の前に value を挿入します。
(4-5) pos の前に value
のコピーを count 個挿入します。
(6-7) pos の前に範囲 [first, last] から要素を挿入します。
(8) pos
の前に初期化子リスト ilist から要素を挿入します。
新しい size() が capacity() より大きい場合は再確保が発生し、すべてのイテレータおよび参照(終端イテレータを含む)が無効化されます。そうでなければ、終端イテレータのみが無効化されます。
pos | - | 前に内容が挿入されるイテレータ。pos は end() イテレータでも構いません。 |
value | - | 挿入する要素の値 |
first, last | - | 挿入する要素の範囲。insert が呼ばれたコンテナ内を示すイテレータは使用できません。 |
ilist | - | 挿入する値の初期化子リスト |
挿入された value を指すイテレータ。 | (1-3) |
挿入された 最初の要素を指すイテレータ、または count==0 の場合は pos。 | (4-5) |
挿入された 最初の要素を指すイテレータ、または first==last の場合は pos。 | (6-7) |
挿入された 最初の要素を指すイテレータ、または ilist が空の場合は pos。 | (8) |
コンパイラ : | Visual Studio 2019 pro., | Version 16.7.0 |
OS: | Windows10 home, | Version 1909 |
#include <iostream> #include <vector> void print_vec(const std::vector<int>& vec) { for (auto x : vec) { std::cout << ' ' << x; } std::cout << '\n'; } int main() { std::vector<int> vec(3, 100); print_vec(vec); auto it = vec.begin(); it = vec.insert(it, 200); print_vec(vec); vec.insert(it, 2, 300); print_vec(vec); // "it" no longer valid, get a new one: it = vec.begin(); std::vector<int> vec2(2, 400); vec.insert(it + 2, vec2.begin(), vec2.end()); print_vec(vec); int arr[] = { 501,502,503 }; vec.insert(vec.begin(), arr, arr + 3); print_vec(vec); }
100 100 100 200 100 100 100 300 300 200 100 100 100 300 300 400 400 200 100 100 100 501 502 503 300 300 400 400 200 100 100 100
emplace_back を使った要素を挿入する例を示します。
emplace_back, emplace_front は c++11 以降で使用可能です。
push_back
を使用したときに必要なコピーやムーブを回避するために、どのように emplace_back を使用すれば良いかを示します。
template< class... Args > void emplace_back( Args&&... args ); |
(1)(c++11以上) |
template< class... Args > reference emplace_back( Args&&... args ); |
(2)(c++17以上) |
コンテナの終端に新しい要素を追加します。
新しい size() が capacity()
より大きい場合は再確保が発生し、すべてのイテレータおよび参照(終端イテレータを含む)が無効化されます。そうでなければ、終端イテレータのみが無効化されます。
args | - | 要素のコンストラクタに転送される引数 |
(なし) | (1)(c++11以上) |
挿入された要素を示す参照 | (2)(c++17以上) |
コンパイラ : | Visual Studio 2019 pro., | Version 16.7.0 |
OS: | Windows10 home, | Version 1909 |
#include <iostream>
#include <vector>
#include <string>
struct President
{
std::string name;
std::string country;
int year;
President(std::string p_name, std::string p_country, int p_year)
: name(std::move(p_name)), country(std::move(p_country)), year(p_year)
{
std::cout << "I am being constructed.\n";
}
President(President&& other) noexcept
: name(std::move(other.name)), country(std::move(other.country)), year(other.year)
{
std::cout << "I am being moved.\n";
}
President& operator=(const President& other) = default;
};
std::ostream& operator << (std::ostream& os, const President& president)
{
os << president.name << ", " << president.country << ", " << president.year;
return os;
}
int main()
{
std::vector<President> elections;
std::cout << "emplace_back:\n";
elections.emplace_back("Nelson Mandela", "South Africa", 1994);
std::vector<President> reElections;
std::cout << "\npush_back:\n";
reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936));
std::cout << "\nElections:" << std::endl;
for (auto const& president : elections) {
std::cout << president << std::endl;
}
std::cout << "\nRe-Elections:" << std::endl;
for (auto const& president : reElections) {
std::cout << president << std::endl;
}
std::cout << "\nContents:\n";
for (President const& president : elections) {
std::cout << president.name << " was elected president of "
<< president.country << " in " << president.year << ".\n";
}
for (President const& president : reElections) {
std::cout << president.name << " was re-elected president of "
<< president.country << " in " << president.year << ".\n";
}
}
emplace_back:
I am being constructed.
push_back:
I am being constructed.
I am being moved.
Elections:
Nelson Mandela, South Africa, 1994
Re-Elections:
Franklin Delano Roosevelt, the USA, 1936
Contents:
Nelson Mandela was elected president of South Africa in 1994.
Franklin Delano Roosevelt was re-elected president of the USA in 1936.
emplace を使った要素を挿入する例を示します。
template< class... Args > iterator emplace( const_iterator pos, Args&&... args ); |
(c++11以上) |
新しい要素を pos の前に直接挿入します。
c++11 以降で使用可能です。
pos | - | 前に新しい要素が構築されるイテレータ |
args | - | 要素のコンストラクタに転送される引数 |
挿入された要素を指すイテレータ。 |
コンパイラ : | Visual Studio 2019 pro., | Version 16.7.0 |
OS: | Windows10 home, | Version 1909 |
#include <iostream> #include <vector> #include <string> struct President { std::string name; std::string country; int year; President(std::string p_name, std::string p_country, int p_year) : name(std::move(p_name)), country(std::move(p_country)), year(p_year) { std::cout << "I am being constructed.\n"; } President(President&& other) noexcept : name(std::move(other.name)), country(std::move(other.country)), year(other.year) { std::cout << "I am being moved.\n"; } President& operator=(const President& other) = default; }; std::ostream& operator << (std::ostream& os, const President& president) { os << president.name << ", " << president.country << ", " << president.year; return os; } int main() { std::vector<President> elections; std::cout << "emplace_back:\n"; elections.emplace_back("Nelson Mandela", "South Africa", 1994); elections.emplace_back("Franklin Delano Roosevelt", "the USA", 1936); elections.emplace_back("Foo", "Japan", 2020); std::cout << "\nElections:" << std::endl; for (auto const& president : elections) { std::cout << president << std::endl; } elections.emplace(elections.begin()+1, "Boo", "Japan", 2021); std::cout << "\nElections:" << std::endl; for (auto const& president : elections) { std::cout << president << std::endl; } }
emplace_back: I am being constructed. I am being constructed. I am being moved. I am being constructed. I am being moved. I am being moved. Elections: Nelson Mandela, South Africa, 1994 Franklin Delano Roosevelt, the USA, 1936 Foo, Japan, 2020 I am being constructed. I am being moved. I am being moved. I am being moved. Elections: Nelson Mandela, South Africa, 1994 Boo, Japan, 2021 Franklin Delano Roosevelt, the USA, 1936 Foo, Japan, 2020
補足:
新しい size() が現在の capacity()
より大きいため、vectorの再構築が発生し、コンテナ内アイテムの移動が発生しているようです。
アイテムの挿入が頻繁に発生する場合、reserve()で必要な領域を事前確保しておく、または std::list
を使用する、などを検討することでペナルティを減らせる場合があります。
本ページの情報は、特記無い限り下記 MIT ライセンスで提供されます。
2022-10-10 | - | ページデザイン更新 |
2020-08-11 | - | 新規作成 |