4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【C++】コンテナクラス

Last updated at Posted at 2025-01-22

動的配列

動的配列とは

  • 動的配列(C++の配列、実行中にサイズの変更が可能)
    固定長配列(C言語の配列、実行開始時からサイズの変更が不可能)
  • 配列と同様の操作が可能。また、データの追加、削除が可能
  • 配列と同様にデータは先頭から末尾まで順にメモリに格納されており、
    連続したデータである為、末尾(最後の次)以外へのデータの追加、削除は負荷が大きい

用途 : オブジェクトを管理するリストなど

vector(C++)

Example.cpp
#include <iostream>
#include <vector>
#include <format>

int main(void)
{
	// 宣言・定義
	// std::vector<型> 変数名;
	std::vector<int> iVector = { 1, 2, 3, 4, 5 };

	std::cout << std::format("確保しているメモリの容量 : {}", iVector.capacity()) << std::endl;
	std::cout << std::format("格納している要素の数 : {}", iVector.size()) << std::endl;

	// 要素の追加(末尾)
	// std::vector.push_back(値);
	iVector.push_back(6);

	std::cout << std::format("確保しているメモリの容量 : {}", iVector.capacity()) << std::endl;
	std::cout << std::format("格納している要素の数 : {}", iVector.size()) << std::endl;
	
	// 要素の追加(任意)
	// std::vector.insert(iterator.position, 値);
	iVector.insert(iVector.begin(), -1);
	iVector.insert(iVector.end(), 7);

	std::cout << std::format("確保しているメモリの容量 : {}", iVector.capacity()) << std::endl;
	std::cout << std::format("格納している要素の数 : {}", iVector.size()) << std::endl;

	// (※)イテレータの定義
	// std::vector<型>::iterator 変数名;
	std::vector<int>::iterator itr = iVector.begin();
	itr += 4;
	iVector.insert(itr, 100);
    
	std::cout << std::format("確保しているメモリの容量 : {}", iVector.capacity()) << std::endl;
	std::cout << std::format("格納している要素の数 : {}", iVector.size()) << std::endl;

	// Range-based for loop(C++11以上)での出力
	for (int i : iVector)
	{
		std::cout << i << std::endl;
	}

	// 要素の削除(末尾)
	// std::vector.pop_back();
	std::cout << std::format("{} を削除しました", iVector.back()) << std::endl;
	iVector.pop_back();

	// 要素の削除(任意)
	// std::vector.erase(iterator.position)
	itr = iVector.begin();
	itr += 4;
	std::cout << std::format("{} を削除しました", *itr) << std::endl;
	iVector.erase(itr);

	// 要素の削除(条件)
	// std::vector.erase(iterator.position)
	// remove_if()の戻り値はiterator.positionを返す
	std::cout << "3 以下の値を削除しました" << std::endl;
	iVector.erase
	(
		remove_if(iVector.begin(), iVector.end(), [](int& i) { return i <= 3; }),
		iVector.end()
	);

	// 要素の全削除
	// std::vector.clear()
	// std::vector.shrink_to_fit()はcapacity = sizeにする
	iVector.clear();
	iVector.shrink_to_fit();
    
	std::cout << std::format("確保しているメモリの容量 : {}", iVector.capacity()) << std::endl;
	std::cout << std::format("格納している要素の数 : {}", iVector.size()) << std::endl;

	// イテレータの操作での出力
	for (std::vector<int>::iterator itr = iVector.begin(); itr != iVector.end(); itr++)
	{
		std::cout << *itr << std::endl;
	}

	return 0;
}

remove_if

remove_if(削除を開始する位置を示すイテレータ, 削除を終了する位置を示すイテレータ, ラムダ式);
->条件を満たす要素をコンテナの後ろに移動し、新しい終端イテレータを返す

