【C++】mapやsetを効率的に併合する.merge()の使い方

目次

はじめに

C++で、二つのmapsetといった連想コンテナを一つにまとめたい場合、従来は片方のコンテナの全要素をループで取り出し、もう片方に一つずつinsertする必要がありました。この方法では、要素のコピーや、場合によってはメモリの再確保が発生し、非効率的でした。

C++17では、この問題を解決する .merge() というメンバ関数が導入されました。.merge()は、コンテナの内部構造(ノード)を直接移動させるため、要素のコピーやメモリ確保を一切行わず、極めて高速にコンテナ同士を併合できます。

この記事では、.merge()の基本的な使い方と、キーが重複した場合の挙動について解説します。


【前提】C++17とは?

C++17(シーピープラスいちなな)は、2017年に正式化されたC++言語の規格です。.merge() はこのC++17で追加された機能のため、利用するにはC++17に対応したコンパイラ(と、その機能を有効にするための設定)が必要になります。


.merge() を使ったサンプルコード

このコードは、std::multiset(重複キーを許容するセット)を、std::set(重複キーを許容しないセット)に併合する例です。

完成コード

#include <iostream>
#include <string>
#include <set> // set, multiset を使うために必要

using namespace std;

int main() {
    // 併合先 (重複キーなし)
    set<string> destination = {"りんご", "みかん"};
    
    // 併合元 (重複キーあり)
    multiset<string> source = {"みかん", "ぶどう", "れもん", "れもん"};
    
    cout << "--- 併合前 ---" << endl;
    cout << "destination: ";
    for (const auto& item : destination) cout << item << " ";
    cout << endl;
    cout << "source: ";
    for (const auto& item : source) cout << item << " ";
    cout << endl;

    // 1. source の全要素を destination に併合
    destination.merge(source);
    
    cout << "\n--- 併合後 ---" << endl;
    cout << "destination: ";
    for (const auto& item : destination) cout << item << " ";
    cout << endl;

    // 2. 併合に失敗した要素だけが source に残る
    cout << "source (併合後): ";
    if (source.empty()) {
        cout << "空になりました。";
    } else {
        for (const auto& item : source) cout << item << " ";
    }
    cout << endl;
    
    return 0;
}

実行結果

--- 併合前 ---
destination: りんご みかん 
source: ぶどう みかん れもん れもん 

--- 併合後 ---
destination: ぶどう りんご みかん れもん 
source (併合後): みかん れもん 

コードの解説

1. destination.merge(source);

これがコンテナを併合する核心部分です。

  • 動作: sourceコンテナの各要素を一つずつ取り出し、destinationコンテナに移動させようと試みます。
  • 効率性: この操作は、コンテナの内部データ(ノード)へのポインタを繋ぎ変えるだけで行われます。要素のコピーや、新たなメモリ確保・解放は一切発生しないため、非常に高速です。
  • 併合元の変化: 併合に成功した要素は、sourceコンテナから削除されます。

2. キーが重複した場合の挙動

destination (std::set) は重複したキーを許容しません。

  • source"ぶどう""れもん"(1つ目): destination には存在しないキーなので、併合は成功し、destination に移動します。
  • source"みかん""れもん"(2つ目): destination には既に同じキーが存在します。そのため、これらの要素の併合は失敗し、sourceコンテナにそのまま残ります

実行結果が示すように、併合後、destination には全てのユニークな要素が集まり、source には destination に既に存在していたために併合できなかった要素だけが残ります。

std::mapstd::multimap の間でも同様に .merge() を使用できます。


まとめ

今回は、C++17で導入された .merge() メンバ関数を使って、mapsetといった連想コンテナを効率的に併合する方法を解説しました。

  • .merge() は、要素をコピーせず、コンテナの内部ノードを直接移動させるため非常に高速
  • 併合先のコンテナが重複キーを許容しない (set, map) 場合、キーが重複する要素は併合されず、元のコンテナに残り続ける

ループを使って手動で要素を移し替えるよりも、.merge() を使った方が、コードが簡潔になるだけでなく、パフォーマンスも大幅に向上します。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次