C++相談室 part85
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2010/10/09(土) 20:22:35ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレに
お願いします。
前スレ
C++相談室 part84
http://hibari.2ch.net/test/read.cgi/tech/1284736187/
0653デフォルトの名無しさん
2010/10/29(金) 02:03:200654デフォルトの名無しさん
2010/10/29(金) 02:23:490655デフォルトの名無しさん
2010/10/29(金) 03:38:45クラスは定義できますか?
0656デフォルトの名無しさん
2010/10/29(金) 03:49:040657デフォルトの名無しさん
2010/10/29(金) 04:10:230658デフォルトの名無しさん
2010/10/29(金) 08:36:16パターンありますか?
0659デフォルトの名無しさん
2010/10/29(金) 11:40:370660デフォルトの名無しさん
2010/10/29(金) 15:53:21しかしヘッダ行[1]とデータの出力行[2]が離れているので、
出力したい項目の追加削除など変更があった場合に
[1]と[2]の2箇所の変更が必要になり、出力項目が多い時はメンテナンスが大変です。
そこで以下のようなクラスを作って楽に管理しようと思いました。【ソース2参照】
使うときはこうします。【ソース3参照】
でも、print_dataというメソッドを実装することって非常に非常に難しいです。
ラムダ式の変数のキャプチャ(?)とかリフレクション(?)とか
マクロをうまく使うとかなんとかして
実現することはできませんか?
同等のことが可能な、スーパープログラマによって書かれたライブラリは存在しませんか?
VC10とgcc4.4で使えるならC++0xの機能や独自拡張を使っていてもかまいません。
疑似コード→ http://codepad.org/Z0j4VE1u
0661デフォルトの名無しさん
2010/10/29(金) 16:13:430662デフォルトの名無しさん
2010/10/29(金) 16:50:25かなりレアだな
0663デフォルトの名無しさん
2010/10/29(金) 16:52:300664デフォルトの名無しさん
2010/10/29(金) 17:19:22取り敢えず、こんなのどう?
http://codepad.org/ZMJP9HtC
ヘッダの数だけきっかりprint_data()を呼ぶって言う制約がつくけど。
0665デフォルトの名無しさん
2010/10/29(金) 21:54:31vector<pair<string,function<string()> vec;
int a;
double b;
vec.push_back(make_pair("a",[&](){return boost::lexical_cast<string>(a);}));
vec.push_back(make_pair("b",[&](){return boost::lexical_cast<string>(b);}));
coust<<vec[0].first<<vec[0].second()<<endl;
coust<<vec[1].first<<vec[1].second()<<endl;
0666デフォルトの名無しさん
2010/10/29(金) 22:10:13struct Foo
{
template<typename T>
Foo& operator<<(const T& rhs)
{
std::cout << rhs;
return *this;
}
} foo;
int main()
{
foo << 1 << "test";
foo << std::endl; // error: no match for ‘operator<<’ in ‘foo << std::endl’
return 0;
}
これ、何でですか?
0667デフォルトの名無しさん
2010/10/29(金) 22:23:03endl のテンプレート実引数が不明
0668デフォルトの名無しさん
2010/10/29(金) 22:31:18だからTが曖昧になっちゃう
0669デフォルトの名無しさん
2010/10/29(金) 22:41:34http://codepad.org/KH5rpOc8
0670デフォルトの名無しさん
2010/10/29(金) 22:52:39ありがとうございます。
試しにdecltype(std::endl)とかやってみるとやっぱりerror: ‘std::endl’ refers to a set of overloaded functionsと怒られますね。
>>669
> std::ostream& (*ENDL)(std::ostream& os)
std::ostream& (&ENDL)(std::ostream& os)
でもよいですよね?(実際に試してみてコンパイルエラーは出てないのですが)
インライン化されるか気になって関数のポインタ取るのに抵抗ありまして。
(実際はその程度は関係ないですか?)
0671デフォルトの名無しさん
2010/10/29(金) 23:30:25凝ったテキスト処理とかやらんからセオリーは知らないけど
ヘッダとやらの項目ごとにデータを溜めてから
一気に書き出した方がいいんじゃないのか?
0672デフォルトの名無しさん
2010/10/30(土) 00:00:04入門書などのクラスの説明で、よく FILE* のラッパークラス CFile があると思います。
class CFile
{
0673デフォルトの名無しさん
2010/10/30(土) 00:01:430674デフォルトの名無しさん
2010/10/30(土) 00:04:14話が高度すぎてついて行けなかった
手元の「C++再考」を読みながら勉強します
0675デフォルトの名無しさん
2010/10/30(土) 00:11:33ちょっと質問です。
入門書などのクラスの説明で、よく FILE* のラッパークラス CFile があると思います。
class CFile
{
public:
bool open();
bool close();
private:
FILE* m_fp;
};
コンストラクタで m_fp を初期化し、
デストラクタで m_fp が有効なら fclose でファイルを閉じています。
よくある例ですが、これ、std::vector に入れれないですよね…。
resize でサイズを増やすだけで、一時オブジェクトのデストラクタが走って
予期せずファイルが close されてしまいます。
解決するには参照カウンタを用意し、
コピーコンストラクタなどを適切に書く必要があると思いますが、
特に Windows なら HWND、HFONT、HBITMAP、など
ハンドルのラッパークラス全てに同じ問題がおきます。
どのように解決するのが普通なのでしょうか?
全てに参照カウンタを準備して管理しなければいけないのでしょうか。
すればいいと言われればその通りなのですが、上記クラスに対して「std::vector には入れれない」という解説が見つからなかったので、
誰もが通りそうな問題なのにおかしいなと思って質問です。よろしくお願いします。
0676デフォルトの名無しさん
2010/10/30(土) 00:25:460677デフォルトの名無しさん
2010/10/30(土) 00:26:59配列のコピーを避けることこそ誰もが通る問題で
C をやらないネイティブ C++ 世代の感覚が異様に見える
0678デフォルトの名無しさん
2010/10/30(土) 00:28:380679デフォルトの名無しさん
2010/10/30(土) 00:31:01通常のコンストラクタの他に
CFile():m_fp(NULL){}
みたいなデフォルトコンストラクタを作っといて
デストラクタで
if(m_fp)fclose(m_fp);
ってやれば当面の問題は解決されるんじゃないの?
0680デフォルトの名無しさん
2010/10/30(土) 00:37:16解決されるわけないだろバカ
0681デフォルトの名無しさん
2010/10/30(土) 00:39:41どうしてvectorに入れたいんだろう?
vector<shared_ptr<CFile>>だと明示的にクローズしないとクローズされなくなるような…
それとも使う度にvectorからは抜くとか、vectorごと捨ててまとめてクローズしたいとかそういうことなの?
0682デフォルトの名無しさん
2010/10/30(土) 00:46:270683デフォルトの名無しさん
2010/10/30(土) 00:49:33読解力の低さと思考停止の早さがひどすぎて回答が難しいよ
もう少し頑張れよ
0684675
2010/10/30(土) 00:51:42C のころはデストラクタもないし、malloc / realloc で何も問題なかったんですよね…。
vector<shared_ptr<CFile> > で解決できそうです。
RAII の解説のところで、コピーコンストラクタなどを private にして
コピーを防いでいる例も見つけましたので、合わせて使おうと思います。
ありがとうございました!
0685デフォルトの名無しさん
2010/10/30(土) 00:55:08いやどういうときに使うものなのか見当がつかないだけだよ
0687デフォルトの名無しさん
2010/10/30(土) 00:56:29FILE*だもんな・・・
0688デフォルトの名無しさん
2010/10/30(土) 00:59:21ゴメン
やっぱboost::ptr_vector駄目だわ
これresizeするとポインタを通してデストラクタを呼ぶためのコンテナなんだよね
だからこの場合は駄目だと思う
0689デフォルトの名無しさん
2010/10/30(土) 01:33:47要するにこういう感じで勝手にデストラクタが呼ばれるといけないわけだよね?
#include <iostream>
#include <boost/ptr_container/ptr_vector.hpp>
class Test {
int i;
public:
Test(int j) : i(j) {}
~Test() { std::cout << "~Test(" << i << ") is called" << std::endl; }
};
int main()
{
boost::ptr_vector<Test> ptt;
for (int i = 0; i < 10; i++)
ptt.push_back(new Test(i));
boost::ptr_vector<Test>().swap(ptt);
std::cout << "Excecution done" << std::endl;
}
~Test(0) is called
~Test(1) is called
~Test(2) is called
~Test(3) is called
~Test(4) is called
~Test(5) is called
~Test(6) is called
~Test(7) is called
~Test(8) is called
~Test(9) is called
Excecution done
0690デフォルトの名無しさん
2010/10/30(土) 01:35:14vector を参照かポインタで扱っても、もともとの問題である vector に CFile を入れる段階の
問題が何も解決しない。
配列のコピーが行われたところで十分な空間・計算リソースがあれば問題にならないんで、
誰もが通る問題とも思えない。
0691デフォルトの名無しさん
2010/10/30(土) 01:36:14何も問題ないように見えるが、何がダメだって言うの?
0692685
2010/10/30(土) 01:43:44ちょくちょく出し入れしないとsharedする意味がないし、vectorにそれが向いてるとは思えない。
コンテナに入れる用途だとselectポーリングするとか、サーバー側のソケット/パイプ管理や
クライアント側のコネクションプールのようなものとかだけど、ポーリング以外では切断する役割
よりも使用未使用管理になると思うし、ポーリングを使うような状況でvectorは俺なら使わない。
そもそも面倒なのでポーリングしないで一個ずつスレッド使っちゃうし。
誰かvector<shared_ptr<CFile>>の利用用途を教えてくれー。
0693デフォルトの名無しさん
2010/10/30(土) 01:50:02いやいやだからpush_backしていくうちにメモリの再配置が起きてその時に
勝手にデストラクタが呼ばれてファイルストリームがクローズしちゃうじゃん
それを嫌がってるんでしょ?
自分でデストラクタを呼び出すならstd::vector<CFile*>でも何の問題もないような気がするんだけど
0694デフォルトの名無しさん
2010/10/30(土) 01:51:56shared_ptr が使われてるのは、単に C++2003 にはムーブや unique_ptr が無いからでしょ。
出し入れがしたいわけじゃないと思うよ。
「〜ような状況でvectorは俺なら使わない」と言うけど、それこそ理由が不明。
単に CFile の配列が欲しくて、実行時にしか要素数が決まらないってだけで十分でしょ。
0695デフォルトの名無しさん
2010/10/30(土) 01:56:02素人考えだとならlistではダメなの?って思うのですよ
利用用途が思いつかないからいいのかどうか見当もつかないんですけど
0696デフォルトの名無しさん
2010/10/30(土) 01:56:40単にoperator[]を使いたいんだと思うよ
0697675
2010/10/30(土) 01:59:35>いやいやだからpush_backしていくうちにメモリの再配置が起きてその時に
>勝手にデストラクタが呼ばれてファイルストリームがクローズしちゃうじゃん
まさにこれです。
vector<CFile> files;
files.resize(1);
files.resize(2); // ←ここでメモリの再配置がおきて、files[0] のデストラクタでファイルが閉じられるので困る
CFile の配列を使うことはあまりないかもしれませんが、
可変個のウィンドウを扱う(HWND)、ビットマップを扱う(HBITMAP)、などはよくあると思います。
>>692 で1個ずつスレッドにしても、スレッドを管理する HANDLE を持つクラスの可変長配列が必要です。
0698デフォルトの名無しさん
2010/10/30(土) 02:00:40何のための ptr_vector だよ。
ptr_vector なら再確保が発生してもポインタのコピーだけすればよくて、
オブジェクト本体のコピーが要らない。したがってデストラクタが呼ばれたりもしない。
自分でデストラクタを呼び出すなんて、論外だね。
0699デフォルトの名無しさん
2010/10/30(土) 02:06:140700デフォルトの名無しさん
2010/10/30(土) 02:07:290701デフォルトの名無しさん
2010/10/30(土) 02:10:21それはわかってる
でも今回のように勝手にデストラクタが呼ばれては困るファイルストリームインスタンスへの
ポインタを保持する場合は駄目でしょって
0702デフォルトの名無しさん
2010/10/30(土) 02:12:460703デフォルトの名無しさん
2010/10/30(土) 02:16:31なるほどまづは前提として受け入れろと
>>697
なるほど。リソースハンドル全般の話で使いまわしとは関係がない話なのですね。
オブジェクトとリソースの生成/消滅は原則連動してて、未参照状態で自動的に
消滅さ&コンテナはとにかくvectorがいいと。
0xはまだまだ知らないことだらけだけど、なんか面白そうですね。
0704デフォルトの名無しさん
2010/10/30(土) 02:21:19>>689にこれじゃ駄目でしょうって例をわざわざ貼り付けたんだけど理解できないかな?
0705デフォルトの名無しさん
2010/10/30(土) 02:31:12テンポラリに swap() で内容を移してるんだから、そのテンポラリの消滅で
デストラクタが走って当然。これを「勝手に」とか言ってるのがどういうことなのか
理解できない。
0706デフォルトの名無しさん
2010/10/30(土) 02:37:08いやだから・・・std::vectorでpush_backして行くとそのうち連続したエリアが足りなく
なってメモリの再配置が起きるでしょうって
boost::ptr_vectorも事情は同じですよって言う意味で書いたんだけど分かってもらえないかな?
0707デフォルトの名無しさん
2010/10/30(土) 02:46:410708デフォルトの名無しさん
2010/10/30(土) 02:48:16外行って頭に水ぶっかけて来い
0709デフォルトの名無しさん
2010/10/30(土) 02:50:18http://ideone.com/C0UYF
capacity() == size()はcapacity()が満たされた場合であり、再配置が起こる
明示的にresize()も呼び出してみた
再配置が起こってもデストラクタは起動しない
スコープアウトしてはじめてデストラクタが起動する
0710デフォルトの名無しさん
2010/10/30(土) 02:52:21おっと。似たようなことしてる人が・・・
0711デフォルトの名無しさん
2010/10/30(土) 02:53:380712デフォルトの名無しさん
2010/10/30(土) 03:00:010713デフォルトの名無しさん
2010/10/30(土) 03:04:270714デフォルトの名無しさん
2010/10/30(土) 03:05:560715デフォルトの名無しさん
2010/10/30(土) 03:18:200716デフォルトの名無しさん
2010/10/30(土) 03:19:55・但しイテレータは無効になる
か
0717デフォルトの名無しさん
2010/10/30(土) 03:28:21あくまでポインタを保持している場合の話な
>>709のコード貼っといて言うのもアレだが
オレはコンテナにファイル管理クラスを突っ込んだりしないけどな
入れるとしたらファイル名とかリソースバッファか
ファイル処理なんてエラーが出やすいし、アクセスは単純化してわかりやすい方がいい
こんな論争現場でしたくないだろw
0718デフォルトの名無しさん
2010/10/30(土) 03:31:420719デフォルトの名無しさん
2010/10/30(土) 09:58:53CFileってコピー可なのか?普通はコピー不可にするべきだろう。MFCって一体?
コピー不可でも、C++0xならムーブ可にしておけばvectorに入るだろうし、突然閉じたりしないしな
0720デフォルトの名無しさん
2010/10/30(土) 10:39:12それにMFCのCFileはコピー不可だよ
0721デフォルトの名無しさん
2010/10/30(土) 13:15:33list じゃだめなん?
HWND なんか典型的にリストの出番だと思うし
それ以前に EnumWindows だろ
vector に push_back を多用する時点で何かおかしいと思わないのか?
resize で不具合が出るのをわかっていて resize にこだわる時点で何かおかしいと思わないのか?
ちなみに MFC は RTTI や文字列を自前で作っているが、それがどういう意味かわかる?
0722デフォルトの名無しさん
2010/10/30(土) 13:51:21// ・・・・
set<int>::iterator it = s.begin(), end = s.end();
while(it != end)
{
DoSometing(s, *it);
++it;
}
DoSometingでコンテナの要素が増減する可能性がある場合ってイテレーターは無効になりますか?
0723デフォルトの名無しさん
2010/10/30(土) 13:57:450724デフォルトの名無しさん
2010/10/30(土) 14:56:48itがさしている要素が削除されるとitが無効になるよ。
0725デフォルトの名無しさん
2010/10/30(土) 15:08:37/ \ /\ キリッ
. / (ー) (ー)\
/ ⌒(__人__)⌒ \ <HWND なんか典型的にリストの出番だと思うし
| |r┬-| | それ以前に EnumWindows だろ
\ `ー'´ /
____
/ \ /\ キリッ
. +/ (●) (●)\
/ ⌒(__人__)⌒ \+
| | クスクス>
\ /
____
<クスクス / \ /\ キリッ
. / (●) (●)\
/ ⌒(__人__)⌒ \ +
| |
+ \ /
0726デフォルトの名無しさん
2010/10/30(土) 15:15:110727デフォルトの名無しさん
2010/10/30(土) 15:18:310728デフォルトの名無しさん
2010/10/30(土) 15:21:590729デフォルトの名無しさん
2010/10/30(土) 15:24:33ダメプログラマーになりたいのなら別だがな
0730デフォルトの名無しさん
2010/10/30(土) 15:24:450731デフォルトの名無しさん
2010/10/30(土) 15:25:290732デフォルトの名無しさん
2010/10/30(土) 15:27:06ダメプログラマーになりたいのなら別だがな
0733デフォルトの名無しさん
2010/10/30(土) 15:28:450734デフォルトの名無しさん
2010/10/30(土) 15:33:390735デフォルトの名無しさん
2010/10/30(土) 15:35:380736デフォルトの名無しさん
2010/10/30(土) 15:37:310737デフォルトの名無しさん
2010/10/30(土) 15:42:00そういえばこれのコールバックをコルーチンでiterateする面白い実装をどっかで見たな
0738デフォルトの名無しさん
2010/10/30(土) 15:44:21空笑がみられる病人がいるようだが
許したければ許せばいいだろ自分で
0739デフォルトの名無しさん
2010/10/30(土) 15:54:400740デフォルトの名無しさん
2010/10/30(土) 15:56:22自分に言ってるのか
0741デフォルトの名無しさん
2010/10/30(土) 16:02:26いや、素直な感想を言ってるだけ
0742デフォルトの名無しさん
2010/10/30(土) 16:04:310743デフォルトの名無しさん
2010/10/30(土) 16:15:390744デフォルトの名無しさん
2010/10/30(土) 16:18:57意味のない一言煽り多いよな。それしかできなそうって感じもするけど。
0745デフォルトの名無しさん
2010/10/30(土) 16:43:140746デフォルトの名無しさん
2010/10/30(土) 17:08:210747デフォルトの名無しさん
2010/10/30(土) 17:12:29vectorでは禁じ手
というかメンバ関数がなかったんじゃないか?
0748デフォルトの名無しさん
2010/10/30(土) 17:17:100749デフォルトの名無しさん
2010/10/30(土) 17:18:12というかメンバ関数がなかったんじゃないか?(キリッ
0750デフォルトの名無しさん
2010/10/30(土) 17:22:15許してやれよw
0751デフォルトの名無しさん
2010/10/30(土) 17:26:10vectorの速度的な話で大規模な配列を取り扱う場合
遅い順に
reserveされてない領域へのpush_back
reserveされてる領域へのpush_back
resize等で既に確保されてる領域への代入
vectorを使わない静的配列への代入
って感じであってる?
push_backが遅いのは仕様だよね?
0752デフォルトの名無しさん
2010/10/30(土) 17:31:31vectorを使わない静的配列への代入
これは同じじゃないかな
■ このスレッドは過去ログ倉庫に格納されています