List(C#)

Example.cs
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // 宣言・定義
        // List<型> 変数名 = new List<型>();
        List<int> iList = new List<int> { 1, 2, 3, 4, 5 };

        Console.WriteLine($"確保しているメモリの容量 : {iList.Capacity}");
        Console.WriteLine($"格納している要素の数 : {iList.Count}");

        // 要素の追加(末尾)
        // List.Add(値);
        iList.Add(6);

        Console.WriteLine($"確保しているメモリの容量 : {iList.Capacity}");
        Console.WriteLine($"格納している要素の数 : {iList.Count}");

        // 要素の追加(任意)
        // List.insert(index, 値);
        iList.Insert(iList.GetEnumerator().Current, -1);
        iList.Insert(iList.Count - 1, 7);

        Console.WriteLine($"確保しているメモリの容量 : {iList.Capacity}");
        Console.WriteLine($"格納している要素の数 : {iList.Count}");

        // foreachでの出力
        foreach (int i in iList)
        {
            Console.WriteLine(i);
        }

        // 要素の削除(末尾)
        // List.RemoveAt(List.Count - 1);
        Console.WriteLine($"{iList[iList.Count - 1]}を削除しました");
        iList.RemoveAt(iList.Count - 1);

        // 要素の削除(条件)
        // List.RemoveAll(ラムダ式)
        Console.WriteLine("3以下の値を削除しました");
        iList.RemoveAll(i => i <= 3);

        // 要素の全削除
        // List.clear()
        iList.Clear();

        Console.WriteLine($"確保しているメモリの容量 : {iList.Capacity}");
        Console.WriteLine($"格納している要素の数 : {iList.Count}");

        // イテレータの操作での出力
        itr = iList.GetEnumerator();
        while (itr.MoveNext())
        {
            Console.WriteLine(itr.Current);
        }
    }
}

連結リスト

連結リストとは

  • 自身の前後のアドレスのみを知る構造
  • 配列とは違いバラバラな位置にデータが格納されているため、
    配列のような操作(ランダムアクセス)は不可能
  • 任意の位置への追加、削除に優れている特徴を持つ

用途 : 生成・削除が頻繁に行われるオブジェクト(シューティングゲームの弾など)の管理

list(C++)

Example.cpp
#include <iostream>
#include <list>
#include <format>

int main(void)
{
	// 宣言・定義
	// std::list<型> 変数名;
	std::list<int> iList = { 1, 2, 3, 4, 5 };

	std::cout << std::format("格納している要素の数 : {}", iList.size()) << std::endl;

	// 要素の追加(末尾)
	// std::list.push_back(値)
	iList.push_back(6);

	std::cout << std::format("格納している要素の数 : {}", iList.size()) << std::endl;

	// 要素の追加(先頭)
	// std::list.push_front(値)
	iList.push_front(-1);

	std::cout << std::format("格納している要素の数 : {}", iList.size()) << std::endl;

	// 要素の追加(任意)
	// std::list.insert(iterator.position, 値);
	iList.insert(iList.begin(), -2);
	iList.insert(iList.end(), 7);

    std::cout << std::format("格納している要素の数 : {}", iList.size()) << std::endl;

	// (※)イテレータの定義
	// std::list<型>::iterator 変数名;
	std::list<int>::iterator itr = iList.begin();
	advance(itr, 4);
	iList.insert(itr, 100);

	std::cout << std::format("格納している要素の数 : {}", iList.size()) << std::endl;

	// Range-based for loop(C++11以上)での出力
	for (int i : iList)
	{
		std::cout << i << std::endl;
	}

	// 要素の削除(末尾)
	// std::list.pop_back();
	std::cout << std::format("{} を削除しました", iList.back()) << std::endl;
	iList.pop_back();

	// 要素の削除(先頭)
	// std::list.pop_front();
	std::cout << std::format("{} を削除しました", iList.front()) << std::endl;
	iList.pop_front();

	// 要素の削除(任意)
	// std::list.erase(iterator.position)
	itr = iList.begin();
	advance(itr, 4);
	std::cout << std::format("{} を削除しました", *itr) << std::endl;
	iList.erase(itr);

	// 要素の削除(条件)
	// std::list.erase(iterator.position)
	// remove_if()の戻り値はiterator.positionを返す
	std::cout << "3 以下の値を削除しました" << std::endl;
	iList.erase
	(
		remove_if(iList.begin(), iList.end(), [](int& i) { return i <= 3; }),
		iList.end()
	);

	// 要素の全削除
	// std::list.clear()
	iList.clear();

	std::cout << std::format("格納している要素の数 : {}", iList.size()) << std::endl;

	// イテレータの操作での出力
	for (int i : iList)
	{
		std::cout << i << std::endl;
	}

	return 0;
}

