[C++] vectorの挙動検証 erase

[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]

前回、前々回と同様の検証をerase関数で実施しました。

erase関数の場合は、メモリアドレスは削除箇所から前の要素は変わらず、削除箇所から後ろは前に詰める形になります。

イテレータの再設定は必要です。再設定しないとwhile文ではデータが格納されていると認識している旧endを延々と探すことになり、ループが止まりません。

#include <iostream>
#include <vector>

using std::to_string;

int main()
{
    std::vector<int> vec{ 1, 2, 3, 4, 5};
    std::vector<int>::iterator itr = vec.begin();
    
    // vectorの各要素のアドレスを出力
    std::cout << "vector" << std::endl;
    while (itr != vec.end())
    {
        std::cout << &(*itr) << std::endl;
        itr++;
    }

	// 3番目の要素を削除
	vec.erase(vec.begin() + 2);
	
	// イテレータ再設定
	std::vector<int>::iterator itr2 = vec.begin();
	
	// 再度アドレス出力
	std::cout << "vector削除後" << std::endl;
    while (itr2 != vec.end())
    {
        std::cout << &(*itr2) << std::endl;
        itr2++;
    }

	for (int num:vec)
    {
        std::cout << to_string(num) << std::endl;
    }
}
--------------------------------------------------
出力例
--------------------------------------------------
vector
0x13e6068c0
0x13e6068c4
0x13e6068c8
0x13e6068cc
0x13e6068d0

vector削除後
0x13e6068c0
0x13e6068c4
0x13e6068c8
0x13e6068cc
1
2
4
5

[C++] vectorの挙動検証 insert

[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]

前回と同様の検証をinsert関数で実施しました。

insertやeraseのようなイテレータが戻り値の関数では、これを受け取ればイテレータを再設定せずに済む場合があります。

先頭に挿入した場合だけ再設定不要で、それ以外の場合は再設定しないと全てのメモリアドレスを確認できません。

#include <iostream>
#include <vector>

using std::to_string;

int main()
{
    std::vector<int> vec{ 1, 2, 3, 4, 5};
    std::vector<int>::iterator itr = vec.begin();
    
    // vectorの各要素のアドレスを出力
    std::cout << "vector" << std::endl;
    while (itr != vec.end())
    {
        std::cout << &(*itr) << std::endl;
        itr++;
    }

	// 要素を挿入
	itr = vec.insert(vec.begin(),6);
	
	// 再度アドレス出力
	std::cout << "vector挿入後" << std::endl;
    while (itr != vec.end())
    {
        std::cout << &(*itr) << std::endl;
        itr++;
    }

	for (int num:vec)
    {
        std::cout << to_string(num) << std::endl;
    }

}
--------------------------------------------------
出力例
--------------------------------------------------
vector
0x1336068c0
0x1336068c4
0x1336068c8
0x1336068cc
0x1336068d0

vector挿入後
0x1336068e0
0x1336068e4
0x1336068e8
0x1336068ec
0x1336068f0
0x1336068f4
6
1
2
3
4
5

[C++] vectorの挙動検証 push_back

[M1 Mac, Big Sur 11.6.7, clang 13.0.0, NO IDE]

vectorの各要素のメモリアドレスおよび要素を追加したときのアドレスの変化をチェックしました。

push_back関数で要素を追加すると、16バイト先のメモリアドレスから再度要素を配置することがわかりました。イテレータを設定していた場合はそれが使えなくなるため、再度設定が必要になります。

#include <iostream>
#include <vector>

using std::to_string;

int main()
{
    std::vector<int> vec{ 1, 2, 3, 4, 5};
    std::vector<int>::iterator itr = vec.begin();
    
    // vector各要素のアドレスを出力
    std::cout << "vector" << std::endl;
    while (itr != vec.end())
    {
        std::cout << &(*itr) << std::endl;
        itr++;
    }

	// 要素を追加
	vec.push_back(6);
	// イテレータを再度設定
	std::vector<int>::iterator itr2 = vec.begin();

	// 再度アドレス出力
	std::cout << "vector要素追加後" << std::endl;
    while (itr2 != vec.end())
    {
        std::cout << &(*itr2) << std::endl;
        itr2++;
    }

	for (int num:vec)
    {
        std::cout << to_string(num) << std::endl;
    }
}
--------------------------------------------------
出力例
--------------------------------------------------
vector
0x1596068c0
0x1596068c4
0x1596068c8
0x1596068cc
0x1596068d0

vector要素追加後
0x1596068e0
0x1596068e4
0x1596068e8
0x1596068ec
0x1596068f0
0x1596068f4
1
2
3
4
5
6

[C++] 参考サイトの選別

C++を体系的にまとめたサイトには説明が不十分なものがあったりします。

std::vectorの説明でコンテナを変更するメンバ関数がpush_backしかないような書き方をしているサイトがあったので、Chromeの拡張機能uBlacklistで検索結果に表示できなくしました。insertやeraseなどを明記しなくても、他にも関連するメンバ関数があることに触れて欲しかったです。

cpprefjp – C++日本語リファレンスが辞書的なサイトとして優れているので、検索する前にまずそこで調べることをお勧めします。

このサイトのような学習過程を記録した個人ブログも中級以上の方には何の参考にもならないですから検索結果に出ないようにすべきでしょう。

cpprefjp – C++日本語リファレンス