【C++】STL(Standard Template Library)相談室 9
1 :
デフォルトの名無しさん :
2008/02/27(水) 02:03:30
7 :
デフォルトの名無しさん :2008/02/27(水) 09:50:04
てすと
C++0xでは typedef vector<int>::const_iterator CIT; for(CIT i = v.begin(); i != v.end(); ++i) { //............... } こんなことしなくて良いなんてよぉ〜 for(auto i = v.begin(); i != v.end(); ++i) { //............... } 素晴らしいじゃんかよぉ〜 禿考えたのぉ〜
template <typename T> typedef std::vector<T>::iterator auto; for (auto<int> i = v.begin(); i < v.end(); ++i) autoの癖にint宣言が必要だから駄目か という以前に(ry
for (auto i: v) にはならないのか
Dだとforeach(i; v)でいけるのを考えると、どうも見劣りがする
>>11 今は頑張ってもBOOST_FOREACH(i, v);か
禿はよく頑張ってるよ。うん。 この調子でどんどん奇怪な言語に仕上げてくれ。
SchemeやりはじめてからC++が糞に見えてきた。まさにやっつけ言語。
SchemeはC++で実装されてるんですよ
あれ?C++0xではさらにこうなるんじゃなかたっけ? std::vector<int> vec = { 1, 2, 3 }; for ( auto i; vec ) { std::cout << i << std::endl; }
まだドラフトには入ってないけど 検討されてはいたはず。
perlから帰ってくると for i ( 10, 15, 23, 8, 6 ) { cout << i << endl; } みたいなことを凄くやりたくなる
>>17 C++コンパイラはLispで実装されてるんですよ
LispはSchemeで実装されてるんですよ
24 :
20 :2008/02/28(木) 00:24:53
,..-──- 、
/. : : : : : : : : :: \
/.: : : : : : : : : : : : : : ヽ
,!::: : : : : :,-…-…-ミ: : :', マジかよ
{:: : : : :: : :i '⌒' '⌒'i: : :}
{:: : : : : : | ェェ ェェ | : :} ∩___∩
{ : : : : : :| ,.、 |: :;! /
>>23 ヽ
__ヾ: : : :: :i r‐-ニ-┐| :ノ | ● ● |
ゞ : :イ! ヽ 二゙ノイ‐′ | ( _●_) ミ
` ー一'´ヽ \ ,,-''"彡 |∪| __/`''--、
) |@ |ヽ/ ヽノ ̄ ヽ
| | ノ / ⊂) メ ヽ_,,,---
| .|@ | |_ノ ,へ / ヽ ヽノ ̄
| |_ / / | / | | ヽ_,,-''"
__|_ \\,,-'"\__/ / ,────''''''''''''''"""""""
~フ⌒ ̄ ̄ ~ヽ ヽ  ̄ ̄"""'''''''--、""''''---,,,,,,__
/  ̄''、|ノ )ヽ
___/  ̄ ̄) / |___
>>23 --、 _____ -丶
|;;;/::::::::::::::::::::::::::::::/ |
// ̄,'' ̄ ̄\:::::::'''',,,丿
/-=・=- -=・=- _|:::::::::::::\
/ゝ ▼ <:::::::::::::::<:::: ̄--_
---┼/ 、 -─-\--<::::::::::::::::::::-_ ふーん
--─\ ⌒  ̄ ̄ ̄ゝ::::::::::::::::::::::::::::::::::::::::-_
\__ ゝ/::::::::::::::::::::::::::::::;;;;;;;;;;;::::::::::::\
,,ノ 丿:::::::::::::::::::::::::/:::::::::::::::::::::::::::::::::::|
> /:::::::::::::::::|::/::::::::::::::::::::::::::::::::::::::::::::|
>.,. /::::::::::::::::::ノ;;/:::::::::::::::::::::::::::::::::::::::::::::::::| ____________
/:::::::::::::::::::ノ;;;;|::::::::::::::::::::::::::::::::::::::::::::::::::::|__-||||||::::||||||::::||||\
/::::::::::::::::::/;;;;;;;|:::::::::::::::::::::::::::::::::::::::::::::::::::::|::::|||||||:::||||||:::||||||::::::
(!!!!!!(:::::::::::::::/ ;;;;;;;;;;;;|::::::::::::::::::::::::::::::::::::::::::::::::::::/::::|||||||:::||||||:::|||||||::ノ
(!!!!!!!!!!!!!ノ (lllllllllllゝ:::::::::::::::::::::::::::::::::::::::/-- ̄  ̄
,,,,ヽ::::::::-ゝ:::::::::::/
(!!!!!!!!!!!!!!!!!!!!ノ
LoadFromFile/Save〜、 LoadFromStream/Save〜、 みたいな入出力は、 STLではどうなっていますか?
>>26 fstream, istream, ostream とか
28 :
26 :2008/02/28(木) 11:35:28
さんks メモリプールはどんな感じで実装すれば良いのでしょう? fstreamで読みながら、メモリサイズを増やすと、劇遅な機ガスので。
>>28 いきなりメモリプールって言われても何のことだかわからん。
読みながら増やすのが嫌なら読む前にファイルサイズで確保すれば
「プール」とか要らんだろ。
ストリームを読む場合なんかだと、最初にサイズが分かりませんが、 効率的なプールはどうやったら作れますか?
>>30 サイズが分からないという前提なら、読みながらメモリ確保が必須なのはしょうがないだろ。
「効率的な」というのが「読みながらメモリ確保しない」という意味でないのなら、説明して
もらわないとわからん。
>>28 漠然とし過ぎていてなんとも。メモリプールを最適化するのに実測なし
で議論するのは簡単ではないと思う。
STLはメモリプールですが?
STLを使って、 LoadFromFile/Save〜、 LoadFromStream/Save〜、 がある、 メモリプールの実装教えれ!
assignだけで、ファイルがメモリに展開されるの? ↓ #include <vector> #include <map> #include <string> #include <istream> #include <iterator> #include <fstream> #include <cstddef> #include <exception> #include <iostream> typedef std::vector<char> memory_type; class pocket { std::map<std::string, memory_type> naka; public: void ireru(std::string const& filename) { std::ifstream file(filename.c_str()); file.exceptions(std::ios::badbit | std::ios::failbit); naka[filename].assign(std::istreambuf_iterator<char>(file) , std::istreambuf_iterator<char>()); } }; int main(int argc, char* argv[]) { try { pocket pocket; for (int i = 1; i < argc; ++i) { pocket.ireru(argv[i]); } return EXIT_SUCCESS; } catch (std::exception const& e) { std::cerr << e.what() << std::endl; return EXIT_FAILURE; } }
やってみたらわかるんでない?
>>38 範囲指定イテレータのassignだよ。vector, deque, list, stringにある。
void container_type::assign(InputIterator b, InputIterator e);
istreambuf_iteratorで検索したら分かりますた。
ttp://ml.tietew.jp/cppll/cppll/thread_articles/3804 >stringのコンストラクタはiteratorを取れるんですね。
>ifstream fs(path);
>s= string((istreambuf_iterator<char>(fs)),
>istreambuf_iterator<char>());
1行でLoadは分かりましたが、逆に対になる1行でSaveするにはどうすれば良いでしょう?
42 :
41 :2008/02/28(木) 13:24:42
それと、stringによるLoadだとテキストファイル対象のようですが、 バイナリファイルだとどうなりますか?
vector
>>41 string s("unko benki");
ofstream ofs("koumon.txt");
copy(s.begin(), s.end(), ostreambuf_iterator<char>(ofs));
>>44 >ostreambuf_iterator
の使い方サンks。
次バイナリファイルの場合キボン。
これが分かれば、LoadFromFile/SaveFromFileメソッドを実装して、今日は定時でさっさと帰ります。
>>42 istreambuf_iteratorはバイナリ入力(sgetc, sbumpc)なんだが。
>>45 ostreambuf_iteratorはバイナリ出力(sputc)なんだが。
詳しくは、ストリームバッファクラス。
>>46 なるほど、
vector<char> Memだったとして、
ファイルストリームfsを作って、
のistreambuf_iteratorをfsから作って、
Memに代入すれば良いのですね?
ってイマイチ書き方が分からない。
コンパイラに相談しながら書いてみます。
イテレーターって難い。
thx
>>47 >ストリームバッファクラス
あ、これ未調査だった。
やっぱ、ストリームの基底クラスがあるんだね。
それが分かれば分かる筈。
>>49 ストリームクラスの基底クラスではない。
継承関係にはない。
ストリームバッファクラス(basic_streambuf<>)のオブジェクトへの
ポインタを保持している。
テキスト版は出来ますた。 //--------------------------------------------------------------------------- bool Test::LoadFromFile(const char *filepath, bool bAdd) { ifstream fs(filepath); string SBuf((istreambuf_iterator<char>(fs)), istreambuf_iterator<char>()); //stringからバッファへロード } //--------------------------------------------------------------------------- bool Test::SaveToFile(const char *filepath) { string SBuf(Text()); //バッファからstringへセーブ ofstream fs(filepath); copy(SBuf.begin(), SBuf.end(), ostreambuf_iterator<char>(fs)); } //---------------------------------------------------------------------------
>>51 ファイルのオープンに成功したかどうかは
チェックせんの?
伸びてると思ったらまた宿題の続きかよ
>ファイルのオープン //--------------------------------------------------------------------------- bool Test::LoadFromFile(const char *filepath, bool bAdd) { ifstream fs(filepath); string SBuf((istreambuf_iterator<char>(fs)), istreambuf_iterator<char>()); if (!fs.is_open()) return false; //stringからバッファへロード if (fs.bad()) return false; if (fs.fail()) return false; return true; } //---------------------------------------------------------------------------
あ、やっぱこう。 //--------------------------------------------------------------------------- bool Test::LoadFromFile(const char *filepath, bool bAdd) { ifstream fs(filepath); string SBuf((istreambuf_iterator<char>(fs)), istreambuf_iterator<char>()); if (!fs.is_open()) return false; if (fs.bad()) return false; if (fs.fail()) return false; //stringからバッファへロード return true; } //---------------------------------------------------------------------------
少しはマニュアル読め コード読んでるこっちが恥ずかしくなるわ
if(!fs) でいいだろ
ラジャ! //--------------------------------------------------------------------------- bool Test::LoadFromFile(const char *filepath, bool bAdd) { ifstream fs(filepath); if (!fs) return false; string SBuf((istreambuf_iterator<char>(fs)), istreambuf_iterator<char>()); if (fs.bad()) return false; if (fs.fail()) return false; //stringからバッファへロード return true; } //---------------------------------------------------------------------------
やっぱ、バイナリの場合、書き方分かりません。 既に、 >vector<char> Memory ってのが存在していた場合は、 上の書き方のままだったらロードするときのメモリは別にとって、次に、Memoryにコピーしなきゃならないのでしょうか? それだと、メモリ2倍で勿体ないような。
>>59 vectorに読み込みたいのか?
ならvectorにも同様のコンストラクタがある。
61 :
59 :2008/02/28(木) 15:48:05
あ、そうではなくて、既に存在しているvectorにロードしたい場合は、ですが。 もしかして、 >vector::swap でおk?
>>61 assign では駄目なのか?
なんか基本があやしいふいんきだから
Accelerated C++ くらいは目を通した方がいいと思うんだが。
>>61 Memory.assign((istreambuf_iterator<char>(fs)), istreambuf_iterator<char>());
vector<char>(Memory).swap(Memory);
64 :
59 :2008/02/28(木) 16:05:38
>>62 ふいんきでヴぁれました?
>>63 回答サンks。
上の1行で良いように見えますが、上下2行でセットですか?
まずは、assignぐぐってみまつ。
チャットじゃないんだから少し頭ん中整理してから投下してくれ
>>59 おまえ C++Builderスレでも同じ様なこと書いてる奴だろ?
バイナリの方、整理しますた。 //--------------------------------------------------------------------------- クラスヘッダー: std::vector<char> Memory; //--------------------------------------------------------------------------- bool Bin::LoadFromFile(const char *filepath, bool bAdd) { ifstream fs(filepath, std::ios::in | std::ios::binary); if (!fs) return false; fs.seekg(0, std::ifstream::end); Memory.resize(fs.tellg()); fs.seekg(0, std::istream::beg); if (fs.bad()) return false; if (fs.fail()) return false; fs.read(&Memory[0], Memory.size()); fs.close(); return true; } //--------------------------------------------------------------------------- bool Bin::SaveToFile(const char *filepath) { ofstream fs(filepath, std::ios::out | std::ios::binary); if (!fs) return false; copy(Memory.begin(), Memory.end(), ostreambuf_iterator<char>(fs)); if (fs.bad()) return false; if (fs.fail()) return false; return true; } //---------------------------------------------------------------------------
69 :
59 :2008/02/28(木) 17:06:08
>>67 自分もそう思ったが、よくよく見ると違った。ていうか、あっちの方がラベルが高くて難しい単語が出てくるおw
鼻血ブーーーーーーーーーーーーーーーーーーー うんこブリブリブリーーーーーーーーーーーーー
>>69 いや、それじゃねえな。 偶々std::を使ったレスを持ち出して、 話のはぐらかしか?
>>72 解説文も解読できないんならおまえ向いてないよ。 工場のライン工やっとけ
のびてると思ったら… C++って学校の宿題スレなかったっけ?
>int toupper(int); >int tolower(int); > std::transform(str.begin(),str.end(),str.begin(),toupper); >: error: no matching function for call to 'transform(__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unknown type>)' これでもエラー出るんですよねorz
ゴメンなさい、 > (int (*)(int))std::toupper に直してませんですたorz
マクロの場合があるからと違うんか
>>77 違う。localeを引数に取る多重定義があって、それと曖昧と言われてしまうため。
関数オブジェクトを使うべき
typedef std::map<char, void*> MyMAP //void* にはMyMAPのポインタが入る このようにmapに自分と同じ型を含めたい場合は、どう書くのがスタンダードでしょうか? 今はnewで確保して入れて、(MyMAP*)にキャストして使用&deleteしてるんですが。
>>80 typedef だと無理っぽいねぇ。 class で囲ってやるか、意味的に奇怪だけど継承するとか。
struct MyMap : std::map<char, MyMap*> {};
今、軽く衝撃を受けたわ
>>81 >struct MyMap : std::map<char, MyMap*> {};
そんな事ができるとは思いもしなかった
例えば、vectorってベクターって呼んで、vectorクラスなんて呼ばないけど、 STLってできあがるものってクラスなんだね。
>>85 いいえ。コンテナだけがSTLではありません。
え”? STL = コンテナ ∩ イテレーター ∩ ?
つ[<algorithm>, <numeric>, ...]
>[<algorithm>, <numeric>, ...] こういうのって何て呼ぶんだ? インライン関数群?
なぜ何でもカテゴライズしたがるんだか
>>89 インクルードファイルalgorithmやnumericで定義されている関数
>>90 日本人だからでしょ
テンプレートだけに型に(ry
boost::type_traits早く標準化汁
標準アルゴリズムって言葉使わないか?
いやまて朝鮮人かもしれんぞ ことによると中国人かも
std::wstringに入ってるファイル名があるのですが、 ここから拡張子だけを抽出したい場合、定番の方法などあるのでしょうか?
rfind と substr でいけるんじゃね? まあ c_str と _splitpath() のほうが面倒が少ないと思うけど。
Win32APIが使えるなら一発
100 :
デフォルトの名無しさん :2008/03/03(月) 16:27:08
>>97 std::stringにファイル名が入ってるなら
そのファイル名が入ってるstd::string型のオブジェクト名
がfilenameという名前とすると
char *fname = filename.c_str();
てな感じでchar *型で受け取り
#include <cstring>をインクルードしておき
char *piliod = strrchr(fname,'.');
で拡張子の手前のピリオド位置を取得し
piliod++;ってすれば拡張子名だけchar *型で取得できる
これらの操作をwchar_t用の関数に変更すれば
wchar_t *型で拡張子名を取得できる
まぁ、STL板だしstd::wstringを操作するとしたなら
素直にクラスのfind_last_of使って
sizetype pos = filename.find_last_of(L'.')てな感じで
けつからピリオドの位置見つけてpos++;して
std::wstring fextenshion =filename.substr(pos)とすれば
拡張子だけ手に入る
が、特殊ケースを想定するとそれだけでは済まないので、 ちまちま書くよりc_strでランタイムやAPIの既存のルーチンに任せるのが定番。
だよなぁ。hoge\2007.11.10\bar とか。
103 :
デフォルトの名無しさん :2008/03/06(木) 14:54:51
>std::vector<char> resultBuf; から、 >std::string SBuf; にデータを移すにはどう記述したら良いですか? SBuf = resultBuf; とするとコンパイルエラーです。 インテリセンスの無い環境でやっててつらいです。
>>100 char *fname = filename.c_str();
これは、不味いんじゃないのか?
>>103 SBuf = &resultBuf[0];
106 :
103 :2008/03/06(木) 15:20:33
>>105 有難うございます。コンパイル通りました。
ついでですが、resutlBufにNULLが入ってる場合、どう書けば良いですか?
今回不要なんですが。
memcpy使うのもC言語っぽいしぃ。
std::string SBuf(resultBuf.begin(), resultBuf.end());
または、
SBuf.assign(resultBuf.begin(), resultBuf.end());
resultBufがnull終端なら
>>105 でもいい
>>105 stringの内部バッファの連続性はまだ保証されてない気がしたが。
>>108 それは関係ないだろ
string s = "foo";
とかやるのと一緒
>>108 resultBufは、char型のvector
vectorはバッファの連続性を保証されているから無問題
問題があるとすれば、
>>107 の指摘の様にnull終端では無い場合
111 :
103 :2008/03/06(木) 15:42:13
NULL入りの場合、無しの場合、両方分かりました。 ありがとうございましたorz
>>108 それよりも、
>>104 の指摘している
>>100 char *fname = filename.c_str();
の方がやばいんじゃない?
*fnameの代入が終了したら、c_str()の戻したポインタの有効期限が切れているから
char *piliod = strrchr(fname,'.');
の処理をするときには、何が起こるのか判らない状態になっていると思うんだけど
>>112 filename.c_str()で返るポインタは、filenameの非constメンバ関数が呼ばれるまで有効
>>105 だとresultBufが空のときにまずいような気がする
null終端なら空ってことはありえない
>>113 お前そんなプログラム書いてるのか。お前には仕事を任せられんな。
>>113 まじ?
ゴミになったのに、ゴミになったって気が付いてないとかそう言う問題の気がするが...
lstrcpy(buf, str.c_str());
これは怖くないが
char *word = str.c_str();
lstrcpy(buf, word);
これは、いつ見ても、ヤバイ香りがするんだ
関数の返すポインタには何度も煮え湯を飲まされたし...orz
>>116 >>117 >>113 is right.
About c_str()
The return value is valid only as long as the string exists, and as long as only
constant functions are called for it.
>>118 言い訳はいいからお前には仕事はやらん。
>>116 お前のレスだけ明後日の方向むいててワラタ
>>116 「そんなプログラム」ってどんなプログラム?
>>113 はプログラムの書き方なんか一言も触れてないよね。
c_str()の戻り値の寿命についての情報を書いてるだけ。
「そんなプログラム」ってどんなプログラム?
それは113のどこに書いてあるの? 教えて。
煽ってるようだけどその手には乗らないよ。 びびりまくりでワロタw
ちゃんと寿命を理解しないで使う方が怖いよ
仕様をちゃんと知らずに見よう見まねでライブラリを使う人ってのは結構いるだろうけど、 見よう見まねや雑談で得た俺仕様を根拠にして、正しい仕様に基づく使い方を攻撃するのは みっともないと思う。
うっかり誰かがstring書き換えるコードを途中に入れてしまったら、 なんて心配をするようなら、116の言うことだって分からなくもない。
どうでもいいが、 >lstrcpy(buf, str.c_str()); これと >char *word = str.c_str(); >lstrcpy(buf, word); これで振る舞いが異るようにc_strを実装する方法は存在しないだろ
>>117 >関数の返すポインタには何度も煮え湯を飲まされたし...orz
仕様を確認せずに「香り」でコード書くから何度もそういうミスを繰り返すのかもね
仕様仕様言ってて仕事がもらえない方が悲惨だと思わない? 会社にはその会社の流儀って物があってね。
>>126 >lstrcpy(buf, str.c_str());
は、lstrcpyの処理が終わるまで、誰もstrを変更しないことが保証されている。
>char *word = str.c_str();
>lstrcpy(buf, word);
は、どこかの禿が
>char *word = str.c_str();
>f(str);
>lstrcpy(buf, word);
と変更しない保証は何処にもないし、f(str)がstrを変更しない保証も無い
んでその流儀に従って何度も煮え湯を飲まされるわけ? なんかバカらしいぞそれ。 仕様をよく確認しなかったが、流儀に従って安全そうに書いたので 救われたって話ならわかるけど。
まったく、ひどい論点のすり替えだぜ。
>>130 お前ニートか無職だろ。
協調性がゼロみたいだもん。
>>129 そんな話はしてねーよ
前者と後者で振る舞いが異なるはずがないと言ってるだけ
いや個々の会社が
>>100 みたいなのを禁止するのは勝手だけども、
>>100 みたいな使い方が仕様に照らして問題ないという事実は変わらないだろ
>>132 ちゃんと働いてるし、給料も沢山もらってるから心配スンナ
世の中はそんな妙な流儀を押し付けられるような職場ばかりじゃないってこと
未経験高卒ですがC++で仕事したいです
>>133 それはわかる。
ただ、俺から見れば117がやばい香りを感じるのは
129のような可能性があるからというのが最大の理由ではないかと思う。
>>137 全く持って同意
同一データに、2通りのアクセス方法があると、間違いを起こす元になると思う
>>137 なるほど、そういう見方もあるか
俺は、
>>117 がC++の実行モデルをあやふやにしか理解してないとか、
文を跨ぐと一時オブジェクトの寿命が切れるのと混同してるとか、そんなのを想像してた
それに、「ゴミになったのに」云々言ってるから、そのままのコードでもポインタが無効になるのを危惧しているように読める
イテレータだって挿入削除で無効になるんだから、 特別神経質になるほどのことでもないと思う。
>>138 そういう意味では、イテレータも基のstringがconstでない場合は、
おちおち使っていられないよな。
例えばだけど、本質的にはこの2つに違いはないと思った。
(もちろん文字列中に\0はないとして)
char const* p = std::strchr(s.c_str(), 'a');
std::string::const_iterator it = s.find('a');
赤福の賞味期限偽装に近い問題やね 賞味期限はいつか本当に切れるだろうが、それは今じゃない...
143 :
108 :2008/03/06(木) 18:06:14
resultBufがstringだと勘違いしてた
今更だなw だが正直でよろしい
>>116 は真性の馬鹿者
仕様を初めて知って、これからはいかにも前から知ってましたよって顔で
他の人にこの問題を説明するだろう。
>>146 このスレではどうでもいいことだけどな。
ところでc_str()をchar*に入れてるのは誰も突っ込まないんだろうか。
確かに、そういう人には仕事任せたくないなw
それ以前にコンパイルエラーになると思うが
std:stringのバッファの連続性が保証されることは、&str[0]とstr.c_str()のアドレス同一性を保証しますか?
保証しない。 c.str を呼んだ場合、メモリの最確保が行われる可能性がある。
なるほど。str.data()はどうでしょうか。
残念ながら data も同じ。
しかしなんだな。 今の規格ではバッファの連続性を保証していなくて、 次の規格ではバッファの連続性を保証する予定ではあるのだが、 連続性を保証したら data で参照、ポインタ、イテレータが失効する可能性は もう無くなるとしてもいいような気がするんだけど、 最新のドラフトではそうなってないんだよな。 ミスなのか、それとも何か深い理由でもあるのか・・・。
>>155 正直プライオリティ低いんだろ
どうでもいいわと思ってる委員が多いと予想
しかし、そろそろそういう細かいところも詰めていかないと、 0x の x は16進数ってのもあながち冗談では済まなく・・・。
いざとなったら得意のundefined behaviorでいいだろ。
やたらスレが伸びてると思ったら・・・
もうここの連中には仕事任せられんな
今後は
>>170 にすべてを託すこととする
なお異論は受け付けない
それは無意味にkskしろってことかい
string::swap について教えて下さい。 >void func(string &sArg) > string sBuf = "AAAAAA"; > sBuf.swap(sArg); のときって、sBufの内容がsArgに移し変えられるっていうのがswapの機能だと思います。 この場合、実装に依存するんだと思いますが、 メモリのエリアがガバっとコピーされるのではなくてクラスの参照を交換してくれるんでしょうか? 性能的に優れてるものだったら、使いまくりたいですし。 一度も使ったこと無いので、swap後にちゃんとメモリ保持しててくれるんだろうか、 落とし穴は無いだろーななんてガクブルしてます。
>>161 stringだったら、内部で保持しているであろう
文字列へのポインタや長さなどといった変数だけが交換されるとみな仮定している。
一般的に、swapは例外を投げないとされており、
しかも、std::stringのswapはO(1)と規格で定められている。
だから、文字列の中身まで交換する実装はありえない。
163 :
161 :2008/03/07(金) 10:29:50
サンクス。 >一般的に、swapは例外を投げないとされており、 へぇー、勉強になりました。 >しかも、std::stringのswapはO(1)と規格で定められている。 勉強になりましたが、O(1)って何だ?_? >だから、文字列の中身まで交換する実装はありえない。 あ、そうなんですか? 例外を発生できないとなると、参照を交換する以外に実装無いと思うんですが。 だって、交換じゃなくてコピーならば、メモリを確保しないといけないし、そうなるとエラーが発生する可能性があるような。 って素人なのに生意気逝ってすみません。
O(1)というのは、例え文字列が長くてもswapが一定時間で終わらなければならないってこと。
文字列をコピーするなら、文字列が長くなればそれだけコピーに時間が掛かるから、この制限を満たせない。
詳しくは「計算量」でググれ。
>例外を発生できないとなると、参照を交換する以外に実装無いと思うんですが。
まさに
>>162 はそう言ってるんだと思うよ。
中身をコピーして交換するんじゃなくて参照(具体的にはポインタ)を交換する。
165 :
161 :2008/03/07(金) 10:40:31
ラジャ! >文字列の中身まで交換する実装はありえない。 つまり、中身をコピーする実装はありえない、って文章ですね。 で、そう言い切れる理由はO(1)で時間制限してて、”ま、参照を交換する実装にしる!”、っていわば指令が出てるわけですね。
>>165 deep copyをするとno throwの保障ができなくなる。
167 :
161 :2008/03/07(金) 11:00:02
すみません、教えてクンですみませんが、最後に記述を教えて下さいorz swapを使いまくりたくなりました。 vector<char>とstringの間で、swapする記述はありますでしょか? vectorメモリは連続しているので、vector同士だとswapできるんじゃないかと思ったのですが。 直にメモリアクセス?イテレータンを無視し過ぎるのも良くないとは思わないでも無いですが。
>vector<char>とstringの間で、swapする記述はありますでしょか? ない。実装上も、例えばstringがnull終端の分だけ余計に内部バッファを持っているなら無理。 >vectorメモリは連続しているので、vector同士だとswapできるんじゃないかと思ったのですが。 vector同士ならできる。
169 :
161 :2008/03/07(金) 11:09:58
>ない。実装上も、例えばstringがnull終端の分だけ余計に内部バッファを持っているなら無理。 なるほど。納得。下手にやるとはまりますね。 >vector同士ならできる。 vectorの異なる構造体同士でもできますか? 記述例超キボンw
テンプレートパラメータが違うとダメだろう
記述例もなにも、vとv1が同じ型のvectorなら、 v.swap(v1); で交換できる。vectorに限らずあらゆるコンテナで。
172 :
161 :2008/03/07(金) 11:36:47
全部分かりました。有難うございましたorz つまり、コンテナが違うとswapはキャストやらなんやらやヴぁい記述になるわけですね(はまるからやらないけど)
質問です。 クラスメソッドの引数で、 >method(string s1) { method(s1.c_str()) } >method(const char *s1); みたいな感じで、オーバーロードで「string」も「char *」も両方受け入れるようにしてるんですが、 どちらか片方だけ定義、ということにできますでしょうか?
174 :
173 :2008/03/07(金) 13:15:17
2つ要るとしたら、stringベースとchar*ベースと効率が良いのはどちらでしょう? まぁ、大差無いですか?
>>173 stringだけ書いとけばconst char*からstringを暗黙に構築してくれると思うが、効率は良くないかも
>>173 片方がconst char * なんだから、string const & の方がいいんでないかい?
で、どっちみちstringを受ける方もconst char * 版を呼び出すなら要らないわけで。
177 :
173 :2008/03/07(金) 13:37:33
何だ、そうでしたか。無駄に2つ作ってしまったorz
178 :
173 :2008/03/07(金) 13:42:12
頭が混乱してましたが、 >stringだけ書いとけば の場合は、引数が入力である場合は、おk、 >片方がconst char * なんだから、string const & の方がいいんでないかい? これ(つまり、& )を選択した場合は、2つ書かないといけないんですよね? コンパイラで試せば良いのですが、皆さん普通はどうされてるのか知りたくて。
>>178 わけがわからん。何がしたいのか書きなおしてくれ。
180 :
173 :2008/03/07(金) 13:48:53
ごめんなさい、テストプログラム書いたら違っていました。 つまり、 >stringだけ書いとけば でおk。 >string const & の方がいいんでないかい? でおk。 但し、char *を渡すと、W8030 Temporary used for parameter のウォーニングが出ると。
話を読む限りstringやconst char*である必要性を感じないし、 俺だったら初めと終わりのイテレータを引数に取るようにする。 stringでもconst char*でもないやつもかかってこい。
182 :
173 :2008/03/07(金) 13:53:05
あ、「「string &」だとウォーニングだったのが、「string const &」だとウォーニング消えました。 つまりやりたかった、 >string と char *の一本化、 および、 >参照渡しでメモリ節約&コンパイルウォーニング無し の全て解決しました。orz
183 :
173 :2008/03/07(金) 13:54:45
>俺だったら初めと終わりのイテレータを引数に取るようにする。 はつみみです。 これ知っとくと大分楽できそうですね。何が良いのか調べてみます。 (参考サイトでも何でも教えて頂ければ参照します。レスで教えてというのも嫌われそうなので)
string const &が要求されてるところにconst char *を渡そうとしたら、stringの一時オブジェクトが作られて、 文字列の内容がコピーされるから、メモリの節約にはなってない
185 :
173 :2008/03/07(金) 14:20:17
>>184 あっ、そーですか。
じゃぁ、今まで作った基礎クラスはそのままに2つのままにしておこうかなぁ。。。
悩む。
186 :
173 :2008/03/07(金) 14:58:05
今、上記内容に沿って、”string const &型”に全面書き換え中ですが、 以外に頭が固いのが、stream系ですね。 っていうか、ifstreamとか引数にstring受け入れないっぽい。
>>186 コードを書く前に、もう少しきちんと勉強したほうがいいと思います。
class StringArg { const char* p_; public: StringArg(const string& str) : p_(str.c_str()) {} StringArg(const char* str) : p_(str) {} const char* get_arg() const { return p_; } }; method(const StringArg& arg);
189 :
172 :2008/03/07(金) 16:49:34
>>188 はじめそれに近い形で書いてたんですが(違いはstring側はconstにしてなかったとこだけ)、
メソッド宣言2行になると、以外にクラス部品作るのがしんどくて。
効率悪くても1つにしたいな、と思いました。
で結局、
>StringArg(const string& str)
の方だけ活かして、
巨大なバッファで、かつ、char *の可能性がある場合のみは、188 の通り、
2つ宣言しようかと思っています。
↑ 172じゃなくて、173でした。
>>189 多分お前は
>>188 を誤読してる
const char *をとるメソッドもconst string &をとるメソッドも用意せずに、
const StringArg &をとるメソッドを用意しろってことだろ
void Method(const char*); のみ用意して、 std::stringを渡したい場合は↓じゃあかんのか std::string s; Method(s.c_str());
193 :
デフォルトの名無しさん :2008/03/08(土) 20:47:51
#include <set> using namespace std; int main() { set<int> s; s.insert(1); s.insert(4); (*s.begin()) = 5; return 0; } 上のプログラムは違法ですよね? ウチのコンパイラは文句を言わないんだけどおかしいですよね?
ふぁっきんBCC
>>193 Effective STL 第22項をどうぞ。
198 :
デフォルトの名無しさん :2008/03/08(土) 21:12:44
>>196 サンクス。STLってたくさん欠陥があるんですね。
>>197 サンクス。今度立ち読みします。
stringにバイナリ書き込みで、 resizeした後、・・・1 c_str()でポインタ取って、・・・2 memcpy・・・3 してます。 2ってSTL的には読み込み専用ポインタであり間違ったコードなんですが、 動作してるのでほっとこうか、正しく書こうか迷ってます。 どうしたら良いでしょう?
>>199 間違ったコードを正しく書くのに、何を迷うの?
>>199 必要な知識は全部持ってるみたいだが、何を訊きたいんだ?
未定義動作に依存するという欠点よりもそのコードが持つ利点が大きいと考えるなら
それを使い続ければいいし、そうでないなら書き換えればいい
いろいろ。 じゃ、直しておきまつ。
コンストラクタやassignとかappendがあるもんな。 イテレータにstd::copyでもいけるし。
>イテレータにstd::copy イテレータンって参照するだけじゃないんだ。 イテレータンがメソッド持ってるって考え方がイマイチわかんないんだおね。
いや、イテレータを引数に取れる関数だろ
イテレータは何かを反復するもの。「何か」は参照かもしれないし、操作かもしれない。
207 :
デフォルトの名無しさん :2008/03/11(火) 20:59:59
ifstreamで半角空白を含むファイル名や、日本語を含むパスで ifstream ifile(フルパス名);で失敗してしまうのですが、これは仕様なのでしょうか? 仕様なのでしたら回避策はあるのでしょうか? Visual Studio 2005SP1を使用しています。 よろしくおねがいします。
問題が再現する最小限のコードを貼れ。まずはそれからだ。
ロケールの設定とか?
コンパイルはVisualStudio2005 Command Promptで行いました。 #include <iostream> #include <fstream> #include <windows.h> using namespace std; int main(int argc, char **argv) { ifstream ifile("新規テキスト ドキュメント.txt"); if(ifile) { MessageBox(NULL, "success", "info", MB_OK); ifile.close(); } else { MessageBox(NULL, "failed", "info", MB_OK); } return 0; } 結果はfailedとでます。
間違えました。 フルパス名をコピペして、\を一つ減らしてエクスプローラーに貼り付けると正常に開けます。 ifstream ifile("d:\\新規テキスト ドキュメント.txt");
まさか、そのファイルがカレントディレクトリに置いてないとか言わないよな? つーか、このスレより環境依存OKのスレかWindows関連のスレの方がいい希ガス。
ありがとうございます。 環境依存スレに行ってみます。
214 :
デフォルトの名無しさん :2008/03/12(水) 03:34:34
vectorに要素をpush_backするとき、全ての要素がこっそりと引越し、 要素を指していたポインタが無効になり、ひどい目にあうことが あるということを知りました。 そこで質問なのですが、引越し時の要素のコピーは コピーコンストラクタを使って行われるのでしょうか? それとも単純にmemcpyなどで行われるのでしょうか?
>>214 コピーコンストラクタじゃなきゃヤバイでしょ。
あくまで例だけど、int型のメンバxと、そのアドレスを持つint*型のメンバpxがあって、
pxの値をmemcpyなんかした日にはえらいこっちゃ。
コピーコンストラクタでpxをdeep copyしてなければ同じようにえらいこっちゃ。だけどね。
>>214 再割り当て時にはコピーコンストラクタが使われるよ。
221 :
217 :2008/03/12(水) 08:01:58
deep copy するわけじゃないのか。215が言いたいのは。 コピーコンストラクタでpx=&xが必要ってことだな。多分。
STLはコピーを前提に作られている。そういうもの。
>>221 コピーコンストラクタという言葉を使っているところからして、
ユーザー定義型がvectorにどう扱われるかを訊きたがってるんだろうな、と判断した上で、
「コピーコンストラクタを用いなければ"正しく"コピーできない型があり得るのに、
vectorが内部で勝手にmemcpyによるコピーで満足しちゃうなんてことは無いよ」
って回答した次第。
>>223 規格に"引っ越し"という言葉は書いてないという揚げ足をとってるのか?
それとも単にC++を知らないだけ?
227 :
217 :2008/03/12(水) 09:01:52
I got it. 関係ないけどクラスをmemcpy、memcpyするソースをよく見かける。怖くて仕方ない。
228 :
217 :2008/03/12(水) 09:02:25
memset、memcpyだった。
怖いじゃなくて、memsetだとプログラム落ちるだろ、jk
そういうのはCのノリが抜け切れてない年寄りが多いの?
231 :
217 :2008/03/12(水) 09:15:12
>>229 落ちるとは限らないよ。仮想関数がないクラスではうまくいく。(memsetでセットする値が適切なら)
仮想関数があるクラスでmemset(this,0,sizeof(this))とかやると
仮想関数ポインタが0になるので、
ポリモーフィズム使用時にNULLポインタアクセスで落ちた。
だから抽象クラスにしたいときには、memsetしてないか全部チェックせなあかんかった。
>>230 そうだね。特に組込系が多いね。クラスを構造体の延長として使ってる。
232 :
217 :2008/03/12(水) 09:22:43
tp://sunlight.cocolog-nifty.com/sunlight/2006/11/class_56c5.html こういう変なことする人もいる。class S が 仮想関数を持つクラスをメンバ変数に持ってたら ダメじゃんって突っ込みたい。 スレ違いでゴメン!
突っ込みたいなら突っ込んであげればいいのに
引っ越しって言えば、moveだろ。 copyを引っ越しと言うのは無理があり過ぎる。
237 :
217 :2008/03/12(水) 15:43:34
自分は暗黙のインストラクタでいいのでw
>>235 「copyを引っ越しと言」ってるようには見えないよ。「引越し時の要素のコピー」って書いてある。
コンピュータデータのmoveは、実際には「copyする」ことと「元を削除する」ことで成り立っているわけで、
つまり「move(ここではvectorの要素の再配置のこと)の手段としてのcopy」の表現だろう。
コピコンでは普通は deep copy する。 そういうもの。
参照カウント付きハンドルの場合はそうじゃないけど。 (boost::shared_ptr etc)
それは特殊例
242 :
デフォルトの名無しさん :2008/03/14(金) 00:11:29
インストラクタwww
243 :
214 :2008/03/14(金) 01:02:08
レス遅れてすみません。解答してくださったみなさん、
ありがとうございます。
でも、*ほとんどの* ケースでは、単純なmemcpyで済みそうなのに、
いつでもコピーコンストラクタが使われるという仕様に疑問を感じます。
コピーコンストラクタが使われるとなると、コピー元のオブジェクトに
対してデストラクタを呼び出す必要があります。これは、*ほとんどの*
ケースでは全く馬鹿馬鹿しい無駄です。
それならreserve使え、とおっしゃるかもしれませんが、どれだけの
領域をreserveしておけばいいのか、前もって計算できないことも
よくあります。
引越し時のコピーはmemcpyで行われるべきではないでしょうか?
>>215 さんが出した例のような場合、ユーザーはreserveを使います。
どうでしょう? だめ?
allocatorを指定するとか。
>>243 そう、毎度コピーするのは無駄と誰もが思ったから、
今度の規格改定でムーブセマンティクスというものが導入されようとしている。
インフラはmemsetやらをやたら使うよ アーキテクチャ依存すんだからOOPは役に立たん ドメインでアーキテクチャ依存せんようにするにはやむえない …が、インフラのC型記述は拡張子.cにして欲しい イヴァーヤコブソンはそんなユースケース駆動モデルを奨めている STLですらQACでNGになられたんじゃ参るストーン
>>245 彼が不満に思っている状況の大半では,
move semantics は何の改善ももたらさないのでは?
そうか?移動なら、コピーに比べ格段に低コストだし、 前のオブジェクトのデストラクタは実質やることなくなる。 こういう問題だと思っていた。214が納得するかどうかは別としてだけど。
>>248 memcpy によってコピーできるオブジェクトというのは,
(C++0x において条件が緩和される) POD 型のオブジェクトに
およそ相当すると思いますけれど,これらのオブジェクトに対しては
コピーの操作と (move semantics でいうところの) move の操作は
同じ操作になると考えられるので「move semantics によって改善される」というのは
まずいのではないかな,と.
デストラクタに関しても, move を使っても copy を使っても
「実質やることがない」のはなんら変わりはないと思います.
>>249 ああ、たしかにPODだとそうだね。
言葉足らずですまん。俺は非POD型を入れることことを考えていた。
というのも243でデストラクタを呼び出さなければならないと言っているから、
214=243は非POD型を念頭に置いているのだと思ったため。
>>243 手元のVC8ではvector<char>とかvector<int>ならmemmoveを使ってくれたよ。
アラインメントを考慮してrep movsdで転送。
struct Foo{int a; int b;}; vector<Foo>だと単純にループ1まわりにつき
8byte転送するようなコードになってた。
PODを判定できれば両方memmoveに出来るんじゃないかな。
わかってない子が来た
253 :
251 :2008/03/14(金) 13:03:30
ん、俺のこと?
俺はただ、
>>243 がpush_backでのバッファ拡張時にmemcpyやmemmoveのような
効率的なコピーが使われないと思いこんでいるようだったから、わかりやすい
反例を示しただけだよ。
>>243 > *ほとんどの* ケースでは、単純なmemcpyで済みそうなのに、
それで済むケースは実際にそうなる場合があるよ、と。
255 :
251 :2008/03/14(金) 13:40:35
ん? 仮想関数がらみとか、コピーコンストラクタでpxをdeep copyしなきゃ ならないケースの話? そういうクラスはPODとは呼ばないけど。
>>251 ちょうどVC8には、__is_podがある。
ただ、手元のVC9 EEのincludeディレクトリをgrepしたが、
使っていないみたいだったorz。
かなり初歩的な質問になるんですけど、std::setがどうやっても 当環境ではエラーを起こすのですが、原因わかりますでしょうか #include <set> #include <iostream> int main(){ using namespace std; set<int> nums; // 空のset return 0; } この文を実行した場合、実行時に Run-Time Check Failure #2 - Stack around the variable '_Lk' was corrupted. と表示され,xtreeのソースが表示されます。 環境:WinXP Pro SP3 Visual Sturio 2008
258 :
257 :2008/03/14(金) 19:12:24
すみません、早速自己解決しました。 単純にPlattformSDKのcrtにあるxtreeが読まれていたからでした お騒がせしました。 ...OSまで再セットアップしたのにorz
アルゴリズムに渡す、ちょっとした関数オブジェクトのクラスにどんな名前つけてる?
func
lambda
fuck
>>259 クラスの役割にかかわらず名前がつけられるなんて思わないでください。
>>259 クラス名決める前に設計段階で静的モデルからクラス図作るからその段階で関数オブジェクトだろうがクラスだろうがメソッドだろうが役割に適した名前になるんじゃないの?
設計改善してコードリファクタリングの過程でまた適した名前にすると思うんだが?
STLとは関係ないし
使い捨てツール作るなら、名前なんかテキトー
動けばよろし
ちょっとした関数オブジェクトの事だろ 他言語なら匿名メソッドとかラムダですませちゃうような奴 そんなん設計段階で無い事の方が多い
はーやく来い来いC++0x
268 :
デフォルトの名無しさん :2008/03/18(火) 01:34:41
先日放送されたクローズアップ現代(NHKの番組)によると、 日本のプログラマ人口は20万人だそうです(かなり不足して いるらしい)。この20万人の中で、C++の言語機能を一通り 理解して、STLやBoostなどのライブラリをそれなりに使い こなすことのできるプログラマは何人ぐらいだと推測しますか? あなたは20万人の中で上位何パーセントの層に属しますか?
マ板で聞いてこいやボケが
今は高度なソフトウェアの需要が少ないので (そういう会社の数が激減したと言うか) 国内でスキルを持っていても活躍の場があまりない気がする。
>>269 やっぱり?でもマ版に入り浸っている人じゃなくて、
具体的なC++の質問に答えられる人にききたいんです。
C++経験者が30%、うち上記条件を満たす人間が30%と感覚で決めつけたとして 20*0.3*0.3=1.8くらいとかだったらいいなぁ・・・
boostともかく、STL使わないC++って、どういう使い方してたら発生するんだろう。 C++経験あったらSTLも使ってるんじゃないの? (単純な疑問文です。)
MFCオンリーなんて人もいるんじゃね?
なるほど。
276 :
268 :2008/03/18(火) 02:19:12
>>273 STLを使ってるといってもいろいろなレベルがあります。
vectorぐらいは誰でも使っていると思いますが、
コンテナとアルゴリズムを駆使して、コンパクトで
エレガントなプログラムを書くとなるとどうでしょうか?
>>268 では "それなりに使いこなすことのできる" 人の数
を問題にしています。
STLのアルゴリズムは必ずしも最適解ではないからなぁ
わがまま言ってんじゃねえ マ板に行け
STLやBoostを使えるのが、プログラマ人口の上位とは限らんすぃ
しかし、C言語しか使えない、もしくは、C/C++両方使えないのは、下位ケテーイ。 Boostって組み込みじゃ氏んでもツカエンよな。
C や C++ が必要とされる分野って、コンパクトでエレガントなコードよりも 効率が良くて高速なコードが要求されることが多いような気がする。 両立できればいいんだろうけどさ。
つまり、C/C++でエレガントなコードが書けたら上位けてーい。
C や C++ が必要とされる分野って、 開発環境がそれしかサポートしてないだけ
つまり、今の組み込みの分野。 C++はじまた。 M$/V$オワタw
>>268 活躍の場って組み込み系か?
DB系だとCなんかよりJava VB C#のほうがラクだし需要あるし
ダカラナニ?って感じなんだが。
仮にその上位ってやつだったとして
給料が高くなる保障があるわけでもないし
くだらない話題だと思わないわけでもないかもしれない可能性がある
組み込みでC++使うにはSTLやBoostを使いこなす事とは別ベクトルのノウハウが要るよ
言語に特化した知識だけじゃたかが知れてる。 でも・・・C++かわいいよC++
ダメな子ほどかわいい(ぼそ
STL、Boostがあるからなんとか付き合っていけるんです。。。
STL、Boost使ってるけど、「shared_ptrを自分で書け」って言われても多分書けない俺はゴミ?
プログラマとライブラリアンは全然別だから気にすんな。
STL/boostは可汎的なライブラリで、これそのものを設計、開発するならそりゃ相当のスキルを要するかも?この世にまだこれらが無かったって前提で 最善の選択肢とは限らないし だけど可汎的だから使うのはさほど大変じゃないと思う…が、使いこなすのはやはり難しいかも JAVAのステータスがどんどん上がってC++のオブジェクト指向開発してるPRJ減ってきたような C++でも構造体をpackしてmemcpyしてるのざらだもんなあ 今のPRJはユースケース駆動モデル(Rational統一プロセス)でOOPに加えてAOP的発想あるが… スレ違いスマソ
テンプレートが絡むとソースが美しくないんだよなぁ、なんか。
おまえさんの美意識は知らんが、 型指定が冗長だからtypedefかヘルパー関数の嵐になるのは仕様。 C++0xのautoで解決されるのも仕様。 既存のライブラリをC++0x用にせっせと書き直す作業が待っているのも仕様。
解決はされないんじゃないかなあ。 メンバ変数に書く際には auto じゃどうしようもないだろうし。
template typedefが欲しい
>>295 既存のライブラリをわざわざC++0xでしか通らないように書き換えたりするの?
300 :
デフォルトの名無しさん :2008/03/19(水) 15:42:21
この言語って機能が多すぎて大人数でプログラム組むの大変じゃない?
なんで?
多分MFCの話じゃね?それならそのとおり。 でも純粋C++なら安定部品を作ればよいだけ。
一口に「C++使える」と言っても、人によってその差は大きいから、 できる人からできない人まで集まってしまうという点では大変だと思っている。 同じようなレベルの人同士でならそう大変でもないはず。
まるで自分はできるとでも言ってるかのよう
CとC++の差が分かってない人がほんと増えた気がする だから困るかっていうと困るほどのものでもないんだが
>>305 C++がUNIXモンリーで単なるC言語のプリプロセッサだったころの、
クラスって何、
の時代しってんのかぁ?ゴルァ。
俺が憶えた頃は、まだ一部のコンパイラでは C++から一旦Cのコード吐いてからコンパイルしてたな。 もちろん例外処理なんて粋なもんは無かった。
まるで見当違いな
>>306 の突っ込みはいかがなものかと思う今日この頃
>CとC++の差が分かってない人がほんと多かった気がする
~~~~~~~~
なら分かるんだけどね、ってどうでもいいスレ違い続けてんじゃねえ!ゴルァ。
いちいちコメントしないと気がすまない奴らばかりだな STLの話しろや
イテレータンが無いとSTLの話できない椰子らw
できるできないとかどんだけ春なんだよ。 できて当たり前。 できないのは単にやってないか馬鹿だから。
STL、boostに関しては、それはいえない。 一通りやり終えるまでどんだけ。
でもさSTLとかも使ってないと忘れるよな。 おれ深く勉強したけど、もう1年くらいやってないから 忘れてるわC++ アハハハ
STLでなくても、1年あれば何だって忘れる。
スマートポインタが用意されているのに使わない人がいるとちょっとあれーと思ってしまう。
shared_ptrはBoostだから使わなかった、使えなかったという人がいたら、 TR1の普及で使うようになってくれるといいな。
Boostがなくてもメイヤーズの本見て作っておけばいくらでも使えたはず。
Boost/TR1が多数の現場で使えるようになるまで 何年かかることやら
shared_ptr っぽいものは boost とは別のライブラリに用意されてるけど ほとんどの人が使ってない罠。 まずは啓蒙からだな・・・。
shared_ptr使わないなんてあり得ないな、おれは。自分でdeleteなんて嫌だよ。 もうそんな時代ではない。細部を理解する必要はあるけど。それこそメイヤーズ みたいな貴重な本があるし。
Boost だから使えない、というような微妙な状況のときは、 自家製の refcount_ptr とか適当に作っちゃうなぁ。 代入や解放をスレッドセーフにしたいときとかも。
でも、scoped_ptr や auto_ptr で済む状況も多いと思う。 shared_ptr まで必要になるのって意外と少ない気がする。
Boostだって素人が作ってるわけではないし、むしろエキスパートが作ってる んだから何が不満なんだよと言いたい。それとも何処の馬の骨とも分からないやつ が作った自作ライブラリのほうが安全なのかよと。上司に言いたい。
こういった場合安全性よりライセンスが問題になることが多いが、 boost のライセンスってゆるゆるだよね?
場合によっちゃあソースコードレビューの対象にせざるを得ないから (& Bootst はレビューしたくないから) 自前で書く、ということもあるな。
あれだけレビューされてる boost を もう一度レビューするのも車輪の最発明と大して変わらない作業のような。
ライブラリのプロが書いたソースを一般レベルのプログラマがレビューするのって 滑稽じゃね?と上司に言いたい。
STL もレビューしてんの? あんなの読みたくもないが。
勉強になっていいじゃん >327
まあ勉強会としてはありかもしれない,、。
VS付属とSTLPortの実装を比べた事はあったなー。おもしろかった
小ささと速度を求めて、shared_ptr => intrusive_ptr => 俺スマートポインタ、と移行したことならある。 intrusive_ptr::operator=()が、いわゆる「スワップ技法」使ってるんだけど、これがBCB6だと遅くて。 こういう「局地的な場面」でまでboostを絶対視するのはいかんってことだね。 概ね信じろ、しかし盲信はするな、と。まぁ当たり前のことなんだけど。
ローカルな話題を堂々と振られるのもあれだな
「使う」話は遍くローカルだよ。
ローカルの事情で使いものにならないこともあると 言いたいのだろうけどそんなのはローカルの事情でしかないだろう。 一々ローカルにかまってたら標準の意味がないだろうよ。
>>332 はローカルな事情をタネにして
>概ね信じろ、しかし盲信はするな
っていう一般的な意見を述べてるだけだろ
話題自体はローカルじゃないし、標準がどうあるべきだという話もしてないと思う
>>336 その結論に持っていくネタがなんだかなって話だろ?
俺も小ささとか速度で難癖つけるのはどうもずれているような気がする。
誰も速度が速いとかオールラウンドに使えるという話はそもそもしていないんじゃね。
>>335 > ローカルの事情で使いものにならないこともあると言いたいのだろうけど
いや、boostの実装には「手を抜いている」部分もあり、必ずしも細部までエキスパートの優れた仕事って
わけではない、という話。
つまり「ローカルの事情の話」ではなく「ローカルの事情を通して知ったboostの実装の話」ね。
だから「boostの話はスレ違いだ」は受け入れるけど、「上司の意向の話」以上にずれた話題と思われるのは心外だなw
そこから来る結論は
>>336 の通り。初心者がboostへの信頼を信仰にまで高めちゃいそうな流れだったから、
思考停止だけはしちゃいけないよね、というレスが事例付きで一つくらいあったほうがバランス良いと思ったんだ。
あ、すまんもう一つレスが入ったか。
>>337 難癖ではないよ。boost大好きだし。
> 誰も速度が速いとかオールラウンドに使えるという話はそもそもしていないんじゃね。
いや、
>>332 もそういう話はしてない。
「エキスパートが作ってるという話」「ライブラリのプロが書いたソースだという話」の一環として書いた。
エキスパートとかプロっていう表現が踊り出すと(この表現自体は正しい)、ある種の人間に
変な思考を植え付ける結果になることがよくあるんだ。
冷静に判断しなきゃいけないところで「boostのほうが凄いに決まってる!だってエキスパートが作ったんだもん!」
「だってライブラリのプロが書いたんだもん!」みたいなね。
そんな馬鹿は放っておけばいいという意見もあるだろうけど、でも俺は今回、信じすぎは良くないからね、
という一言があったほうが、流れとして適切だと判断したから書いたわけ。
車輪を再発明するよりSTLやboostで合うなら使っていこうよ
レビューされているぶん、俺たちが会社で書く似たようなコードより信頼性は高いだろう
これだけの話だろ
車輪が環境に合わない場合は自作するしかないけど(
>>333 の場合)
自分で書くよりは信頼性が高いだろうというだけの話が
何故信仰や絶対という話になるのか理解に苦しむな…
>>340 そう、それだけの話。
で、
>>332 も「それだけの話」なんだけど(boostは概ね信頼できるという「事実」に対して、
必ずしも我々を越えちゃいないという「事実」を例示付きで添えただけ)、妙に突っ込む人がいて長くなってる。
343 :
340 :2008/03/20(木) 07:41:09
この環境ではスピードが遅くて使い物にならん!だから自作した! boostは盲信するな!絶対視するな! こんなイミフな展開にツッコミ入れない人間がどこにいるの。ワロス
イミフな展開になるように言い換えてるからじゃね?
そもそも
>>332 一つなら「展開」でも何でもないよ。単発だもの。「展開」は皆で「作った」んだよ。
なんかもう、1レスずつ突っ込み方が違っちゃってて、 数撃ちゃ当たる状態だな。そんなに必死に「やり込めたく」なるのかなぁ、俺のレス。
初心者です。STLのエラーメッセージが黒魔術で困っています。 皆さんはどのように理解してデバッグなさっていますか?
Effective STL に「STLのエラーを読めるようにしよう」みたいな項目がある。 要約すると、 std:basic_string< 〜 > とかを string に置換して読むこと、 こういうエラーが出たときはこういうミスを犯している可能性が高いっていう対応を知ること。 俺はエラーメッセージは読まずにえらーが出てる最初の行だけ見て直すけどw
>>348 エラーメッセージは見るな
自分のソースを見ろ
C++ Templateにも追い方が少し書いてあったと思う
初心者って絶対自分のコード疑わずに コンパイラのせいにするよなぁ C++どころかCの頃からそうだったなぁ
言語に関らずそうだよ
VC++だとテンプレートの中でエラー・警告が出たら、 その呼出元も表示してくれるので、 ひとまず自分のソースコードのどこの行が悪いのかはわかる。 あとはにらめっこの始まりなんだけどね。
とりあえずエラー行を見る。 それで大体の場合は分かる。 それで分からない場合、 次はテンプレートの型とエラーの種類を見る。 長ったらしいテンプレート引数は別に見なくていい。 それで分からない場合にはいよいよテンプレート引数を見るけど、 大体はその中で自分で作ったクラスが悪さしていることが多いのでそれをまず見る。 それでもダメな時は全体を見る。
const指定が間違ってるとか 名前照合に失敗してるとか そういうことが多いような
自作関数オブジェクトをアルゴリズムに適用するときとかね
>>356 constの有無程度なら「constがある/ない」で警告してくれればいいんだけど、型を変換できないと言われてtypedefしてない型を延々出されると何事かと思う。
もう慣れたけど。
STLの内部で使ってるの型を吐き出してくれるから、 VS付属→STLPortとか実装を取り替えると同じエラーでもメッセージがぜんぜん違ってくれる素晴らしい罠。
さてconceptはまだですか?
boostを盲進、過信するのはやや問題があるとは思う 特に納品物というか成果物としては。いくらboostのライセンスが軽いとはいえ。 boostの一部がTRで採用されて0xに反映されたら標準ライブラリとみなせるだろうけど… いっぽうで、ツール類作るときは積極的に使用する。 tokenizerとかregexとか、bindなんか使うとやみつきになる その点、STLはまずコンパイル・リンクエラーなってる場合はほぼ間違いなく自分のコードに問題あり もしくは、VC++とかBorlandC++とかそういうコンパイラ でも、テンプレートが展開されたエラーは原因を見つけるのに慣れないと苦労するのも確か。
>>361 は標準ライブラリを盲信、過信していると思う。
と凡人プログラマが申しております。彼は自分のプログラミング能力が ライブラリ作成者よりも優れていると申しております。
そういうのを盲信って言うんだよw
見事に釣られてしまったようです。
>>362 361だが、過信してはいないつもりだが、エラーの要因はまず自分のソースを疑うね
その点はboostでも同じだよ
まぁ、そう考えればSTLはバグがないとまでは言わなくとも(実際にある)、自分のソースを疑うってだけだ
だから過信、盲進してるかもな
ただ、boostはコンプライアンス上の問題やらでdefect発生時にどうなのよ?ってだけだよ
技術的な観点では、俺にとってboostはSTLのサブセットだよ。なにせ、boostの開発に携わってるのは
C++標準化の連中なんだから
それに、
>>363 のいうようにあらゆるケースや検証をして世の中に出てきたSTLと、必要なテストしかしてない
自分の作成したコードが正しいなんて言う根拠はどこにもない
で、
>>362 はSTLよりも優れたテンプレートを作っていると?w
boostはhppって拡張子が嫌い。
hppはまだいい ippってなんじゃらほい
現行STLやboostのメンバー見れば凄いのが揃ってるのはわかる。 コンパイラ作成者やM$のデヴェもいる。
370 :
361 :2008/03/20(木) 21:32:54
>>367 俺、boost信者になってからは寧ろ好きになったw
だけど、自分のコードはやはり .h を拡張子にしたいね。前プロジェクトではboost使いまくりーの、
.hppを拡張子にしまくりーのだったがw
>>366 >boostの一部がTRで採用されて0xに反映されたら標準ライブラリとみなせるだろうけど…
標準ライブラリと見なせることとコードの信頼性に何か関連性はあるのかね、と思ったのよ。
>>371 で、boost使ってて何かトラブったことあんの?
>>371 すくなくともベンダがリリース前にテストしたという信頼性は担保されるだろ
.h はCとの互換性を考えてあるヘッダのみに使って欲しいなあ C++専用のヘッダは hpp とか hh とか hxx とか使って欲しい # emacsで開くとc-modeになってしまったという経験がある # もちろんファイルの先頭にモードを書いておけば済む話だけども
要件を満たすための全てのテストが通れば、boostを使っていようが自分で作ったライブラリを使っていようがok 自分で書いたコードが正しいと確信するための作業をboostにも適用すればいいと思う …標準ライブラリもいろいろで、C++の仕様見てないんじゃないかと疑いたくなるようなのもあるよ
>>372 逆。
標準ライブラリと見なせなくても boost には標準ライブラリと同等の信頼性はあると思っている。
boostっていっても信頼性は一様じゃないと思うが Boost.PPの滅多に使われないマクロあたりに嫌なバグが潜んでたとしても驚かないな
>>374 # vimのcpp用indentスクリプトの貧弱さは泣けてくる
まあ、昔からあってさらに頻用されてるやつは十分信頼性あると思うけどね。
っつー訳で auto_ptr は使うなと
>>374 はげど!
C互換もないのに.hって何だよ?と。
しかしライブラリを見てたらだんだん
ヘダファイルに拡張子なくてもよくね?と思えてきた
>>381 エディタで開くときに面倒・・・ただそれだけ。
ファイルを分類したいときも拡張子が無いと困るな。
拡張子に縛られてるOSは大変だな。
ファイル実体内にメタデータ仕込むとかも論外だけどな
ファイルシステムに組み込むよな、普通。
>>385 それってファイル壊してない?そんなOSがあんの?
拡張子だと気軽に書き換えられるからちょっと楽かも
xxx.tiff ↓ xxx.jpg 「劣化しますがよろしいですか?」 (OK) (キャンセル) (pngにする) そんなOSがあったら、使いたくはないが、触ってみたい。
マックバイナリというものがあってだな
boostの主要な部分って、仕様は固定されてるの? 結局、そこが一番問題じゃないかね。
そういや、std::auto_ptr使うような場面でboost::shared_ptr使った時、 実行コスト的にはやっぱり不利になるんかな? 大した違いじゃ無いだろうけど、ちょっと気になる。
なる
shared_ptr の初期化にはメモリ確保が余分に必要。 参照カウンタが0になった時にはメモリの解放が余分に必要。
>>387 9までのMac OSってそうじゃないの?
>>394 あと削除子保持するコストも必要だと思う。
Windowsならともかく、UNIX系は拡張子なんて慣例で付けるものでどうでもいい が、やはりC++とCのヘッダファイルを区別するのに、hとhxxにしときたい JAVAとかC#プログラマとかはC/C++でc/cpp、hのペアのファイル直すのがめんどいらしい
>>395 違うよ。
いわゆるMacBinaryはデータフォークとは明確に分離してる。
まあ、他のプラットフォームにしてみれば異質なものに代わりはないけど。
execが最初の2byteでシェルスクリプトを判断するようなものかな? どうでもいいけど
どっちかと言うと、ファイルのプロパティとしてファイル名やパーミションやタイムスタンプがあるように、 ファイルタイプとクリエータがある感じ。 MacBinary形式と言うのは、これらのプロパティを128バイトのヘッダとし、その後にデータフォークと (必要なら)リソースフォークを連結した特殊なファイル形式のこと。
>>400 ファイル名、タイムスタンプ、権限や属性はファイルシステムで管理しているがMacは違うの?
ところで、list.sort()やalgorithmのsort条件を関数オブジェクト使って決めると思うが、
関数オブジェクトという言葉が通じない人が多い
operator()のオーバーロードってことではファンクタというほうがわかりやすいのだろうか?
関数オブジェクト自体は理解してるの? ちなみに自分はファンクタという言い方はあとで知った。
関数オブジェクトって関数をオブジェクト化したみたいで好きじゃないな。 コード上で関数のように使えるだけで、関数とは全く関係ないのに。
作るのが面倒って点に関してはあまり好きじゃないが、 やってることはエレガントだとは思う。
405 :
デフォルトの名無しさん :2008/03/22(土) 17:22:14
クラスと何が違うのかわかんね
特別学級みたいなもんです
>>402 ファンクタを理解しているか?って言われれば、理解しきっていると言えるほど俺は自信ないw
Cの時によく使った関数ポインタのような、イベントハンドリングのロジックを外部化したり、コールバックなんか
に使うもんだという理解が強いかな
あとは、ポリモーフィズムとして同一で処理ロジックだけカスタマイズするときにファンクタとすることが多い
話は変わるが、組込み系ではメモリシステムをラップすることが多いとおもうが、
operator new()、operator delete()、operator new []()、operator delete []()なんかをオーバーロードするときは
EffectiveC++なんかを読み返してしまうよ…
メモリシステムといってそこでリークやオーバーフロー、未初期化アドレスアクセスなんかしてたら偉いことに
なってしまうし
そもそも、自分はC++、STLを理解しきっているとは思ってないよ
先週その典型例があった、C++といいつつCでマクロを書いたのだが、printf()をラップして可変引数をログ出力
するってやつ。stdarg.hの使い方を分かってなかったw
そういう
>>402 は?
stdarg.h 使うってことはマクロじゃないんでない? まあ、その関数をさらにマクロでラップしてるんだろうけど。
409 :
402 :2008/03/22(土) 20:26:05
いや、402は、「あんたが理解してるか?」の意味じゃなくて、 「関数オブジェクトという言葉が通じない人は関数オブジェクトの存在を知らないから通じないんじゃない?」っていう意味です。 関数オブジェクトという用語を知らずに関数オブジェクトを使うかなあって思ったから。 自分も理解しきってないよ。簡単な関数オブジェクト作れるレベル。
なんで雑談してんの?
相談が無いからだろう 相談できる雰囲気でもないがね
何で雑談しているのかを聞く それも雑談なんじゃね? 自分の胸に聞くのがはえーんじゃね?
>>407 ひょっとして有名人?
関西でPGでかつどうしてんの?
とりあえず2期のオガちゃんは萌えた。
>>409 ざらにいるんじゃないか、ファンクタを知らないPGは
だけど、今のPRJはユースケース駆動モデルでOOPかつAOP的コンセプトを多分に取り入れてる
から、ファンクタや関数オブジェクトの名前すら知らないようではさすがにPGとして使えない
デザインパターンの幾つかを理解しているくらいは最低求められる
とはいいつつも、知らずにそういうパターンを使っているってことは経験あるとおもうよ
大抵はライブラリとして用意されてるものを別途作って無駄なことやってることになるんだろうけどねw
>>410-412 まぁ固いこと言わないでマターリやろうよ
>>413 いや、有名人でもなんでもないよw
出身地は関西だが、都内で仕事してるしさ
>>414 オガちゃんいいよな!
>>408 可変引数を使うのにstdarg.hを使ったよ
va_start()やらはマクロを通して最終的にコンパイラ組込み型だからさ
ログ吐き用とはいえ、%SSっていう変なリテラルを敢えて作って、UTF-16の文字列をUTF-8(ASCII)
に変換してログ出しするってのを作ったわけなのだが、案外はまってしまったw
緒方賢一に萌えるスレはここですか?
そうです。
vectorにデータを追加した時にメモリ確保に失敗した場合、検出する方法ってありませんか? newでいうbad_allocの例外をキャッチするような感じ。
422 :
419 :2008/04/16(水) 02:26:03
>>420 お!
VC2005で確認しました。
STLでもbad_allocスローしていたんですねw
あざ〜す♪
アホすぎる
VC6 ではデフォルトで new が bad_alloc 投げなくて アクセスバイオレーションになるのは有名な話だけどね。
で?何処にVC6だという前提が示されていたの?
なんだこの意味不明の質問
427 :
デフォルトの名無しさん :2008/04/16(水) 20:34:00
で、どこにVC6でないという前提が示されていたの? とでも言ってほしんだろうか おまえらもっと仲良くしろよ タダでさえ過疎ってんのに
424 は 豆知識としてとらえるのが普通だと思うんだけどな。 419の環境がどうとかじゃなくて。
常識人は一人だけ。残りは全員アホ。
そんな微妙すぎるリンクを貼った
>>420 がまず意味不明。
>>424 の内容はもっともだが、VC6世代なら誰でも知ってる常識レベル。
なぜあえてそこだけピックアップして言及したのか意味不明。
何にカチンと来たのか、その後の煽り合いも意味不明。
つまりお前ら全員意味不明。
なぜあえて、というところは
>>419 >>420 >>422 の「bad_alloc がスローされるんだ♪」
という流れを見ての、ちょっとした老婆心じゃね?
>>429 要するに、君は色んなことの意味がことごとくわからない人、なわけだよね。
可哀相だけど、馬鹿につける薬って無いらしいから・・・合掌。
おまえら昔はぬるぽ返してたんだよとか 今でもnothrowとかできるんだよとか ちゃんと教えてやれよ
この程度で煽りに見えるとか
VC だとぬるぽは VC6 までだね。
だからこそ STL で
>>424 が起こる訳だが。
>>433 ま、煽りではあると思うよ、実際。
煽りと感じないことをアピールして煽り耐性自慢してもしょうがない。
仲良くしようよ。
friend関数を
窓から
こんにちは
やあ、おぜうさん
まあ、ごきげんやう
よひてんきですね
庭にはてふてふも飛んでます
std::list::erase の引数の型は std::list::const_iterator の方が適切ですよね?
なんで?
std::list::erase() に渡した反復子の参照先が将来的に変更されることがないからです。
constなポインタでもdeleteできるから、 それもある意味整合性があると言える気がする。
同じタイプのmapが2つあったときに、 片方のmapにもう片方のmapの要素を全部移動する方法ってありませんか? swapみたいにコピーしないで済む方法があればいいんですが。
swapじゃダメな理由は?
joinしたいからswapじゃダメなんじゃね
>>449 450さんの言われたとおりです。
限定的にしか使わないクラスをsecondにしてるので
operator=オーバーライドしてコスト下げるしかないかなぁとは思っています。
Boostとかであればそれでもいいんですが。
second をポインタにして、 実体はリストに保持しておくとか。
STLportのVC9正式対応版はよくれ
454 :
デフォルトの名無しさん :2008/05/05(月) 17:27:47
typedef std::iterator<std::bidirectional_iterator_tag, char> MyIterator; MyIterator it; *it = 'A'; これは、何がいけないんでしょうか?
int* p; *p=0; これのどこがいけないと思いますか?
なぜ質問に質問でこたえるのですか?
質問に質問で答えてはいけないのですか?
458 :
側近中の側近 ◆0351148456 :2008/05/05(月) 18:03:57
>>454 (っ´▽`)っ
itの記憶領域確保しろよ☆
it = new MyIterator('A');
かな?
え?
>>455 >>458 そういう問題じゃないだろ
そもそもstd::iterator<>はインスタンスを作ることを意図したクラスじゃないし、
operator*も定義されてない
>>460 いや、阿呆なのは458だけでしょ。
>455の例えはよくわかる。
俺にはさっぱり分からん
463 :
側近中の側近 ◆0351148456 :2008/05/05(月) 18:23:46
>>461 (っ´▽`)っ
そうだよ。(っ´▽`)っがヴァカなだけだよ
464 :
側近中の側近 ◆0351148456 :2008/05/05(月) 18:26:04
(っ´▽`)っ だってC++よくわからないんだも〜ん☆
m9('A')
>>454 じゃあ、どんな動作を期待しているのか述べてみよう。
468 :
デフォルトの名無しさん :2008/05/07(水) 21:58:26
>>455 の例えは全然わからんな。
何が言いたいの?
何も指してないイテレータを参照剥がししてどうすんだ? わかりやすくポインタで例えてやろうかあぁ?
もし
>>469 なら、やっぱり的外れだろ
std::iterator<>はそもそもイテレータじゃないんだから
ぼくにも分かりやすいようにガンダムで例えてください
ガンダムの格納庫はあるのに、 肝心のガンダムがない
std::string とかでぬるぽ使えないのはなんで?
>>473 どういう動作をさせるためにどうやって使いたいのかわからない。
>>474 const char * にNULLを渡すか空文字を渡すかで動作が違う関数があると、
それをstd::stringでラップするときに微妙に困るじゃない。
boost::optionalの出番か?
>>475 class my_string : public std::string {
bool m_is_null;
public:
my_string() : m_is_null(true) {}
operator=(const char* p) { if (p==NULL) set_null() else set_string(p); }
operator=(const std::string& s) { set_string(s); }
void set_null() { m_is_null = true; clear(); }
void set_string(const std::string& s) { m_is_null = false; *this = s; }
bool is_null() { return m_is_null; }
}
>>477 実は同じのを作って使ってるんだ。でもありがとう。
Concrete Containerをplubic継承www
と笑う人もいるので、抽象化して template <class T> Nullable : public T { ... }; などしておいてはどうだろうか
仮想デストラクタのないクラスはpublic継承しちゃだめだろ常識的に考えて・・・
delete されるような場面でアップキャストしなけりゃ良いんじゃね?
すると笑う人は笑わないのか?
結局boost::optional自作になるのか
なんで継承したがるんだ
楽にかつ安全に特徴を追加する方法って無いのかねぇ…
普通にオーバーロードを活用すればいいんじゃね? >486
std::string * でいいような…それかboost::optional<std::string>
const char *でいいだろ・・・
話は逸れるけど、逆にnullが存在し得る参照型Stringを持つJava/C#を触ると、 nullの存在がうっとおしいと思うときがあるから不思議。
ぬるぽ
>>490 そうそう、無効値としてnullか""のどちらにするか結構悩む。
std::iterator は仮想デストラクタないけど public 継承していいんですか?
494 :
デフォルトの名無しさん :2008/05/09(金) 13:04:18
EBOがあるからいいんじゃないか?
495 :
デフォルトの名無しさん :2008/05/09(金) 13:06:26
間違えたw 気にしないで・・・。
>>493 typedefしかしてないクラスだから、public継承しないと意味無いと思うけど。
このほうが安全じゃない? class my_iterator : private std::iterator<Tag, Type> { typedef std::iterator<Tag, Type> super_t; public: using super_t::iterator_category; using super_t::value_type; using super_t::difference_type; using super_t::pointer; using super_t::reference; };
std::iterator や std::unary_function のようなクラスは protected な非仮想デストラクタが定義されていればいいのに。
それ自身インスタンス化することないし、基本クラスとして使うこともないし いいじゃないの?
データメンバもメンバ関数もないクラスにアップキャストしても 何もいいこと無いからな
マーカインタフェースという概念があってだな。
>>499 C++ Coding Standardsの50項目目に紹介されている。
反論の根拠ってなんでしょうか。
507 :
505 :2008/05/09(金) 21:13:02
そこの部分だけ一回で理解できなかったのですが、理解できました。ありがとう。具体的なケースはよく分かってませんが。
VC++ならコードを書いて、右クリックの定義へ移動が便利。
510 :
508 :2008/05/10(土) 02:36:53
thx xstringファイルに定義されていました。 インクルードの経路が複雑・・・。
>>482 >ほとんどの台は左第一停止で引き込み100%だったっしょ。(チェリーバーは順押しで引き込み100%)
いや、だから「すげー細かい」ってことだったんで・・・
スーパーヘビーメタルについては「リプor緑/リプ/リプ」がJacInなんで引き込み100%かと・・・
http://www.pachinko-club.com/gallery/kisyu.php?id=603803 ミラクルUFOに関してはわからず・・・
>初BET枚数の異なる2種類ボーナス △ デビルメイクライ3 ロデオ 4種類REGの内、1つが1枚、他は2枚
リオパラダイスがBIG/REGでBET枚数違ったような・・・(リオが3月でDMCが6月)
業界初スレか。珍しい誤爆だなあ。
ごめんなさいorz
やっべ何言ってるかさっぱり分からんw うちらも外から見たら同じなんだろうけど
>>514 > うちらも外から見たら同じなんだろうけど
むかしガイドライン板に「一度も行ったことない板に行ってみるスレ」ってのがあって、
この板を覗いた奴の感想は「わけわからん。半分ぐらい日本語じゃない」だったなw
マジでまったくわからんなw まぁ、俺はこの板の内容も半分以上わからんが
そういわれるといかにも初心者丸出しな質問でさえ高度に見えてくるぜ
す、すいません・・・ STLをかじり始めの者なのですが、質問があります。 std::ofstreamだのstd::wofstreamだのをいじってみたのですが、 どうしてもユニコードでファイル出力ができません。 std::setlocale("japanese")とやってみると、どうやらshift-jisの テキストが出力されてしまうみたいなんですが・・・。 STLを利用してユニコードのテキストファイルを出力するには どうすればいいのでしょうか?よろしくお願いします。 ちなみにVC9を使用しております。
>>518 ストリームをテキストモードで開いているとUnicodeからANSIへの変換が暗黙のうちに行われます。
バイナリモードで開くとこの変換は行われません。
wchar_tはUTF-16だったりUTF-32だったり処理系定義だということに注意。
522 :
518 :2008/05/13(火) 03:33:12
>>519 >>520 >>521 のみなさん、返答ありがとうございました。バイナリで書き込まない
といけなかったのですね・・・。
>>521 さんの貼り付けてくれたサンプル
コードでなんとか分かりました。やっとUTF-16のテキストファイルを
作成することができました。ありがとうございました。
C#とかの.NET系なら、UTF-16,UTF-8,UTF-32,Shift_JIS,ISO-8859-x,Windows-xxxやら、 システムがサポートする文字コード全て、パラメータ指定するだけで出力出来るんだけどね。
つlibiconv
つICU
つmlang
527 :
523 :2008/05/13(火) 18:58:21
C#とかの.NETなら、標準ライブラリのみで、普段入出力に使用しているクラスに パラメータとして文字コードを追加していするだけでいいんだけどね。
それだけの理由でC#を使えるようならとっくに使っているわ。
529 :
518 :2008/05/15(木) 21:06:15
Boost.IostreamsがUTF-8のcodecvtを持っていたはず。 一般のライブラリでの実装と言えばそれくらいしか知らないけど。
531 :
デフォルトの名無しさん :2008/05/21(水) 21:31:09
唐突で申し訳ありませんが、以下、2点質問させてください。 ご意見で結構なので、よろしくお願いします。 @eraseで、listから登録しているクラスのポインタを削除した場合に、 →リストから削除したクラスのデストラクタはコールされる? リストから要素のみ削除されると理解していたのですが、 VC6.0のSTLのドキュメントを読んだところ、 N回のeraseでN回のデストラクタが呼ばれると書いてあったため困惑中。 Aマルチスレッドアプリでコンテナなどを用いるのは危険?(VC6.0を想定) →MSDNにて、eraseを複数のスレッドから同時に実行するとデッドロックする という記載等があったため、少なくともVC6.0のSTLは マルチスレッドアプリを作る上で適当でないと思い始めている段階。 実際、beginなどの引数なし関数コール時にアプリが落ちた経緯あり
「listから登録しているクラスのポインタを削除」の意味がワカラン こういう日本語もワカル人がいるので不思議 そういう人を待て
std::list<T>なら、eraseしたときに該当するオブジェクトのデストラクタが呼ばれる。 std::list<T*>なら、該当するオブジェクトとはlistの要素たるT*のオブジェクトであり、 T自体のデストラクタは呼ばれない。 Tオブジェクトのデストラクタが呼ばれるようにしたければ、 boost::shared_ptrでも使えというのがC++の現状。
>>531 1. について
ポインタ要素を erase してもデストラクタは呼ばれません。
実体を格納している場合には erase でデストラクタが呼ばれます。
2. について
読み取り専用なら安全です。更新があるなら、明示的に排他制御
しましょう。
>>533 534
回答ありがとうございます。
概ね、当方の理解と一致しており、胸を撫で下ろしました。
質問事項Aのマルチスレッドでの使用に関しては、
別スレッドでswap/uniqeなどで
iterator iの参照先の内容が変わることを考慮すると、
begin等も容易には使えないですね。
ちなみに、今、他人のソースをレビュー中でして、
人のソースを見ていると、自分の理解が正しいのかどうか
ちょっと不安になってきたりと・・・oTL
>>535 unique後はそもそもイテレータが無効になるから、マルチスレッド以前の問題だね。
>>535 スレッド安全性については規格では何も規定していないから、実装ごとにドキュメントを
読む必要がある。ドキュメントに記載がなければ、同時アクセスは一切できないものと
考えたほうがいい。そういう実装もあるので、最大限の移植性が必要なら同時アクセスは
一切できないものと考えるべき。
Intel謹製のスレッドセーフSTLがあったような・・・ あとポインタ格納しつつeraseしてもデストラクトする実装ならboost::ptr_listってのがある
テンプレートライブラリはクラスのマクロみたいなもんですよね? コンパイル時に全部展開されるので多用する場合はメモリを無駄に消費しそうなんですが、 比較的大規模なアプリを作るときは、やはりコンパイル済みのライブラリを使うべきなんでしょうか? 例えばMFCとSTLはどのように使い分けるのが賢いんでしょうか。
同じテンプレートを同じ型で別の場所でインスタンス化した場合はリンカが重複を除去する場合が多い なので、規模が大きくなるほどテンプレートのオーバーヘッドの割合は減少すると思う MFCとSTLでは重複するのはコンテナくらい コンテナはSTLの方が大分出来が良いので、基本的にコンテナはSTLのを使えば良いと思う MFCにべったり近い処理をするときなどは専用のコンテナが使いやすいこともあるかもしれない 結局はケースバイケースかな
>リンカが重複を除去する場合が多い 重複除去は仕様。必ず行われる。
重複除去しないとstatic変数のユニーク性が保証されなくなる。
>>541 例えば CODE セグメントとか .text セクションが 10 倍になって困るのか?
一割り増しでも困るなら、使うのをやめというたほうがいいだろう。
なんというか、なんでもいいから毎月雑誌読もう。二年もするとだいぶ変わる。
コピペ思い出した
boostで重いやつ(regex、spiritなど)を多用するとメモリ不足になる(VC++なら/Zm指定要求してくる) さらに酷いとコンパイラやリンカが落ちる。 STLレベルならそこまでのことにはならないが、テンプレートの副作用だな。
lambdaなんか使うとtypoが原因でコンパイラが落ちるからなw
それはメモリ不足とは別。
vectorって単なる動的配列として使ってもOKですか? たとえば、こんな風にバッファとして直接vectorに値を書き込むのはvectorの使い方として適切? std::vector<char> TestV; TestV.resize(MAX_PATH); ::GetCurrentDirectory(TestV.size(),&(TestV[0])); std::cout<<&(TestV[0])<<"\n";
なぜstringを使わない?
>>550 vectorの内部バッファの連続性は規格で保証されているのでok
>>551 現時点ではstringの内部バッファの連続性は保証されてなかった気がする。
別に連続性云々じゃなくて…… まあいいや。
文字配列でない配列にstringを使う方が頭おかしいだろ そんなコードさわりたくねえ
vector<char>って書いて有るじゃん
std::string str=string(&(TestV[0])); std::cout<<str<<std::endl; とでも書かないと満足できない人なんだよ、きっと。
>>553 「まぁいい」って、
>>551 を書いた根拠がまさにそれで、
立場が無くなって言葉濁してるだけでしょ?w
も前らおちつくんだ
&(TestV[0])でポインタ得るのはどうよ
&TestV[0]
&*TestV.begin() ならマジックナンバーが現れなくていい とか言いたいのかな
vector::data()はまだ規格に入ってないんだっけ?
自分用のライブラリで、 2箇所でSTLを取り入れただけで、.libのファイルサイズが3倍になったんだけど テンプレート導入でサイズ急膨張って常識なんすか?
:テンプレートは結局、自動的にコードを生成する機能といえるのでうまく使わないと予想外にコードが大きくなる。
STLを使うとコードが10倍に?
元のライブラリが10KByteで30KByteになったとかだったら驚かない。 3MByteが9MByteになったとかだったら、なにやったんだよと思う。
シンボル情報削れば大したことにならんと思うが
OSもコンパイラもそれらのバージョンも言わずに3倍とな!?
コンパイラはg++です
VC++でexpressive入れた途端に未最適化コードとmapファイルが1MB増えた覚えはある
>>561 そこは &TestV.front() だろ・・・常考。
STLスレだけにテンプレ通りの話をしてるのですね
575 :
デフォルトの名無しさん :2008/05/28(水) 22:48:49
template<class T> class ListEx { list<T> m_list; list<T>::iterator m_itr; }; iterator の行でエラーになります。 何がいけないのでしょうか?
typename list<T>::iterator m_iter;
>>576 ありがとうございます
エラーは出なくなりました。
でも、 typename がなぜ必要なのかわかりません。
どこを調べたらいいのでしょうか?
>>577 一度、Effective STLを読んでおいた方がいいんじゃないか?
型なのかメンバ変数なのかハッキリしろコラァ! とコンパイラが怒るから
この文脈では list<T>::iterator のTは型に決まってるだろ、と小1時間ほど問い詰めてやりたい
Tじゃなくて、iteratorが型かどうかわからない。
template<typename T> struct list{ enum{ iterator = 0 }; }; だったらlist<T>::iteratorをする時にはtypenameの代わりに何が必要なのか
>>583 何もいらない。
typenameがないときは、暗黙のうちに値として扱われるよ。例外もあるけど。
>>581 実際VC++だとtypename無くても通るっぽい?
賢いというよりテンプレート宣言を読むときは「あーはいはい」って感じで
実際に型当てはめてからチェック開始してるのかね
>>582 なるほど、
typename list<T>::iterator m_iter;
は list<T>::iterator がタイプ名だとコンパイラに教えているのか
やっと納得できた
C++続けるつもりなら読むべきものをまず読んどけ
SICPですね、わかります
SICPとはまた時代遅れの物を
TR1のお勧め参考書おしえてくれ
>>590 つTechnical Report 1
592 :
デフォルトの名無しさん :2008/05/31(土) 01:30:22
ちょっと質問です。 STL辺りに「テーブルクラス」なんてありますか? イメージとしては、データベースのテーブルをオブジェクトとして扱うクラスです。 result = DBDATA.summary(var1) ; こんな感じです。
>>590 EffectiveC++の第三版はtr1にちょっと触れてる
>>592 イメージとしては、データベースのテーブルをオブジェクトとして扱う
クラスはない感じです。
>>592 STLだけでやるなら、連想系コンテナとアルゴリズムを組み合わせる感じかね。
>>592 where句が限定されているならmapでいいんじゃないの?
っていうかDB的に使うなら普通にsqliteでも使った方が無難だよ。
O/Rマッパーが欲しいんじゃね DataSetとか
mapは、要素の追加または削除を行ってもそれ以外の要素の参照は保たれたままな事が保証されていますか?
追記です。要素への参照の他に、キーのについても同じ事が言えますか?
自己解決しました。ありがとうございました。
死ね
死ねっていう奴と 死ねって言われた奴は 死ねばいいのに
そして伝説へ・・・
死んでもそれ以外の人の参照は保たれたままな事が保証されていますか?
死して屍拾う者なし、ってメモリリークのことですか?
GC「骨くらいは拾っておいてやるよ」
デストラクタ「生ける者の為の卒塔婆」
std::mapのイテレータに順ずるものから、木構造の右部分木、左部分木をそれぞれ取得して 木を追跡したいんですが、そういうことは可能でしょうか?
赤黒木使ってたら左部分木と右部分木だけとは限らないよ アルゴリズムの本読んでみ
>>609 std::map が木で実装されているとは限らないので、そういう操作は無い。
木の追跡(?)自体がやりたいわけじゃないと思うんだけど、結局のところ何がしたいの?
>>611 upper/lower_boundで解決しました。
やっぱり解決しませんでした。もういいです諦めます。STL死ね。
お前が死ね
すぐファビョる所を見ると朝鮮人か
私が死ぬのであなた達は死ななくてもよいのです
STLは生き物ではないので死ぬことはできません
私のお墓の前で泣かないでください
STLの考え方に頭が付いていかない所を見ると 頭が悪いかジジイかのどちらかだろう
お尋ねします。 vector<vector<bool>> TempA; vector<vector<bool>>::iterator itr1; vector<vector<bool>>::iterator itr2; と宣言したとします。 itr1 = TempA.begin(); itr2 = TempA.begin(); としたのち、 TempAのたとえば2行目と3行目の中身すべてを比較したいとき、 itr1++;itr2 += 2;としてiteratorを進めて、 *itr1 == *itr2の比較を一度行えばいいのでしょうか? それとも、各行でiteratorを作成して、 各行ベクトルの列座標に対応したiteratorを回す必要がありますか? p.s.この動作のあと、一致している行を、 itr2=Temp.erase(itr2); みたいに削除したいのです。
>>620 要するに二つのvectorを==で比較できるかってことだよな
できるよ
>>621 ありがとうございます。
行に対応するvectorの各要素の比較という認識で大丈夫でしょうか。
そう。要素ごとに==で比較してる
>>622 23.1 Container requirements に
a == b は a.size() == b.size() && equal(a.begin(), a.end(), b.begin())
と等価と書いてある。
>613 map使わずにソート済vector使えばいいんじゃね?
626 :
620 :2008/06/05(木) 10:43:24
>>623 亀レス申し訳ない。
ありがとうございました。
そういう情報ってどのヘッダーを見ればいいんでしょうか?
vector.hを眺めていてもさっぱりです…。
>>626 C++の規格書一回読んでみるのもいい。
vectorかその内部でincludeしてるファイルに書いてあるんじゃね。実装が。
イテレータを返すbegin, endが、どうして戻り値の型が違うだけで(iterator, const_iterator)オーバーロードされた関数を特定できるのかが分かりません。 自分で同じ様な事をしようとしてもSTLとは違いコンパイラが関数を特定できずに失敗します。
>>630 戻り値の型じゃなくて、引数リストの後ろの const の有無が違う。
>>631 それは実装側のbegin, endの定義ですよね?
自分で作ったものもconst_iteratorを返すものは引数リストの後にconstをつけているんですが、
これは利用する側が呼び出すときには特に関係ない様です。
まさか container_type::const_iterator it = ((container_type::const_iterator (container_type::*)()const)container.begin)();
なんてしなきゃいけないんですか?
iteratorからconst_iteratorへの変換はできるようになってる?
変換できるようにしたら const_iterator begin() const の必要性なくならないか?
なんで? constなインスタンスに対してイテレータ取得できなくなっちゃうじゃん
VC7 template<class _Ty,class _Alloc> class _Vector_iterator : public _Vector_const_iterator<_Ty, _Alloc>
>>636 補足しとくと、iteratorは基底クラスであるconst_iteratorに変換できるといいたいだけ。
constなしbegin()の戻り値はiteratorだからconst_iteratorにも変換されうる。
begin()の戻り値を渡す先がconst_iteratorかiteratorかで、
begin()の種類(後ろにconst付きか否か)が選択されているわけじゃない。
>>632 MyContainer c = ...
MyContainer const& cc = ...
MyContainer::const_iterator = c.begin();
MyContainer::const_iterator = cc.begin();
これをトレースするといいよ。
なるほど、constなメンバ関数はオブジェクトがconstな時に使用されるんですね。
constメンバ関数と非constメンバ関数が両方ともある場合はそうなる。 非constメンバ関数がない場合は非constオブジェクトからもconstメンバ関数が呼ばれる。
\n とか \r\n とかが入った文字列を SetDlgItemTextすると char のときはちゃんと改行してるのに string だと改行されずに何も表示されないわけですが string って \n とかとは別に改行とかタブコードがあるんでしょうか?
実際のコード貼ってみれ
643 :
641 :2008/06/13(金) 21:37:36
あははははは!!!!! エディットコントロールのマルチラインがFalseなだけだった 俺市ねw
641は死んだの?
>>644 今日までの641は氏に、また一歩成長したプログラマーとして生まれ変わるのです。
フェニックスシングルトンなわけですね。
シングルトンを真面目に考えるとややこしい事限りないなあ。
非常に優秀なデザインパターンの1つだと思うな
インスタンスの数が1個に限定される分、むしろ単純にならないか?
Modern C++ Design を読むと シングルトンのややこしさがよく分かる。 Scala みたいに言語的にサポートしてくれればいいんだが。
作るのはいいけど削除のタイミングが面倒くさいんだよね。
いつでもnewdelete出来るように改良した、って自慢げに変なシングルトン使いまくる奴ならいたな
deleteしたら自動的に新しいインスタンスが作られて、 newしたら自動的に今あるインスタンスが削除されるシングルトン
>言語的にサポート 使う人間のスキルへの依存度が高いC++に期待してはいけないものだよ。
シングルトンて心太に似てるよね
STLを軽く弄るためにこのスレを覗きにくるC++ビギナーはフェニックスシングルトンとModernC++Designをどうやって関連付けて考えるだろうか。
「スレ違い」 と関連づけて考える事だろう
mapはどうやってfindなどで入力されたキーが木にあるキーと同じかどうかを見るんでしょうか? 比較関数ならstd::less<T>がデフォルトで入っていてこいつを使えば良いと分かるんですか、 これと同じ様に一致関数をテンプレート引数で指定できませんか?
比較関数をltとすると、 !lt(x, y) && !lt(y, x) で一致判定してる
マップのキーは、その比較関数を使って一致を判断する !(a < b) && !(b < a) なら a と b は一致していることになる
そして等価と等値の話が始まる。
重要な概念だしな
そしてEffective STL が売れる
そして日本語版Modern C++ Designが叩かれる。
ListとかVectorってスレッドセーフですか? 複数のスレッドからイテレータ取得してアクセスしたりするなら シグナルやミューテクスでロックしてからアクセスするべきですか?
そうですね。
>>666 実装次第。
各処理系のマニュアルを読むよう。
STLportでぐぐらない方が良い。
スレッドセーフなのか?という問いに答える者はいなかったといふ
実装次第だし。
スレッドセーフではない と一律で答えておいたほうが面倒がない
Camelなリストやベクタはスレチ。
というか、「スレッド」の概念が標準C++にあるんだっけ?
ございません
スレッドの概念が無いから「スレッドセーフでない」という概念も無い。
C++0xにご期待下さい
コンテナの範囲外にイテレータがインクメントされてしまってもコンテナを自動で拡張し、 あたかも未だに範囲内を指している様に振舞うイテレータってのがあると思うんですけど 実際はなくてただの思い過ごしだったりしますか?しなかった場合はそれが何なのか教えてください。
insert_iteratorのことを言ってるのかな。
自己解決もしたし意味不明な書き込みなんてみんな無視してくれるだろうと思っていたら教えてくれている人が居た。 ありがとう。
682 :
デフォルトの名無しさん :2008/06/20(金) 15:05:13
std::vector<std::string> v1; みたいなインスタンスをシリアライズ化したいんですけど、単純に FILE *fp = fopen("vec.bin", "wb"); fwrite(&v1, sizeof(v1), 1, fp); fclose(fp); みたいに書き込めば良いんですかね? そして戻すときは、逆に std::vector<std::string> v1; char* buf = (char*)&v1; FILE *fp = fopen("vec.bin", "rb"); while(fread(buf++, 1, 1, fp) > 0); fclose(fp); みたいな感じでいいんですかね? STLのインスタンスのシリアライズ化で、もっと適切な方法があったら教えてください。
vectorの内部にはポインタも含まれるから オブジェクトの性質を考えてPOD型のデータまで落としこまないとダメだろう
vectorの扱う型ががフリーストアを使ってないという保証があればあるいは
boost::serialization使うって手も <あまり使いやすくは無い
VS2005では一応下のコードは正常に動きました。 とりあえずこれが動けば十分です。 std::vector<std::string> v1; v1.clear(); v1.push_back("要素1"); v1.push_back("要素2"); v1.push_back("要素3"); FILE *fp; fopen_s(&fp, "vec.bin", "wb"); fwrite(&v1, sizeof(v1), 1, fp); fclose(fp); std::vector<std::string> v2; char* buf = (char*)&v2; fopen_s(&fp, "vec.bin", "rb"); while(fread(buf++, 1, 1, fp) > 0); fclose(fp);
>>686 まてまて、それv1の確保したメモリアドレスをv2が指しているだけだろ。
終了時に2重解放でエラーになってないか?
と思ったら、デストラクタで怒られました。 何がいけないんだろう・・・
上の人も書いてるけどvectorは内部にポインタを持ってるんだってば。 (ついでにstringもな) fwriteでv1を直書きすると、ポインタのアドレスが保存されるだけで、 ポイント先は保存されないんだよ。
>>687 ,689
どうすればいいでしょうか。
やりたいことは、カンマ区切りで並んでいる大量の文字列データがあって、
それをカンマの区切りを探しつつ読み込むと非常に時間がかかるので、
初回だけカンマ区切りを解釈したら、その後はインスタンスをバイナリで一気に保存、一気に復元したいのです。
vector使わずに配列を使えばいいんでしょうが、vectorのデータをシリアライズ化するということは ニーズとしてあるはずなので、そういう手法があれば教えていただきたいのです。 ただシリアライズのためにboostという別ライブラリを使用するのは、ちょっと大げさすぎかなと。。 そこまでするなら配列でやります。
自分の力量・理解度に応じた実装をするべし
最低限のデータを保存したい場合はこうじゃない? std::vector<std::string> v1; v1.clear(); v1.push_back("要素1"); v1.push_back("要素2"); v1.push_back("要素3"); FILE *fp; fopen_s(&fp, "vec.bin", "wb"); const char *pstr; fwrite(&v1.size(), sizeof(size_t), 1, fp); //読み込むときの利便を考えて要素数を保存 for(size_t c=0, e=v1.size(); c < e; c++) { pstr = v1[c].c_str(); fwrite(pstr, strlen(pstr), 1, fp); } fclose(fp);
stringのサイズ保存してなかったので訂正 書き込み std::vector<std::string> v1; v1.clear(); v1.push_back("要素1"); v1.push_back("要素2"); v1.push_back("要素3"); FILE *fp; fopen_s(&fp, "vec.bin", "wb"); fwrite(&v1.size(), sizeof(size_t), 1, fp); //読み込むときの利便を考えて要素数を保存 size_t size; for(size_t c=0, e=v1.size(); c < e; c++) { size = v1[c].size(); fwite(&size, sizeof(size), 1, fp); fwrite(v1[c].c_str(), size, 1, fp); } fclose(fp);
読み込み std::vector<std::string> v2; FILE *fp; fopen_s(&fp, "vec.bin", "rb"); size_t size; fread(&size, sizeof(size), 1, fp); v2.resize(size); for(size_t c=0, e=size; c < e; c++) { fread(&size, sizeof(size), 1, fp); v2[c].resize(size); fread(&v2[c][0], size, 1, fp); //stringの確保するメモリが連続してない環境なら、一度vectorなりに読み込む必要が //あるが、vcなら問題ないので省略 } fclose(fp);
最初にもちらっと書いたが、serialization使うとこれですむ
//保存
{
vector<string> data;
data.push_back("Hello");
data.push_back("World");
ofstream file("save.dat");
boost::archive::text_oarchive oa(file);
oa << (const vector<string>&) data;
}
// 復元
{
vector<string> data;
ifstream file("save.dat");
boost::archive::text_iarchive ia(file);
ia >> data;
}
下準備がちょっと面倒だけどな。
興味あったら下記を参照してください。
ttp://www.kmonos.net/alang/boost/classes/serialization.html
>>694 ,695
やっぱり要素ごとにサイズと一緒に保存という形しかないんでしょうか。
私のイメージではシリアライズというと、メモリ上にあるオブジェクトの塊を
そのままバイナリで一気に書き込むという感じで、だからこそ高速化に役立つと思うのです。
要素ごとに書き込んでいると、カンマ区切りのケースとそれほど時間の差が出ないような・・・
MFCのCObjectを継承したクラスはシリアライズができますが、それはおそらく、
オブジェクトのデータやステートをメモリ空間上で一塊になるようにしている配置しているからこそ
できるんじゃないかと思います。
STLではどうもそういう仕組みはないようなので、保存や復元に時間がかかるのは無理ないんでしょうかね。。。
>>696 boostの場合はどうなんでしょうか。
保存と復元を高速化できるかどうかがキモなんです。
>>690 カンマ区切りの文字列の読み込みに、そんなに時間がかかるとは思えんが。
時間がかかっているのはパースよりもvectorの伸張だろう。
先にカンマの数をカウントしてvector.reserve()するとか、vectorではなくて
dequeにするとかの方が速くなるかと。
>>697 MFCのシリアライズは、各メンバをひとつずつCArchiveに書き込んでたと思うよ
CObjectを継承すれば自動的にサポートされるものでもなく、メンバをひとつずつ書き込むコードを各クラスに個別に実装する必要があった
シリアライズに対するそのイメージは誤りかと
データ個数にもよるが保存と読み込み時間を短縮したいなら まずデータ構造自体から見直すべきだろ。 というか、そこがネックになってる時点で何かが間違ってる。
>>699 ,700
そうなんですか。
可変長データ配列のオブジェクトの保存と復元を高速化するためには、
各自が工夫して実装するしかないんですかね。
なんか車輪の再発明のような気が・・・
配列要素の変更・追加・削除は頻繁にはやらないので、そちらの時間コストは多少増えてもいいんです。
とにかくソフトの起動をコンマ1秒でも速くするために、ドカンと一気に読み込めるようにしたいんですよね。
BYTE型配列1本と、ポインタ・サイズを格納した配列の計2本で、
そういったことをやれそうなイメージはあります。
vector<string>が固定長なデータじゃないので、要素ごとにアクセス しなければならないのは仕方が無い。 また、上の例でも1文字ずつカンマをチェックしながらアクセスするよりは、 単純に数倍は速いよ。 ディスクアクセスが気になってるのなら、あらかじめメモリ上に 直列化して、総サイズも一緒に書き込むとか工夫しなさい。 (もともとfread、writeがバッファリングしてるので、あまり効果は無いだろうけど) あとboostのも1要素ごとの読み書きです。 入れ子になってるコンテナの巡回探査がデフォで出来るってだけ。
ほんとに直列の読み書きがしたければAPI叩くしかないんじゃないかなあ
>>701 まぁ今回の件に限らず、「コンマ1秒でも速くする」というような目標を持っている場合、
車輪の再発明は避けられないことが多いよね(そうでない場合も勿論あるけど)。
本当に速くしたいなら MMX とか SIMD とか使うと
DANGOさんの出番だな
: premature optimization is (省略されました。続きを読むにはワッフルワッフルと書き込んでください)
ポインタのない言語なら
>>686 みたいなことは当たり前にできるんだけどな。
ポインタのある言語では、一気に話が複雑になるな。
データの入出力なんて元々複雑で時間の掛かる処理なんだから 横着するつもりなら効率の劣化には目を瞑るべき。 大体そんな困るほど遅くなることなんぞ滅多に無いし。
だいたい直列化してないデータを直列させるからシリアライズと いうのに、最初からメモリ上に直列に並んでると考えるのはどうなのよw
>>708 ポインタの無いJAVAみたいな言語だって、>686みたいな記述はできても、
要素の実際の読み書きは1つずつだろ?
>>686 これは素晴らしい!!!
すこぶる高速ですね
>>686 これstringの実装によってはやばくないのかな
>>713 そのコードがダメなのははっきりしてるから。
続きも読め
それ以前の問題。
ポインタ保存してポインタ復帰してるだけだからな。
>>709 いや、プログラムの起動を可能な限り速くしたいというニーズはどこにでもある。
3秒で起動するブラウザと1秒で起動するブラウザ、どっちを使いたいかといえば速い方がいいに決まってる。
そういう場合のクラスデータのシリアライズは、1分かかるのを30秒にしたいとかいうオーダーの話ではなくて、
0.3秒かかるのを0.05秒に縮めたいとかいうオーダーなんだよ。
起動時にデシリアライズするオブジェクトの数は1つじゃないしな。
トータルで1秒以内で起動させたいとか、そういうレベルのことをやりたいとなると、
バイト配列の中に直列化したデータ(多少隙間があってもいい)をあらかじめ揃えておいて
一気にシリアライズするという考えも、アリだと思う。
ファイル読み書きのオーバーヘッドなんてI/O待ちが大半なんだから、 よっぽどアホな処理でもしてない限り大差ないだろ
>>718 さっきドラゴンボール全巻買ってきた までは読んだ
:そこ、高速化したいなら横着せず書かないといけないって書いてんじゃん
その手のオーバーヘッドで一番時間食うのはstatだったりするんだよな
>>718 将来まで不変のデータ構造ならいいけど、
少しでも変えると過去のバージョンで直列化したデータが読めなくなるよね。
(すべてのバージョンに対するコンバータを付けるのもどうかと思うし)
痛し痒しだなぁ。
ちゅーか目的が高速化なのに質問者が面倒がって 既存の実装使おうと食い下がってるだけだじゃん。
既存の実装で高速化できないってことは既存の実装がクソだということですよね
F-1を公道に持っていったら全く使い物にならないのと同じ。 普通車なら速くはないが大体どこでも走れる
>>724 べっ別にあんたのために実装したんじゃないんだからね。
すべてに効果のある実装は存在しない。自分の目的に合う実装がなければ自分で作る。
暇だから素のテキストと長さ情報付きのバイナリで試してみた。 入力データはwindows.hおよびそこからincludeされているファイルから抽出した 全て大文字の先頭以外にアンダーバー入りの定数マクロ(WM_hoge等)18364個。 文字列の平均の長さは20.8文字。 手抜きのために、カンマ区切りではなく改行区切りで保存。 テキスト(ifstream.getline()で読み込み) vector<string> 23ms deque<string> 21ms list<sting> 21ms バイナリ(ifstream.read()で読み込み) vector<string> 14ms deque<string> 12ms list<sting> 12ms ちなみに、VC++2008Stdでコンパイル、E8400のPCで実行。 全て複数回実行した中で一番速かった結果。
freadに変えればさらに速くなるぜ
ifstreamをやめて、fopen,fgets,freadにしてみた テキスト(fgets()で読み込み+改行コード除去) vector<string> 14ms バイナリ(fread()で読み込み) vector<string> 14ms CreateFile,ReadFileも試してみた テキスト(2048バイトずつ読み込み) vector<string> 11ms バイナリ(必要なサイズだけ読み込み) vector<string> 100ms
つーかstringって時点でバッファに直読みできねーよな CString::GetBuffer()使ってみ
731 :
729 :2008/06/21(土) 23:51:07
結局、ifstream.getline()が遅いだけで、読み込み部分を最適化したら テキスト形式でもバイナリ形式でも差がない感じ。 ちなみにテキスト形式でファイル一気読みでは、稀に10msが出る程度。 あと、バイナリ形式でReadFile()でチマチマ読むのは何故か遅かった。 fread()は速いのにね。
それはスレ違い。
>>731 それは「何故か」でも何でもなく明らかなことだ
fread()はチマチマじゃなくて「一気に」バッファに読み込んで
読み込んだ分だけユーザに渡してるから速いんだよ
>>732 スレ違いかもしれないが重要なことだろ。
stringに高速にデータを読み込む方法は存在しない。
必ずコピーが発生するのだから。
カーネルバッファ→stdioバッファ→ユーザバッファ(典型的にはchar[])→string
こんな感じ
ほらみろ、効率悪い
stringの実装を知っていれば環境依存の方法で… ってもうSTL作者になる以外ないな
>>730 この場合だと、GetBuffer使うメリットねーと思う。
>>736 いーやある。
fread()ではstringに直接読み込めないので一時的にchar[]に読み込んでコピー
するしかないが、
CString::GetBuffer()ならfreadで直接読み込める
つまり、一段コピーを減らせる
738 :
736 :2008/06/22(日) 00:03:33
>>737 理由は
>>733 が書いてる。GetBufferつかったら、それ以上に読み込み遅くなるだろ。
>>738 は?何言ってんの。
CStringで適当なサイズをリザーブしといて、
GetBuffer()で取ったchar*のポインタにfread()しろっつってんだぞ?
間違いなくchar[]に読み込んでからstd::stringにコピーするより
速いよ。
740 :
739 :2008/06/22(日) 00:09:03
ああ、話のズレがわかった。 俺はstd::stringなんて使わなきゃ速いよつってるんだ。 最後にstd::stringにコピーしなきゃならないんなら意味ないわな、 そりゃ。 コピー君だもの。
単に速いだけの話しならstd::istreambuf_iteratorとstd::ostreambuf_iterator が速いんじゃないの?書式化なしだし
>>739 いってることはりかいできるけど、俺が言いたかったのはそうじゃない。
俺が言ってるのは、読み込んだデータには
複数のデータ(複数の文字列と文字列サイズのペア)が格納されてるってことだ。
んで、
>>686 あたりからの流れのように、vectorに一個一個格納すると。
まあすれ違いだからもう自重する。
>>741 それはどんだけ頑張ってもマクロ版のgetc()/putc()と同等の速度で、
言うまでも無くfread()より遅いよ
またEffective STLを読み返さねばならんようだな
>>743 そりゃそうだ
比べるのが無謀
というか比べるな
std::stringのかわりにstd::vector<char>つかえばいいんじゃね char*, const char*のかわりに使えるし STLやboostのiterator取るタイプの関数も全部使えるし std::stringと違ってバッファ直接書き換えできるよ
どんだけ頑張ってもAPI直書きより 遅い。
>>747 上に出てるように、ちまちまReadFile()を呼ぶようなアホなまねをやるぐらいなら
まだfread()のほうが速いよ
もうRAMDisk使います
一応言っとくけど、バッファ渡して書き換えてもらう系の 関数だのAPIだのを使う際には全てこの議論は当てはまるんだぜ 別にI/Oだけの問題じゃない std::stringを使っている限りは常にコピーがワンクッション入ることを 覚悟せよってこった 通常はどうでもいい問題だがな
あーつまり何だ? ドライバ書けと
tcpのread/writeでのコピーは減るように各OSがんばってるネー
x86はリトルエンディアンであるというだけでtcp/ipのビッグエンディアンを 実現するのに少し不利なんだよな
物理層じゃなくてアプリケーション層の話な
データ本体だからendianは関係ないのでは・・
データをストアする時にひっくり返るでしょう ブラウザはどういう仕組みになっているのか知らないが Unicodeをリトルエンディアンのまま画面出力できるようになっているのか、 それともビッグエンディアンに並び替えて表示しているのか
速度最重視ならLEで送ってもらうんでないの
OSネイティブの文字コードで送られてくることなんか超レアケースだろ。そんなところが 最適化されててもたいしたメリットは無い。
保存したファイルを直接ファイルマッピングして、そのまま利用するのが最速なんじゃね 要するにオンメモリでの利用形式を、保存形式に合わせるw
>>759 ファイルマッピングはファイルサイズを伸ばせないのが難点だな。何かいい方法がないものか。
>>759 ReadFile()やWriteFile()は別にディスクをガリガリ読み書きする
わけじゃなくて、オンメモリのバッファキャッシュが相手だからな
事実上裏でOSがページ単位でファイルマッピングしてるのと同じで
CreateFileMapping()したからつって経験上別に速くならないよ
Windowsではな
話を大幅に戻すと、小手先の最適化に走る前に、本当にCSVやvector<string>
じゃなければいけないのかってところを考えるべきだと思うね
固定長データ、ISAM、SQLite、Berkeley DBのようなものが適切なんじゃないかとかさ
fopenは、内部的にReadFileを呼び出しているものの、バッファリングしているので (普通に使う分には)充分な速度が出る。 ただし、複数回のコピーが無駄と言えば無駄。 ReadFileは、OSのバッファにキャッシュしていてディスクアクセスはしないものの、 システムコールだから、カーネルとのスイッチが発生する。 だから、細かく何度も呼び出すと非常に遅くなる。 CreateFileMappingと使うと、OSのバッファキャッシュを経由しないので ゼロコピーとなり、読み出しに限れば最速を期待できる。 書き込みは、普通はバッファリングされるfwriteを使うべき。 Readと同様、直接APIを叩いても大して効果ないし 逆にバッファリングを無効にすると、ディスクアクセス完了まで待たされることになる。 この場合にどうしても最速を求めるなら、非同期APIを使う。
俺、この類はcatコマンドのソース読んで参考にした。 読み込みと、書き込み(表示)について練り込まれた結果の 知識が詰まってるなと思った。 ちなみに read() write() 使ってた。
あ、そうだ。 stdioはバッファリングしてるけど fgetc/fputcのような、1文字入出力系は注意。 最近のVCとかは、マルチスレッド対応ライブラリで 1文字ごとにロックしているので、このコストがバカにならない。 遅いと言われるcygwinとかもそうかもしれない。 istream_iteratorとかは知らんが、MT対応を謳っているなら ロックしている可能性は十分ある。
iostreamの比較なんて昔から皆やってるのになぜいまさら
実装が進化しているかもしれん。
残念ながらstdioより速いiostreamなんてのは見たこともないし、今後も無いだろ。 実装の質の問題というよりは、仕様上無理なんじゃないか。 ios_base::sync_with_stdio()とかあるし、デフォでシンクロしてるのが仕様だから、 stdioをバイパスできず、stdioの上に構築せざるをえないってことになる。 おまけに仕様も複雑だ。 これでstdioより速くなるわけがないんだぜ。
_CRT_DISABLE_PERFCRIT_LOCKS
まあ、速さだけが基準じゃつまらんよな。
>>697 そもそも
(世にある)シリアライズ機構 = 高速化のためのもの
という発想が間違い。
シリアライズ機構 =
ヘテロなオブジェクトの集合であっても、汎用的に直列表現に置き換えるための汎用枠組み
ととらえる方が常識で、(たとえば
>>699 みたいに)
でも汎用では自アプリにとっては遅くて不都合!という場合に、
自アプリに特化した、汎用無視の保存方法作る、というのがさらに常識。
CSVって決まってるならCSV特化とかね。そのかわりそこ変わった瞬間に大幅変更だけど。
はぁ?手軽に最高速がC++の売りなんじゃないですかぁ? バカなの? ぶっちゃけRubyのほうが100万倍マシ
C++が手軽なんて話は始めて聞いた
最初に「100万倍」ってとこだけ目に入って、 あーきっとアホの子なんだろうなーと思って残りを見たら 完全にその通りだった。
Ruby信者が例外なく全員キモイのは何故なんだろう
Rubyは優秀な言語なのに、使ってる人の中身がDQNだからもったいないよなw
釣りだったことにして逃げ切りを図るレスが来る頃合いだけど、 それを先にこうして予測したことで、ちょっとルートが変わるかもしれないな。
いつも思うんだが信者がわざわざRubyの評判を落とすような事をするかな。
儲に見えないのは俺だけか
ということにしたいんですね
>>778 例えば宗教団体の信者は熱心に勧誘を行って、結果周りから見るとイメージダウンをしている。
似たようなもんでは
そうかそうか
784 :
デフォルトの名無しさん :2008/06/24(火) 20:00:11
vectorの要素を指すポインタは無効になることがあります。 では、queueの要素を指すポインタは無効になることがありますか? 下のプログラムを実行すると、1 2 4 4 5 6 と出力され、期待通りに動きました。 このプログラムは正しいプログラムですか? #include <iostream> #include <queue> using namespace std; int main() { queue<int> q; q.push(1); q.push(2); q.push(3); int* x = &q.back(); q.push(4); q.push(5); q.push(6); (*x)++; while (!q.empty()) { cout << q.front() << ' '; q.pop(); } return 0; }
>>784 queueの中身のデフォはdequeなので、要素追加で
リアロケートが発生することがある。ポインタもイテレータも無効になる。
786 :
784 :2008/06/24(火) 21:00:22
>>785 なるほど。ありがとうございます。危ないところでした。
では、リストを使って、queue<int, list<int> > q;
とすればOKでしょうか?
>>785 途中への追加はイテレータ等が無効になる可能性があるけど
端への追加ではイテレータ等は無効になんないんじゃないの?
>>787 > 23.2.1.3 deque modifiers
> An insert at either end of the deque invalidates all the iterators to the deque,
> but has no effect on the validity of references to elements of the deque.
イテレータは無効になるが、要素への参照は有効のまま。
>>786 vectorやdequeなら、イテレータではなく添え字でアクセスするのも有り。
790 :
デフォルトの名無しさん :2008/06/28(土) 14:03:55
algorithmのcopyについての質問です。 ifstream ifs(argv[1]); vector<char> file; copy( istream_iterator<char>(ifs.seekg(10, ios_base::beg)) istream_iterator<char>(ifs.seekg(20, ios_base::beg)) back_inserter(file) ); 上記のようなコードで、あるファイルの10バイト目から20バイト目までをコピーしようとおもったのですが、出来ませんでした。 このような事をする場合はどうしたらいいのでしょうか?
>>790 int const begin = 10;
int const end = 20;
ifs.seekg(begin);
int const length = end - begin;
file.resize(length);
ifs.read(&file[0], length);
>>791 ありがとう、だけどファイル以外のストリームに対しても同じ方法がとりたいとおもっているので、
algorithmのcopy、あるいはSTLの何かを使って解決したいのです。
で、思いついたのが790のコードなのです。
>>792 >791 はファイル以外のストリームにも使えるんじゃないか?
seekg() ができないかもしれないってこと?
そういや copy_n() ほしいな。
どうでもいいけどistream_iterator<char>使うな istreambuf_iterator<char>使え istream_iterator<char>はoperator>>で入力するから、空白とか スキップする。コピーにならんぞ
どうでもいい割には念を押すね。
>>795 それ「どうでもいい」事じゃないと思うw
あげあしはどうでもいいよ。
揚げ足取り、って言いたかったのかな。
手羽先、って言いたかったんたと思うよ
コケコッコーーー!!!
お前ら鳥類食ってて何も恥じらいはないのかよ。 哺乳類としてのプライドはどこへ
意味不明
つーか、ヘビとかトカゲとか、哺乳類を食うのは許せないよな。 やつら爬虫類が生まれた頃にはまだ哺乳類も鳥類も居なかったってのに。 赤外線センサーまでつけやがって。
面白いと思って書いてるのかな
鳥類爬虫類は許せるが 鯨だけは愛と権利が与えられるべきだと思います STL
何故か日本より沢山偶然鯨が掛かる隣の国には抗議しません
何でこんな流れに
みんな鳥類食ってて何も恥じらいもないからだと思う
牛食うのは禁止すべきだろ。
人食いてぇ
通報しますた
考え方を変えるんだ そこにシニカルなアーティクルか精神的原論を見出せるかどうかを試してから通報すべきだ 日本は民主主義社会だっていってたよ確か誰かが 毎日と朝日の新聞見ながら泡噴きながら 人食いてぇ=女の子監禁してぇ 人(で)食いてぇ=女の子換金してぇ 人=幼女 人=稚児 人=人 通報しますた
お前らSTLの話しろよ。 鳥類とか哺乳類とか人間とかあんまり関係ないだろ。
>>813 通報されないように気を付けて。
ところで、map<int,bar*> mに挿入する時、
m.insert(map<int,foo*>::value_type(0, new foo))とか
m[0]=new fooとか
するのはヤバいよね。
スマポ使えない状況でどう書くのが一番スマートですか?
foo* p = new foo; try { m.insert(map<int,foo*>::value_type(0, p)); // m[0] = p; } catch(...) { delete p; throw; }
まずmap<int,bar*>のbar*を、直接 opertaor =(bar *ptr) 出来ないようなクラスに置き換える。 ・map<int, test<bar> > 後はしらね。勝手に適当にメソッドでnewが隠蔽されるようなものでも書けば良いと思うよ。
foo* p = new foo(); if (!map.insert(std::make_pair(0, p)).second) { delete p; p = 0; }
p = repinterpret_cast<void*>(0);
>>819 insertで例外起きたらメモリリークするでよ
>>816 それだと m[0] に既存のポインタが入っていた場合にリークする。
↓これでいいかな?
foo* p = new foo;
try
{
&nbps; foo*& in = m[n];
&nbps; delete in;
&nbps; in = p;
}
catch (...)
{
&nbps; delete p;
&nbps; throw;
}
「スマポ使えない」と言ってもさすがに auto_ptr は使えるだろうから、
↓こっちのがいいと思う。
std::auto_ptr<foo> p(new foo);
foo*& in = m[n];
delete in;
in = p.release();
823 :
822 :2008/07/02(水) 13:37:02
うわ。 nbsp ミスった。最初のコード訂正。 foo* p = new foo; try { foo*& in = m[n]; delete in; in = p; } catch (...) { delete p; throw; }
foo * p = new foo; try { std::swap(p, m[0]); delete p; } catch(...) { delete p; throw; }
関数内クラスでauto_ptrもどきを自作すればいいんじゃね? 簡単に pair<map<int,bar*>::iterator, bool> ib(map.insert(std::make_pair(0, 0))); if (ib.second) ib.first.second = new foo; でも良い気がするけど。
こんばんは。g++でtr1::unordered_setを使おうと思ったのですが。 tr1::unordered_set< vector<unsigned char> >とすると ‘struct std::tr1::hash<std::vector<unsigned char, std::allocator<unsigned char> > >’ と怒られてしまいます。これは何が悪いのでしょうか? (vector用のhash関数を自分で作る必要があるということでしょうか?)
827 :
デフォルトの名無しさん :2008/07/05(土) 23:41:48
すいませんage忘れました。
>>826 コードとエラーメッセージをちゃんと貼れ。
デバッガとかでさ、変数名長すぎでしょ。 もう嫌だ。
#include <iostream> #include <vector> using namespace std; class A { int val; public: A(){cout<<"new"<<endl;} ~A(){cout<<"delete"<<endl;} void setval(int x){ val = x; } int getval(void){ return val; } }; int main () { A a; vector<A> list; cout <<"------------------------------------ Line1"<< endl; for ( int i=0; i<5; ++i ) { a.setval( i ); list.push_back( a ); } cout <<"------------------------------------ Line2"<< endl; //cout << "size:\t\t" << list.size() << endl; //cout << "list[data,3]:\t" << list[data, 3] << endl; for ( unsigned int i=0; i<list.size(); ++i ) { cout<< list[a,i].getval() << endl; } cout <<"------------------------------------ Line3"<< endl; list.clear(); cout <<"------------------------------------ Line4"<< endl; return 0; }
Line1とLine2の間の push_backのリサイズ時では何が起こっているのでしょうか
capacityが要素を保持するのに足りなければ、メモリの再確保が起きている。
ということは、一度破棄していると言うことでしょうか
そのクラスAにコピーコンストラクタも書いてみ
A(const A &obj){cout<<"copy"<<endl;} と push_back後に1loopの目安として新しく cout<<"----------------------------------"<<endl; を付け足して走らせてみたところ Line1とLine2の間の"copy"と"delete"の表示が copy がpushした回数+1 deleteがpushした回数 になりました。 copyの回数が+1なのが気になります。 入れる側の参照+listに入っている数と考えそうになりましたが これでサイズを比べて足りないようなら再確保…と考えるのは変よですね copyとdeleteの順番と回数を考えると 前のvectorから入っている分コピーした回数+付け足す側からコピーの一回分 という事でしょうか
あれ、ちょっと変ですね…3回目のプッシュで考えると 既にpushされているのが2個なので copy ←コピーしようとした ここでサイズが足りないので再確保 copy ←コピーしようとした copy ←前のvectorからコピー copy ←前のvectorからコピー delete ←入れようとした時のテンポラリの破棄? delete ←前のvectorに入ってるのを破棄 delete ←前のvectorに入ってるのを破棄 でしょうか、なんだか混乱してきました…。
ここでサイズが足りないので再確保 copy ←前のvectorからコピー copy ←前のvectorからコピー copy ←前のvectorからコピー copy ←新しい要素のコピー delete ←前のvectorに入ってるのを破棄 delete ←前のvectorに入ってるのを破棄 delete ←前のvectorに入ってるのを破棄 だろ。まぁ新しい要素をどこでコピーするかは実装依存だろうが。 valの値も表示させれば分かるべ。
それが4回目のpush_backなら納得できるのですが 3回目のpush_backでcopyが4つ表示されているので混乱しています。
iが3だから3回目とか勘違いしてないか?
略 copy copy delete -----------0 copy copy copy delete delete delete -----------1 copy copy copy copy delete delete delete -----------2 略 こう表示されています 環境は VC++2005EE +SDK win2000 です
class A { int val; public: A(){val=0,cout<<"new"<<endl;} A(const A &obj){cout<<"copy"<<endl;} ~A(){cout<<"delete"<<endl;} void setval(int x){ this->val = x; } int getval(void){ return val; } }; 略 cout <<"------------------------------------ Line1"<< endl; for ( int i=0; i<5; ++i ) { a.setval( i ); list.push_back( a ); cout<<"----------------------------------"<< i <<endl; } cout <<"------------------------------------ Line2"<< endl; 略 ソースはこうなってます
copy ----------------------------------0 copy copy delete ----------------------------------1 copy copy copy delete delete ----------------------------------2 うちではこうなった。 VC++2008EE forループ入る前にvectorになんか入れてない? size()の値表示させてみ。
これが全文です。 #include <iostream> #include <vector> using namespace std; class A { int val; public: A(){val=0,cout<<"new"<<endl;} A(const A &obj){cout<<"copy"<<endl;} ~A(){cout<<"delete"<<endl;} void setval(int x){ this->val = x; } int getval(void){ return val; } }; int main (){ A a; vector<A> list; cout <<"------------------------------------ Line1"<< endl; for ( int i=0; i<5; ++i ){ a.setval( i ); list.push_back( a ); cout<<"----------------------------------"<< i <<endl; } cout <<"------------------------------------ Line2"<< endl; for ( unsigned int i=0; i<list.size(); ++i ) { cout<< list[a,i].getval() << endl; } cout <<"------------------------------------ Line3"<< endl; list.clear(); cout <<"------------------------------------ Line4"<< endl; return 0; }
2005入れてないから2003でやってみたらそうなった。 ソース追ってみると、追加する要素を一旦ローカル変数にコピーしてた。 その変数のコピーと破棄が1回ずつ多いみたい。 2005のソースはわからんが多分同じ理由だろう。
なるほど、これで胸のつかえが取れました 付き合ってくれた皆さん、本当にありがとうございました。
>>844 >追加する要素を一旦ローカル変数にコピーしてた。
list.push_back( list[3] );
string::find()は内部でどのようなアルゴリズムが使用されているのでしょうか? string text="000...01"; // text.size()==100000 string pattern="000...01"; // pattern.size()==10000 text.find(pattern); としたとき、自前で実装したKMPと比較して明らかに遅いのですが・・・
std::strstr
>847 環境による ヘッダ嫁
ていうか、「同じ文字列を何度も探索する」という前提で 前処理が必要となるBM法とかを 1回しか探索しないfindやstrstrが使ってるわけ無いじゃん。 当たり前すぎる。 おまえのKMP法は、前処理の時間も含めてもfindより速いのか、 つまり、毎回探索文字列が変わる処理に適応できるのか その辺から考察してみろよ。
この例なら前処理の時間を含めても速いだろ
じゃあ、findは(短い文字列探索の時間が長くなることなど気にせず) 探索文字列の長さを調べてから探索アルゴリズムを選択するように実装すべき、ということで。
そうだ、もうひとつ。 strstrが特殊アルゴリズムを用いない理由として テキストの長さが不明な場合には BM法とかの非全文字探索アルゴリズムが使えない、というのがあるけど findに関しては、(ランダムアクセス可能なものは)テキストの長さが事前にわかるから アルゴリズム選択は完全にバカげてる、と言いきれるほどではなさそうだね。 実際、set::find等は、そのコンテナ向きのアルゴリズムで実装されてるし。 とはいえ、それをふまえても find(やstrstr)は1回きりの短文探索向きのままで それ以外でかつ速度が必要なら自分で実装して使い分ける、という 今の形の方がずっと良いとは思うけど。
847です。 前処理は大した速度低下には繋がらないと思いますが、 確かに無駄ではありますね。標準ライブラリは特殊な例に対しても 致命的に遅くならないように実装されているものだと認識していたので、意外でした。 ただ、memcpy()とmemmove()みたいなのがあるのなら、 find_kmp()とかfind_bm()とか用意してくれていても良いような気が… >> 850 > 「同じ文字列を何度も探索する」という前提で〜 そんな前提がありましたっけ?自分の理解不足でしたらすみません
すれ違いだったらすみません。 STLPortの分かりやすいリファレンスマニュアルってあるんですか? 探したんですが見つからなくて・・・ 英語でもかまいませんので知っていたらお願いしますm(_ _)m
856 :
デフォルトの名無しさん :2008/07/23(水) 09:46:17
STLは標準規格ですよ 日本語のでOK 実装している人が違っていて、速度やバグが違うだけです。
例外関係とかも統一されてるのかな? まったく同じならVisualStudioのマニュアルを参考にします。 ありがとうございますm(_ _)m
858 :
デフォルトの名無しさん :2008/07/23(水) 10:28:56
VisualStudio付属のやつでいいじゃん
Portにしかないやつを使いたいんだろ。
添削するところはねーだろう。 それよりコンテナの違いを、馬鹿後輩にもわかるように一つ頼むよ。 vectorをlistにキャストしちゃだめだぁぁぁぁぁぁぁぁ! 気の利いた説明はできないけど、ぜんぜん駄目なんだぁぁぁぁぁぁぁ! ごめん、おれ、うまく説明できないんだ。 あした、おれが直すんだ。。
delete とか state とかって何だ?
bufferが残ったままというのは消せないというよりやるせないじゃないだろうか。
>>861 「全く違うクラスはキャストできないだろ?」
もしくは、
>>861 「vectorをlistとか、ありえないです!クズです!しねです!
Enterキーとリセットボタンこっそり入れ替えられろです!
むしろ人生リセットしろです!!」
って、ひかれるくらい可愛くな。
ありそうなキャスト。 class CDerived が class CBase の派生とき vector<CBase*>* を vector<CDerived*>* にキャスト。
868 :
861 :2008/08/01(金) 01:22:54
>>864 俺が悪かった。
>>865 俺も勉強不足だった。 俺が勉強してから、後輩にurl教える。
ちなみに、キャストはCキャストだったので、多分、、なにそれおいしいの状態だと思う。
ともあれthx.
ともかく C 系のスレでは '=' の記号の扱いにもうすこし敏感になっても良いかと思う。
( ´・д・) =3 こういうの見るとキャストしたくなる みたいな?
yareyare_daze('A') =3
キャストの前に定数をdefineしてないのが許せんw
STLを使って、ソートされていないstd::vector<int>からi番目に大きい要素〜j番目に大きい要素までを取り出す必要があります。std::(partial_)sortを使うよりも高速な方法はありますか?
>>874 それはソートするしかないだろう。
順番が重要でなければ、nth_element使ってi番目を求めて、
i以降に対してもう一度nth_elementという方法もあるが
partial_sortと大して変わらないと思う。
>>874 一度全体順位(sort)出さないと不可能
sortする時間が問題ならmapとかにしてみては如何か。
>>874 ソートされていないvector<int>という条件は鵜呑みにするとして、
他に何か特別な性質はあるか?
そこから突いていけば手はあるかも知れない
そこに何の前提も置けないならry
そうなってくるとアルゴリズムの話だわな
881 :
875 :2008/08/06(水) 03:01:58
nth_elementは思ってたより速かった。(VC++2008) ずっと前に作った中央値を求めるベンチマークを再度実行してみたら、 要素数10万でsortやpartial_sortの5倍くらい速いわ。 nth_elementがこれだけ速いなら、iとjの範囲によっては、nth_elementを 2回やってから、その部分だけsortの方が速いかもしれないね。 中央値を求める目的では、partial_sortはsortと大差なかった。 良くて10%速い程度かな。もっと小さい範囲で使うものだね。 ちなみにmultisetに突っ込むのは、恐ろしく遅かった。
というか、nthのnは幾つだよ。
中間値でかんべんしてください >_<)
いえ、ゆるしませんわよ
ふんがー
かーいかいかい
std名前空間にsinとかcosとか算術関数があるんだけど stlportとか入れるとこういうのも置き換わって高速化されたりするんですか?
sinやcosはSTLじゃない。
おkサンクス
ちょっと質問です。XP、VC2005です。 class CHoge { public: CHoge() { a = new int; } int* a; }; のように、メンバを全てコンストラクタで動的に作成するクラスがあります。 std::vector<CHoge> hoge; hoge.resize(10); *hoge[0].a = 10; *hoge[1].a = 20; とすると、*hoge[0].a、*hoge[1].a ともに20となってしまいました。 意図としては new は 10回通る予定だったのですが、 実際に new を通ったのは1回だけで、残りはコピーコンストラクタで初期化されてしまったようで、 a 自体がコピーされ、10個の *a が全て同じ場所をさしてしたようです。 pimpl などで割りとよく使われる実装だと思うのですが、 この resize の挙動は規格で決まっているのでしょうか? これを解決するには、コピーコンストラクタを実装するか、 コンストラクタではなく初期化関数を作って自分で呼び出す、しかないでしょうか? よろしくお願いします。
古い版では void resize(size_type sz, T c = T()); 新しい版では void resize(size_type sz); void resize(size_type sz, T c); になってる気がする・・・ 知らん間に変わったのかも いずれにせよ、コピーコンストラクタを実装しとくのが身のため その例にはないけど、デストラクタで解放するんだろ? vectorのcapacityが溢れたときに死にそう
安全にコピーできないオブジェクトをコンテナに入れる時点でまずい
894 :
デフォルトの名無しさん :2008/08/13(水) 11:43:40
>>894 先ずは、どう「うまく行かなかったか」を説明するといいよ。
vectorから特定の要素を削除した場合ってどうしてます? 自分は通常、一番後ろから移動してきてpop_backしちゃうんですけど それだとインデックスが変わってしまうので面倒な場面があります そこで、空きインデックス用のvectorを別に作り、要素削除時にその インデックスを登録していき、push_auto等の関数を作って空き領域に 入れていく方法を考えたりと、試行錯誤しています なんかこの辺をうまいこと解決したコンテナってSTLにないですかね^^;
#include <functional>はした? binary_functionはいくつかのtypedefをするのに必要。
898 :
895 :2008/08/13(水) 11:54:22
template<class T> struct func : binary_function<T, T, bool> { bool operator()(const T& X, const T& Y) const{ return (X < Y); // ←ここを書き換える } }; これで、 expected `{' before '<' token expected template-name before '<' token expected unqualified-id before '<' token のようなエラーが出てしまいました。
899 :
895 :2008/08/13(水) 11:57:56
>>897 ありがとうございます!
#include <functional> してませんでした。
しかし、これを書き足した上でコンパイルしても同じエラーが出ました。
>>899 エラーがどの行で出たのか位書けませんか?
それとも、その辺りを察しろと言うことですか?
それから、名乗るのなら「894」でしょ。
>>900 >894に書かれているサイトのソースの該当行を書き換えた結果が>898。
902 :
894 :2008/08/13(水) 12:03:09
>>900 // ここを書き換える の部分のことですよね??
とりあえずコンパイルしてみただけなので、まだ書き換えてないです。
>>901 すいません。
>>898 の2行目で出ています。
俺の所でもやってみたけど症状が再現せんぞ。 VC9.0
904 :
894 :2008/08/13(水) 12:05:52
ああ。。コンパイラ書いてなかったです・・ 自分のところはMinGW5.1.3です。
#include <vector>も必要なんじゃないの? まあqueueの中でincludeしてるかもしれんが
906 :
894 :2008/08/13(水) 12:11:49
vector はinclude 済みでした。。うーむ。
これで俺の所ではエラー無し。VC9.0 #include <iostream> #include <cstdlib> #include <vector> #include <functional> #include <queue> template <class T> struct func : std::binary_function<T, T, bool> { bool operator()(const T& X, const T& Y) const{ return (X > Y); } }; int main() { std::priority_queue<int, std::vector<int>, func<int> > pq; int i; for (i = 0; i < 10; i++ ) pq.push(std::rand()%10); while (!pq.empty()) { std::cout << pq.top() << ' '; pq.pop(); } std::cout << std::endl; }
MinGW 3.4.5 + STLport 4.6.2 でもエラー無し
909 :
894 :2008/08/13(水) 12:24:03
ぐっは template<class T> struct func : binary_function<T, T, bool> { bool operator()(const T& X, const T& Y) const{ return (X < Y); // ←ここを書き換える } }; のあとでnaming use space std; してました。 binary_functionがstd だったんですね。。ありがとうございましたm(_ _)m
もはやネタとしか思えん。
STLに取りかかる前にC++の基礎をやった方がいいのでわ・・・・
名前空間を知らなかったんじゃなくて、binary_funtion が std 空間にいることを知らなかっただけだろう C++ の基礎とか関係ない。煽りたいのならもうちょっとましな煽り方をしろよ
逆ギレキタ━━━━(゚∀゚)━━━━!!
いやいや、それ以前に naming use space std ってところが怪しさ満点
夏休みだねえ・・・
916 :
894 :2008/08/13(水) 14:03:13
役立たずさん達ありがとね
自分の不甲斐なさを差し置いて何をゆー
「nth_element」の読み方を教えてください。 えぬすえれめんと?
んすえれめんと
えぬてぃーえいちあんだーばーいーえるいーえむいーえぬてぃー
setのeraseって存在しないものを与えても大丈夫ですか? マニュアルなどを見ても何も記載がないので、 VC++やg++で試してみると何も起きないので平気かなと思ったのですが。 #include <set> int main() { std::set<int> s; s.insert(1); s.erase(2); }
>>921 そりゃそうだろ
ところで削除した数を返すので試してみな
ゼロを返すはずなので
923 :
デフォルトの名無しさん :2008/08/14(木) 10:45:43
自作のSTLやテンプレート使いまくりの行列計算プログラムをVS2005の AcademicEdition のC++でDebug実行すると、STLのlistライブラリの中、 213行目で「iterator not dereferencable」という実行時エラーが出て しまいます。このエラーの意味ってなんですか? VC++2003まではこんな エラーが出ていなかった気がするんですが。プログラムも変更した覚えは ないですけど
辞書使えよ 我々はエスパーではない。 コードも貼らずにエラーの原因が解かるとでも思ってるのか。
925 :
デフォルトの名無しさん :2008/08/14(木) 11:04:30
はいはい。お前には聞いてないよ。ひっこんでろ
エスパーレスだが end越えてデータ取得しようとしてるんじゃね?
928 :
デフォルトの名無しさん :2008/08/14(木) 11:20:13
>>926 あるがとうございます。私もそれを疑って調べています。
外国の掲示板に「iterator not dereferencable」の実行時
エラーが出てきたという質問があって、やはりそのような
関係のエラーが考えられる、前のプログラムが正しくない
からだという回答がありました。
質問者は以前のコンパイラ(VC++7.0)ではそんなエラーはでな
かったと言ってましたが。
私自身もVS2003では実行時エラーが出なかったプログラムが
VS2005で出だしてよく調べたら、プログラムにバグがあって
VS2003では見逃されていたという苦い経験があります。
いまテンプレート使いまくりの呪文みたいなコードをチェック
してますが、まだバグをみつけきっていませんorz
929 :
デフォルトの名無しさん :2008/08/14(木) 11:23:13
あるがとう→ありがとう 前のプログラム→お前のプログラム
vector<T>::iterator i=container.begin(); i--; // 無効なデクリメント みたいなコードが入ってるのでは? VS2003は iterator は T* のtypedefだから範囲検査がなかったけど、 VS2005のdebug 版はちゃんと警告を出してくれるとか
そのへんってSTLのバージョンで変ったってことなのか? STLPortとか使ってるとまた違うのかな・・・
STLPortのデバッグ版は昔からいろいろチェックしてるはず。Effective STLにも載ってたな。 VCはVC8(2005)からそのへん強化されたんだっけ。
933 :
デフォルトの名無しさん :2008/08/14(木) 12:43:19
>>930 >vector<T>::iterator i=container.begin();
>i--; // 無効なデクリメント
もろにこれと似たコード使ってます(;^ ^)。++iですけど
やはり、end()をオーバーしているか、インサート
した後に古いイテレータで参照しているんでしょう。
VS2005のヘルプには、確かに標準C++ライブラリの新機能として
『不正な反復子の使用を検出する機能がサポートされました。
詳細については、「反復子のデバッグのサポート」と「Checked
Iterators」を参照してください』
とあります。
ともかく、エラーの見当がついてきました。
ありがとうございました。
>>933 >やはり、end()をオーバーしているか、
念のため、end()は、有効な範囲の一つ後ろにあるから、end()を"オーバー"しなくても、
end()に到達した状態で参照するとエラーになるよ。
ここを読んでいるとほんとうにためになるな。 自分では一度も経験した事のないエラー例が山ほど 書き込まれて、しかもそれの原因を探るのはなんか オラはワクワクするぞ。
VS2008SP1がstd::tr1に対応したので、STLportも対応して 欲しい所なんだが今はどうなってるんだろう
見た感じunordered_map/set(だけ?)はあるっぽい
mem_fnもあるんじゃね?
pair<int,string>のintのほうを優先度として扱うpriority_queueを作りたいのですが、 もっとも短い宣言方法を教えてください。
priority_queueでググれ
pairのoperator<は、まずfirstを比較してくれるようなので自作のComparatorは不要でした。
最小値を先に取り出したい時も、単にgreater<T>を使えばいいのね。どーも
>>940
942 :
デフォルトの名無しさん :2008/08/18(月) 19:13:35
C++用のライブラリ作ってるんだが、 リスト(主にdoubleを想定)を受け取る関数やコンストラクタは どんな受け取り方すれば使いやすいか迷ってる。 いつもどう書いてる? beginとend?
ケースバイケースだろ、んなもん。
template化可能なら template<class T> void func(std::list<T> &lst) リスト以外のコンテナも渡したくなったら template < template<class T, class Allocator=std::allocator<T>> class ConT > void func(ConT<T> &con) こうやってる
普通iteratorかrangeじゃね
コンテナを出力先にする場合、iteratorやrangeじゃ無理だろ?
というかコンテナでやりとりしてたら何の為のイテレータ?って事になるじゃん
inserter使えばいいじゃん。
何が何やら
例えばvectorの先頭に要素追加したい場合、inserterじゃ無理じゃないの?
は?
そもそも、>942はリストコンテナを受け取る関数としか書いてないのに……
リストを読み取りながら特定の要素の間に何かを挿入したい時、 iteratorだけではどう書けばいいでしょうか?
>>953 現状では list 本体を使う必要がありそうだなぁ。
手動で実装する双方向リンクリストだと可能な気がするんで、 std::list に
static な insert(iterator, value_type) や splice() があるといいのかも。そうなると
size() がリストを走査することがほぼ確定するんだけど、現状でもたぶん splice() を
定数時間にするためには避けられないだろうから、あんまり問題なさそう。
>>944 後者に初めて関数ポインタを見たときのような感動を覚えた
#include <map> struct ab_t { int a; int b; }; int main() { st::map<const char*, ab_t> foo; foo["bar"] = {0, 1}; return 0; } としたいんですが、foo["bar"] = {0, 1};の箇所が代入できません。 構造体の初期化とmapへの要素追加を同時に行うには、 どのようにすれば良いでしょうか。
mapのキーがconst char*なのはどうかと思うけど、 コンストラクタ付ければ良くね? 無理なら、struct cab_t : ab_t{ cab_t(){ ... } }; みたいな ラッパクラス作るとか。
コンストラクタを付けられないとしても、ab_tを作って返す関数で十分だろ foo["bar"] = make_ab_t(0, 1);
つboost::assign
960 :
デフォルトの名無しさん :2008/08/21(木) 14:35:07
>>958 コンストラクタを付けられない理由なんてないでしょ。
初期化したいならコンストラクタ、これ常識。
>>960 この場合にコンストラクタを追加するのに反対するわけじゃないけど、
対象環境によっては POD にしておきたいからコンストラクタを付けられないってことは
めずらしくもない。
>>960 そう、お前の常識は他人にとっては非常識。
963 :
デフォルトの名無しさん :2008/08/21(木) 15:17:08
>>961 STLに使う構造体をPODにする理由について。
そもそもab_tの定義を変更できるかどうか分からん
non-intrusiveなコンストラクタを付けよう
967 :
デフォルトの名無しさん :2008/08/23(土) 02:53:08
Accelerated C++という本に back_inserter (<iterator>ヘッダ)を使うには そのコンテナが push_back 関数を持っていなければならないと書かれていて、 自作のコンテナ Vec ( vetor に似たクラス)に push_back 関数を実装して Vec< int > v, u; v.push_back( 1 ); copy( v.begin(), v.end(), back_inserter( u ) ); というようなコードが出てくるのですが これを bcc32 や VC2008 でコンパイルすると エラー E2404 c:\Borland\Bcc55\include\rw/iterator.h 636: 依存関係にある型限定子 'Vec<int>' に 'const_reference' という名前のメンバー型がない(関数 main() ) (bcc32の場合) 1>c:\program files\microsoft visual studio 9.0\vc\include\iterator(22) : error C2039: 'reference' : 'Vec<T>' のメンバではありません。 (VC2008の場合) というようになってしまいます。なんででしょう? っていうか、reference や const_reference なんてメンバ作れとは Accelerated C++ には一言もかかれてないんだけど・・・。
イテレータについてiterator_traitsを特殊化してないんじゃない?
ああすまん、この場合定義が足りてないのはイテレータじゃなくてコンテナのほうだな。 beginとかendとかはイテレータを返す関数だろ。 例えばbeginの宣言はこうなってるはずだ。 iterator begin(); const_iterator() begin() const(); で、このiterator、const_iteratorはコンテナごとにtypedefしておく必要がある。
970 :
デフォルトの名無しさん :2008/08/23(土) 03:28:51
なんで
971 :
デフォルトの名無しさん :2008/08/23(土) 03:29:59
ぎゃーw
>>970 はミス。
スルーでお願いします
973 :
970 :2008/08/23(土) 08:23:46
やだよ
エー
>>969 > const_iterator() begin() const();
これは無いわw
括弧付けすぎ
格好わるww
((const_iterator) (begin) (const))
Lisp風?
BOOST_PP_SEQみたいだ
boost::preprocessorとか使って、 #define VARIABLE_A 1 #define VARIABLE_B 2 #define VARIABLE_C 3 ・・・ ってA〜Zまで書くのマクロにできない?
つ[enum]
すまん間違った #define VARIABLE_1 A #define VARIABLE_2 B #define VARIABLE_3 C こうだ
>>983 無理
マクロ定義をコンパイル時に生成する手段は無い
それからスレ違い
そもそもそのAやらBやらは何に使うんだ
さらに別マクロのためのプリプロセストークンかな
987 :
981 :2008/08/23(土) 22:18:08
すまんかった
cppppの出番ですな さらにcppppのソースをppするppのppが・・・
この例ならcppを二回通せば十分だけどな
古き悪きm4使おうぜ!!
さあ、そろそろ次スレの話を始めようか