LinkedList(C#)

Example.cs
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // 宣言・定義
        // LinkedList<型> 変数名 = new List<型>();
        LinkedList<int> iLinkedList = new LinkedList<int>(new int[] { 1, 2, 3, 4, 5 });

        Console.WriteLine($"格納している要素の数 : {iLinkedList.Count}");

        // 要素の追加(末尾)
        // LinkedList.AddLast(値);
        iLinkedList.AddLast(6);

        Console.WriteLine($"格納している要素の数 : {iLinkedList.Count}");

        // 要素の追加(先頭)
        // LinkedList.AddFirst(値);
        iLinkedList.AddFirst(-1);

        Console.WriteLine($"格納している要素の数 : {iLinkedList.Count}");

        // 要素の追加(任意)
        // LinkedList.AddBefore(index, indexの要素の前に追加する値);
        // LinkedList.AddAfter(index, indexの要素の後に追加する値);
        iLinkedList.AddBefore(iLinkedList.First, -2);
        iLinkedList.AddAfter(iLinkedList.Last, 7);

        Console.WriteLine($"格納している要素の数 : {iLinkedList.Count}");

        // (※)イテレータの定義
        // LinkedListNode<型> 変数名;
        LinkedListNode<int> itr = iLinkedList.First;
        for (int i = 0; i < 4; i++) { itr = itr.Next; }
        iLinkedList.AddAfter(itr, 100);

        Console.WriteLine($"格納している要素の数 : {iLinkedList.Count}");

        // foreachでの出力
        foreach (int i in iLinkedList)
        {
            Console.WriteLine(i);
        }

        // 要素の削除(末尾)
        // LinkedList.RemoveLast();
        Console.WriteLine($"{iLinkedList.Last.Value}を削除しました");
        iLinkedList.RemoveLast();

        // 要素の削除(先頭)
        // LinkedList.RemoveFirst();
        Console.WriteLine($"{iLinkedList.First.Value}を削除しました");
        iLinkedList.RemoveFirst();

        // 要素の削除(任意)
        // LinkedList.Remove(itr);
        itr = iLinkedList.First;
        for (int i = 0; i < 4; i++) { itr = itr.Next; }
        Console.WriteLine($"{itr.Value}を削除しました");
        iLinkedList.Remove(itr);

        // 要素の削除(条件)
        // List.RemoveAll(ラムダ式)
        Console.WriteLine("3以下の値を削除しました");
        while (itr != null)
        {
            if (itr.Value <= 3)
            {
                iLinkedList.Remove(itr);
            }
            itr = itr.Next;
        }

        // 要素の全削除
        // LinkedList.clear()
        iLinkedList.Clear();

        Console.WriteLine($"格納している要素の数 : {iLinkedList.Count}");

        // イテレータの操作での出力
        itr = iLinkedList.First;
        while (itr != null)
        {
            Console.WriteLine(itr.Value);
            itr = itr.Next;
        }
    }
}

連想配列

連想配列とは

  • pair型(Key(鍵)とValue(値))によって管理されるデータの構造
  • KeyとValueには別々の型が入る
  • 二次元配列に似た使用感

用途 : エンティティの管理(IDと情報など)、オブジェクト属性(体力、攻撃力など)の管理など

map(C++)

Example.cpp
#include <iostream>
#include <map>
#include <string>
#include <format>

