STL(C++) の std::list と GLib の GList で foreach してみた。
C と C++ の微妙な違いがあってなかなか興味深い。
C++, STL
#include <iostream> #include <list> #include <algorithm> void show_data(std::string s) { std::cout << s << std::endl; } int main (int argc, char **argv) { std::list<std::string> l; std::string s; for (int i=0; i<3; i++) { std::cout << "input " << i << " : "; std::cin >> s; l.push_back(s); } // for_each @ algorithm std::for_each(l.begin(), l.end(), show_data); return 0; }
GLib
#include <glib.h> void show_data(gpointer data ,gpointer user_data) { g_printf("%s\n",data); } void delete_data(gpointer data ,gpointer user_data) { g_free(data); data = NULL; } int main (int argc, char **argv) { GList* list = NULL; gchar s[256]; gint i; for (i=0; i<3; i++) { g_printf("input %d : ", i); scanf("%s", s); //list = g_list_append (list, s); // All Last Data list = g_list_append (list, g_strdup(s)); } /* foreach */ g_list_foreach(list, show_data, NULL); /* free */ g_list_foreach(list, delete_data, NULL); g_list_free( list ); return 0; }
ビルド結果は同じものが作られるはず。
std::for_each, g_list_foreach 共に関数ポインタを使っている。
GLib はソックリにしようと思ったのでしょうか?
STL は関数オブジェクトが使えるとかもろもろは置いておいて。
ところで for 文等を使わずにズラズラ並べるなら当然下記でもいい。
スタックのメモリ領域なので当然破棄処理も不要。
実際のアプリケーションでこんなコードになることはまずありえないですが。
list = g_list_append (list, "YAMAHA"); list = g_list_append (list, "HONDA");
for 文でコレをやると当然だけど全部同じ s ポインタを参照になる。
なのでデータを拾う毎にヒープに領域を作ってそのポインタを入れていく必要あり。
当然破棄も必須、C++ の std::string は全自動でやってくれているだけだし。
ただ知ってのとおり std::list は整数による添字アクセスができない。
というか何をするにもループ必須で正直使い勝手がよくない。
GList は一応こんなことができるようです。
gchar* c; /* 3 番目を表示 */ c = (gchar*)g_list_nth_data(list, 2); g_printf("%s\n", c); /* 3 番目を削除 */ c = (gchar*)g_list_nth_data(list, 2); list = g_list_remove(list, c);
STL を少し知っているなら直感的に書くことが可能、かつちょっぴり便利。
でも class は使えないからデストラクタで破棄とかはできないよってか。
むりやり std::list と同じにしようとしたのではないようで面白い。