Page List

Search on the blog

2014年4月5日土曜日

std::swapで配列をスワップする

 C++のstd::swapを使うと

std::swap(a, b)

のようにして、変数aとbの値を入れ替えることが出来る。

これは配列に対しても適用出来る。例えば、以下のようにして配列a[]と配列b[]をスワップ出来る。
#include <iostream>

using namespace std;

void dump(int arr[], int sz) {
    for (int i = 0; i < sz; i++)
        cout << arr[i] << " ";
    cout << endl;
}

int main(int argc, char **argv) {
    int a[] = {1,2,3};
    int b[] = {4,5,6};

    swap(a, b);

    dump(a, 3);   // 4 5 6
    dump(b, 3);   // 1 2 3
    
    return 0;
}
また、行列(二次元配列)の行の入れ替え操作を行うことも出来る。例えば、以下のようにして行列aの1行目と3行目を入れ替えることが出来る。
#include <iostream>

using namespace std;

void dump(int arr[][3], int sz) {
    for (int i = 0; i < sz; i++) {
        for (int j = 0; j < 3; j++) {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
}

int main(int argc, char **argv) {
    
    int a[][3] = {
        {1,2,3},
        {4,5,6},
        {7,8,9}
    };

    swap(a[0], a[2]);

    dump(a, 3);
    // 7 8 9 
    // 4 5 6
    // 1 2 3
    
    return 0;
}
なぜこのようなことが出来るのか納得できなかったので、swap関数の中身を見てみた。どうやら、配列に対してオーバーロードされているようだ。gccのstd::swapの定義は以下のような感じだった。
template<typename _Tp, size_t _Nm>
inline void swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
{
    for (size_t __n = 0; __n < _Nm; ++__n)
        swap(__a[__n], __b[__n]);
}

ほうほう、テンプレート型のところに配列のサイズを指定できるのか。
何かテキトーな関数を書いて実験してみた。
#include <iostream>

using namespace std;

template<typename T>
inline void dump(const T &a) {
    cout << a << " ";
}

template <typename T, size_t N>
inline void dump(T const (&a)[N]) {
    for (size_t i = 0; i < N; i++)
        dump(a[i]);
    cout << endl;
}

int main(int argc, char **argv) {

    int x = 10;
    
    int a[] = {1,2,3,4,5,6,7,8,9,10};
    
    int b[][3] = {
        {1,2,3},
        {4,5,6},
        {7,8,9}
    };


    // x = 10 
    cout << "x = ";
    dump(x);
    cout << endl;

    // a = 1 2 3 4 5 6 7 8 9 10 
    cout << "a = ";
    dump(a);
    cout << endl;
    
    //b = 1 2 3 
    //4 5 6 
    //7 8 9 
    cout << "b = ";
    dump(b);
    cout << endl;
    
    return 0;
}
予想どおりに動いた。テンプレートはこんなことが出来るのかー。面白い。。

0 件のコメント:

コメントを投稿