transform関数

http://www.geocities.jp/ky_webid/cpp/library/022.html

copy関数に似ていますが、transform関数は関数(や関数オブジェクト)を渡して独自の処理をしながら要素のコピーを行えます。

int型のvectorで試してみます。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int pow2 (int num) {
    return num * num;
}

int main () {
    vector<int> data1;
    vector<int> data2;
    
    for(int i=0;i<10;++i) {
        data1.push_back(i);
    }
    
    // pow2を利用して各要素を2乗しながらコピーする
    transform(data1.begin(),data1.end(),data2.begin(),pow2);
    
    copy(data2.begin(),data2.end(),ostream_iterator<int>(cout,"\n"));
    
    return 0;
}

これを実行すると落ちました・・・。

transformの第三引数にdata2.begin()を渡しているのが原因です。

イテレータ経由で値を追加するわけですが、どうもtransformの内部実装として、受け取ったイテレータにそのまま代入しているだけなのでdata2に確保された要素が無いので落ちるみたいです。data2に予めpush_back等でdata1と同じだけ値が確保されていれば問題なく動きますがそれだと無駄が多いですよね。

こういう場合に使えるのが前に習った挿入イテレータですね。

置き換えてみます。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int pow2 (int num) {
    return num * num;
}

int main () {
    vector<int> data1;
    vector<int> data2;
    
    for(int i=0;i<10;++i) {
        data1.push_back(i);
    }
    
    // back_inserterを使い末尾に値を追加できるようにする
    transform(data1.begin(),data1.end(),back_inserter(data2),pow2);
    
    copy(data2.begin(),data2.end(),ostream_iterator<int>(cout,"\n"));
    
    return 0;
}
$ main
0
1
4
9
16
25
36
49
64
81

うまく動きました。

さて、transform関数にはもう一つの使い方もあります。

二つの配列を走査しながら処理を行うことができます。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int add (int num1,int num2) {
    return num1 + num2;
}

int main () {
    vector<int> data1;
    vector<int> data2;
    vector<int> data3;
    
    for(int i=0;i<10;++i) {
        data1.push_back(i);
        data2.push_back(i);
    }
    
    // data1とdata2を足した結果をdata3へコピー
    transform(data1.begin(),data1.end(),data2.begin(),back_inserter(data3),add);
    
    copy(data3.begin(),data3.end(),ostream_iterator<int>(cout,"\n"));
    
    return 0;
}
$ main
0
2
4
6
8
10
12
14
16
18

足された結果が入ってますね。

ちなみにこの時もしdata2の要素数がdata1の要素数よりも少なかった場合、プログラムが落ちます。

というわけで事前に必ず各配列の要素数の確認が必要になりますね。