int main(void)
{
	// 宣言
	// std::map<keyとなる型, valueとなる型> 変数名;
	std::map<std::string, int> iMap;

	// 要素の追加(二次元配列方式)
	iMap["A"] = 0;
	iMap["B"] = 10;
	iMap["C"] = 20;

	std::cout << std::format("格納している要素の数 : {}", iMap.size()) << std::endl;

	// 要素の追加(std::make_pair<型, 型>())
	// std::map.insert(std::make_pair<型, 型>(key, value));
	iMap.insert(std::make_pair<std::string, int>("あ", 100));
    
	std::cout << std::format("格納している要素の数 : {}", iMap.size()) << std::endl;

	// 要素の追加(make_pair())
	// std::map.insert(std::make_pair(key, value));
	// ※ (型)値 はC言語のキャスト
	iMap.insert(std::make_pair((std::string)"い", 100));
    
	std::cout << std::format("格納している要素の数 : {}", iMap.size()) << std::endl;

	// 要素の追加(make_pair())
	// std::map.insert(std::make_pair(key, value));
	// ※ static_cast<std::string>値 はC++のキャスト
	iMap.insert(std::make_pair(static_cast<std::string>("う"), 100));
    
	std::cout << std::format("格納している要素の数 : {}", iMap.size()) << std::endl;
	
	// 要素の追加(emplace)
	// std::map.emplace(key, value);
	iMap.emplace("え", 100);
    
	std::cout << std::format("格納している要素の数 : {}", iMap.size()) << std::endl;

    // Range-based for loop(C++11以上)での出力
	for (std::pair<std::string, int> pair : iMap)
	{
		std::cout << std::format("Key : {}, Value : {}", pair.first, pair.second) << std::endl;
	}


	// 要素の削除
	// std::map.erase(key);
    std::cout << std::format("Key : え, Value : {} を削除しました", iMap["え"]) << std::endl;
	iMap.erase("え");

	// 勝手に新規作成しやがる場合
    // iMap.at(key)を使うとエラーを出せる
	int tmp = iMap["エラーにならない1"];
	std::cout << tmp << std::endl;

    // 新規作成->削除
	iMap.erase("エラーにならない2");

	// 要素の全削除
	// std::map.clear()
	iMap.clear();

	std::cout << std::format("格納している要素の数 : {}", iMap.size()) << std::endl;

	// イテレータの操作での出力
	for (std::map<std::string, int>::iterator itr = iMap.begin(); itr != iMap.end(); itr++)
	{
		std::cout << std::format("Key : {}, Value : {}", itr->first, itr->second) << std::endl;
	}

	return 0;
}

insertとemplaceの違い

insert : キーと値のペアのコピーまたはムーブを行う
emplace : キーと値のペアの直接構築を行う

Dictionary(C#)

Example.cs
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // 宣言
        // Dictionary<keyとなる型, valueとなる型> 変数名 = new Dictionary<同型, 同型>();
        Dictionary<string, int> iMap = new Dictionary<string, int>();

        // 要素の追加(二次元配列方式)
        iMap["A"] = 0;
        iMap["B"] = 10;
        iMap["C"] = 20;

        Console.WriteLine($"格納している要素の数 : {iMap.Count}");

        // 要素の追加(Add)
        // Dictionary.Add(key, value);
        iMap.Add("あ", 100);

        Console.WriteLine($"格納している要素の数 : {iMap.Count}");

        // foreachでの出力
        foreach (KeyValuePair<string, int> pair in iMap)
        {
            Console.WriteLine($"Key : {pair.Key}, Value : {pair.Value}");
        }

        // 要素の削除
        // Dictionary.Remove(key);
        iMap.Remove("あ");

        Console.WriteLine($"格納している要素の数 : {iMap.Count}");

        // 要素の全削除
        // Dictionary.Clear()
        iMap.Clear();

        Console.WriteLine($"格納している要素の数 : {iMap.Count}");
    }
}

(※)イテレータ

イテレータとは抽象化されたポインタのこと。

用途 : コンテナクラスの操作

先頭はコンテナクラス型.begin()、末尾は**コンテナクラス型.end()**で取得可能
末尾とは最後の要素の次

*itrはイテレータが指し示す要素の値を取得できる

最後に

一応、UnityC#でのテスト(Console->Debug.Log)を行っていますが、
本家C#との違いがあればご指摘お願いします。

4
2
10

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?