std::vectorをコピーする
提供: C++入門
スポンサーリンク
C++のstd::vecotrをコピーするには、std::copyとstd::back_inserterを使用するとより簡単に書けます。
目次
概要
std::vectorからstd::vectorにコピーする方法を紹介します。
簡単にstd::vectorをコピーする方法
std::copyとstd::back_inserterを使用するとより簡単に書けます。
#include <iostream> #include <vector> #include <algorithm> // std::copy #include <iterator> // std::back_inserter using namespace std; int main(int argc, char const* argv[]) { vector<int> v1,v2; for(int i = 0;i<1024*4*100;i++) { v1.push_back(i); } copy(v1.begin(), v1.end(), back_inserter(v2) ); return 0; }
コピー時にSegmentation faultが起きる
Segmentation faultが起きるコード
#include <iostream> #include <vector> #include <algorithm> // std::copy using namespace std; int main(int argc, char const* argv[]) { vector<int> v1(1024*4*100, 0),v2; // v1に0を1024*4*100個入れる copy(v1.begin(), v1.end(), v2.begin()); return 0; }
上記のコードは、Segmentation faultを引き起こします。
% ./a.out Segmentation fault
memmoveのあたりでこけているのかもしれません。
(gdb) backtrace #0 0x2829b5e6 in memmove () from /lib/libc.so.7 #1 0x080492d9 in std::__copy_move<false, true, std::random_access_iterator_tag>::__copy_m<int> () #2 0x08049166 in std::__copy_move_a<false, int*, int*> () #3 0x08048f21 in std::__copy_move_a2<false, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > > > () #4 0x08048c36 in std::copy<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > > > () #5 0x08048a36 in main ()
Segmentation faultの解決策 1
コピー先のオブジェクトのサイズに問題があるようなので、あらかじめ std::vector::resizeでサイズ調整をしておきます。
#include <iostream> #include <vector> #include <algorithm> // std::copy using namespace std; int main(int argc, char const* argv[]) { vector<int> v1(1024*4*100, 0),v2; v2.resize(v1.size()); copy(v1.begin(), v1.end(), v2.begin()); return 0; }
Segmentation faultの解決策 2 back_inserterを使う
std::back_inserterを使用するとより簡単に書けます。
#include <iostream> #include <vector> #include <algorithm> // std::copy #include <iterator> // std::back_inserter using namespace std; int main(int argc, char const* argv[]) { vector<int> v1(1024*4*100, 0),v2; copy(v1.begin(), v1.end(), back_inserter(v2) ); return 0; }
std::vectorにクラスのオブジェクトを入れるときの注意点
問題のないコード
このコードは、問題になりません。
include <algorithm> // std::copy #include <iterator> // std::back_inserter using namespace std; class C { public: C(){} virtual ~C(){} }; int main(int argc, char const* argv[]) { vector<C> v1(20, C() ),v2; cout << v1.size() << endl; copy(v1.begin(), v1.end(), back_inserter(v2) ); return 0; }
コピーコンストラクタの問題でエラーになるコード
このコードは、コピーコンストラクタの問題でエラーになります。
include <algorithm> // std::copy #include <iterator> // std::back_inserter using namespace std; class C { public: C(){} virtual ~C(){} C(C& r) {} }; int main(int argc, char const* argv[]) { vector<C> v1(20, C() ),v2; cout << v1.size() << endl; copy(v1.begin(), v1.end(), back_inserter(v2) ); return 0; }
エラーが長すぎるので、1部分だけ切り出します。 コピーコンストラクタが指摘されています。
/usr/local/lib/gcc49/include/c++/bits/stl_construct.h:75:7: error: no matching function for call to 'C::C(C)' { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); } ^ /usr/local/lib/gcc49/include/c++/bits/stl_construct.h:75:7: note: candidates are: vector_copy_with_class1.cpp:10:3: note: C::C(C&) C(C& r) {} ^ vector_copy_with_class1.cpp:10:3: note: no known conversion for argument 1 from 'C' to 'C&' vector_copy_with_class1.cpp:8:3: note: C::C() C(){} ^ vector_copy_with_class1.cpp:8:3: note: candidate expects 0 arguments, 1 provided
解決策
コピーコンストラクタの引数は、constでなければなりません。
#include <iostream> #include <vector> #include <algorithm> // std::copy #include <iterator> // std::back_inserter using namespace std; class C { public: C(){} virtual ~C(){} C(const C& r) {} // 変更点は、この引数をconstにしたこと }; int main(int argc, char const* argv[]) { vector<C> v1(20, C() ),v2; cout << v1.size() << endl; copy(v1.begin(), v1.end(), back_inserter(v2) ); return 0; }
関連項目
- std::copy
- std::back_inserter
- std::vector シンプルな例
- std::vecotrを2次元配列として扱う
- std::vectorで構造体を扱う
- std::vectorをコピーする
- std::move: 所有権を移動する
- std::vector 特定の要素をカウントする
- std::sort : std::vectorをソートします。
- std::initializer_list
メンバ | 意味 |
---|---|
constructor | vectorのコンストラクタ。vectorを初期化します。 |
destrctor | デストラクタ |
operator= | operator= |
reserve | std::vectorのキャパシティを予約します。 |
capacity | 割り当てられているストレージキャパシティのサイズを返します。 |
size | サイズを返します。 |
resize | サイズをリサイズします。 |
shrink_to_fit | コンテナのキャパシティにフィットしたサイズまで縮小します。 |
push_back | std::vector の最後に新しい要素を追加します。要素は、コピー、もしくは、move されます。 |
std::vector の最後の要素を取り除きます。コンテナのサイズが1つ小さくなります。 | |
insert | std::vector に新しい要素を追加します。vector同士を連結できます。 |
erase | std::vector の1つの要素、または、要素のレンジを削除します。 |
clear | std::vector の要素をすべて削除します。 |
empty | std::vector が空であれば、trueを返し、そうでなければ、falseです。 |
begin | std::vector の最初の要素のイテレータを返します。 |
front | std::vector の最初の要素の参照を返します。 |
back | std::vector の最後の要素の参照を返します。 |
at | std::vector の n 番目の要素の参照を返します。無効な要素にアクセスしたとき、 std::out_of_range の例外を送出します。 operator[] は、境界チェックをしません。 |
operator[] | std::vector の n 番目の要素の参照を返します。 operator[] は、境界チェックをしません。 |
std::vector::shrink_to_fit | C++11で追加された、コンテナサイズを領域に合わせます。メモリの解放に利用します。 |
ツイート
スポンサーリンク