トップページ⇒tech
1001コメント275KB

C++相談室 part85

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん2010/10/09(土) 20:22:35
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレに
お願いします。

前スレ
C++相談室 part84
http://hibari.2ch.net/test/read.cgi/tech/1284736187/
0685デフォルトの名無しさん2010/10/30(土) 00:55:08
>>683
いやどういうときに使うものなのか見当がつかないだけだよ
06866752010/10/30(土) 00:55:56
>>682
ptr_vector!
これを忘れていました。是非使ってみようと思います。こちらもありがとうございました。
0687デフォルトの名無しさん2010/10/30(土) 00:56:29
>>684
FILE*だもんな・・・
0688デフォルトの名無しさん2010/10/30(土) 00:59:21
>>686
ゴメン
やっぱ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:14
>>677
vector を参照かポインタで扱っても、もともとの問題である vector に CFile を入れる段階の
問題が何も解決しない。

配列のコピーが行われたところで十分な空間・計算リソースがあれば問題にならないんで、
誰もが通る問題とも思えない。
0691デフォルトの名無しさん2010/10/30(土) 01:36:14
>>688
何も問題ないように見えるが、何がダメだって言うの?
06926852010/10/30(土) 01:43:44
うーん考えたけどまるで思いつかないよ。

ちょくちょく出し入れしないとsharedする意味がないし、vectorにそれが向いてるとは思えない。
コンテナに入れる用途だとselectポーリングするとか、サーバー側のソケット/パイプ管理や
クライアント側のコネクションプールのようなものとかだけど、ポーリング以外では切断する役割
よりも使用未使用管理になると思うし、ポーリングを使うような状況でvectorは俺なら使わない。
そもそも面倒なのでポーリングしないで一個ずつスレッド使っちゃうし。

誰かvector<shared_ptr<CFile>>の利用用途を教えてくれー。
0693デフォルトの名無しさん2010/10/30(土) 01:50:02
>>691
いやいやだからpush_backしていくうちにメモリの再配置が起きてその時に
勝手にデストラクタが呼ばれてファイルストリームがクローズしちゃうじゃん

それを嫌がってるんでしょ?

自分でデストラクタを呼び出すならstd::vector<CFile*>でも何の問題もないような気がするんだけど
0694デフォルトの名無しさん2010/10/30(土) 01:51:56
>>692
shared_ptr が使われてるのは、単に C++2003 にはムーブや unique_ptr が無いからでしょ。
出し入れがしたいわけじゃないと思うよ。

「〜ような状況でvectorは俺なら使わない」と言うけど、それこそ理由が不明。

単に CFile の配列が欲しくて、実行時にしか要素数が決まらないってだけで十分でしょ。
0695デフォルトの名無しさん2010/10/30(土) 01:56:02
>>694
素人考えだとならlistではダメなの?って思うのですよ
利用用途が思いつかないからいいのかどうか見当もつかないんですけど
0696デフォルトの名無しさん2010/10/30(土) 01:56:40
>>695
単にoperator[]を使いたいんだと思うよ
06976752010/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
>>693
何のための ptr_vector だよ。

ptr_vector なら再確保が発生してもポインタのコピーだけすればよくて、
オブジェクト本体のコピーが要らない。したがってデストラクタが呼ばれたりもしない。

自分でデストラクタを呼び出すなんて、論外だね。
0699デフォルトの名無しさん2010/10/30(土) 02:06:14
0x の移動に対応したコンパイラなら vector<fstream> で良さそうだが
0700デフォルトの名無しさん2010/10/30(土) 02:07:29
あーそうですね
0701デフォルトの名無しさん2010/10/30(土) 02:10:21
>>698
それはわかってる
でも今回のように勝手にデストラクタが呼ばれては困るファイルストリームインスタンスへの
ポインタを保持する場合は駄目でしょって
0702デフォルトの名無しさん2010/10/30(土) 02:12:46
>>701 >>691
0703デフォルトの名無しさん2010/10/30(土) 02:16:31
>>696
なるほどまづは前提として受け入れろと
>>697
なるほど。リソースハンドル全般の話で使いまわしとは関係がない話なのですね。
オブジェクトとリソースの生成/消滅は原則連動してて、未参照状態で自動的に
消滅さ&コンテナはとにかくvectorがいいと。

0xはまだまだ知らないことだらけだけど、なんか面白そうですね。
0704デフォルトの名無しさん2010/10/30(土) 02:21:19
>>702
>>689にこれじゃ駄目でしょうって例をわざわざ貼り付けたんだけど理解できないかな?
0705デフォルトの名無しさん2010/10/30(土) 02:31:12
>>704
テンポラリに swap() で内容を移してるんだから、そのテンポラリの消滅で
デストラクタが走って当然。これを「勝手に」とか言ってるのがどういうことなのか
理解できない。
0706デフォルトの名無しさん2010/10/30(土) 02:37:08
>>705
いやだから・・・std::vectorでpush_backして行くとそのうち連続したエリアが足りなく
なってメモリの再配置が起きるでしょうって

boost::ptr_vectorも事情は同じですよって言う意味で書いたんだけど分かってもらえないかな?
0707デフォルトの名無しさん2010/10/30(土) 02:46:41
>>706 >>698
0708デフォルトの名無しさん2010/10/30(土) 02:48:16
>>707
外行って頭に水ぶっかけて来い
0709デフォルトの名無しさん2010/10/30(土) 02:50:18
再配置結果
http://ideone.com/C0UYF

capacity() == size()はcapacity()が満たされた場合であり、再配置が起こる
明示的にresize()も呼び出してみた
再配置が起こってもデストラクタは起動しない
スコープアウトしてはじめてデストラクタが起動する
0710デフォルトの名無しさん2010/10/30(土) 02:52:21
http://codepad.org/3PHDRO8v
おっと。似たようなことしてる人が・・・
0711デフォルトの名無しさん2010/10/30(土) 02:53:38
アホをいち早く切り捨てた >>683 カコイイ
0712デフォルトの名無しさん2010/10/30(土) 03:00:01
今頃頭に水かぶりにいったのかな?
0713デフォルトの名無しさん2010/10/30(土) 03:04:27
うわぁ・・・
0714デフォルトの名無しさん2010/10/30(土) 03:05:56
夜中に元気だなお前ら
0715デフォルトの名無しさん2010/10/30(土) 03:18:20
金曜日の夜だけは元気なんだよ
0716デフォルトの名無しさん2010/10/30(土) 03:19:55
・メモリの再配置が起きてもデストラクタは起動しない
・但しイテレータは無効になる

か
0717デフォルトの名無しさん2010/10/30(土) 03:28:21
>>716
あくまでポインタを保持している場合の話な

>>709のコード貼っといて言うのもアレだが
オレはコンテナにファイル管理クラスを突っ込んだりしないけどな
入れるとしたらファイル名とかリソースバッファか
ファイル処理なんてエラーが出やすいし、アクセスは単純化してわかりやすい方がいい
こんな論争現場でしたくないだろw
0718デフォルトの名無しさん2010/10/30(土) 03:31:42
つまり今回のようなケースではboost::ptr_vectorで問題はないわけだ
0719デフォルトの名無しさん2010/10/30(土) 09:58:53
>>697
CFileってコピー可なのか?普通はコピー不可にするべきだろう。MFCって一体?

コピー不可でも、C++0xならムーブ可にしておけばvectorに入るだろうし、突然閉じたりしないしな
0720デフォルトの名無しさん2010/10/30(土) 10:39:12
MFCの話してるわけじゃないだろ
それにMFCのCFileはコピー不可だよ
0721デフォルトの名無しさん2010/10/30(土) 13:15:33
>>697
list じゃだめなん?
HWND なんか典型的にリストの出番だと思うし
それ以前に EnumWindows だろ

vector に push_back を多用する時点で何かおかしいと思わないのか?
resize で不具合が出るのをわかっていて resize にこだわる時点で何かおかしいと思わないのか?

ちなみに MFC は RTTI や文字列を自前で作っているが、それがどういう意味かわかる?
0722デフォルトの名無しさん2010/10/30(土) 13:51:21
set<int> s; // あるいはlistやvector

// ・・・・

set<int>::iterator it = s.begin(), end = s.end();

while(it != end)
{
DoSometing(s, *it);
++it;
}

DoSometingでコンテナの要素が増減する可能性がある場合ってイテレーターは無効になりますか?
0723デフォルトの名無しさん2010/10/30(土) 13:57:45
うん
0724デフォルトの名無しさん2010/10/30(土) 14:56:48
>>722
itがさしている要素が削除されるとitが無効になるよ。
0725デフォルトの名無しさん2010/10/30(土) 15:08:37
        ____
       / \  /\ キリッ
.     / (ー)  (ー)\
    /   ⌒(__人__)⌒ \   <HWND なんか典型的にリストの出番だと思うし
    |      |r┬-|    |        それ以前に EnumWindows だろ
     \     `ー'´   /

        ____
       / \  /\ キリッ
.    +/ (●)  (●)\
    /   ⌒(__人__)⌒ \+   
    |              |  クスクス>
     \            /

        ____
<クスクス   / \  /\ キリッ
.     / (●)  (●)\
    /   ⌒(__人__)⌒ \ +  
    |              |        
   + \            /
0726デフォルトの名無しさん2010/10/30(土) 15:15:11
許してやれよ
0727デフォルトの名無しさん2010/10/30(土) 15:18:31
vector に push_back を多用するのは何がおかしいの?
0728デフォルトの名無しさん2010/10/30(土) 15:21:59
効率がおかしい
0729デフォルトの名無しさん2010/10/30(土) 15:24:33
そういう効率だけを考えていてもダメ
ダメプログラマーになりたいのなら別だがな
0730デフォルトの名無しさん2010/10/30(土) 15:24:45
reserve()しとけば問題ないんじゃないの
0731デフォルトの名無しさん2010/10/30(土) 15:25:29
規格どおりならおかしくもなんともない。
0732デフォルトの名無しさん2010/10/30(土) 15:27:06
そういう規格だけを考えていてもダメ
ダメプログラマーになりたいのなら別だがな
0733デフォルトの名無しさん2010/10/30(土) 15:28:45
vectorでreserveしてpush_backするぐらいならdeque使っておけて事?
0734デフォルトの名無しさん2010/10/30(土) 15:33:39
dequeじゃ同じことなんじゃ…
0735デフォルトの名無しさん2010/10/30(土) 15:35:38
EnumWindowsはどっから出てきたんだ
0736デフォルトの名無しさん2010/10/30(土) 15:37:31
許してやれよ
0737デフォルトの名無しさん2010/10/30(土) 15:42:00
確かにEnumWindowsは出てくるべきではないと思うね
そういえばこれのコールバックをコルーチンでiterateする面白い実装をどっかで見たな
0738デフォルトの名無しさん2010/10/30(土) 15:44:21
許すって何を?
空笑がみられる病人がいるようだが
許したければ許せばいいだろ自分で
0739デフォルトの名無しさん2010/10/30(土) 15:54:40
意味のない一言煽り多いよな。それしかできなそうって感じもするけど。
0740デフォルトの名無しさん2010/10/30(土) 15:56:22
>>739
自分に言ってるのか
0741デフォルトの名無しさん2010/10/30(土) 16:02:26
>>740
いや、素直な感想を言ってるだけ
0742デフォルトの名無しさん2010/10/30(土) 16:04:31
言ってる自分が気づいてないんだな。
0743デフォルトの名無しさん2010/10/30(土) 16:15:39
図星だったのか
0744デフォルトの名無しさん2010/10/30(土) 16:18:57
>>743
意味のない一言煽り多いよな。それしかできなそうって感じもするけど。
0745デフォルトの名無しさん2010/10/30(土) 16:43:14
君たち、 C++ の話をしろ
0746デフォルトの名無しさん2010/10/30(土) 17:08:21
push_back を多用するな。 push_front を使うんだ(キリッ
0747デフォルトの名無しさん2010/10/30(土) 17:12:29
>>746
vectorでは禁じ手
というかメンバ関数がなかったんじゃないか?
0748デフォルトの名無しさん2010/10/30(土) 17:17:10
つまりInsertを使えってことだな
0749デフォルトの名無しさん2010/10/30(土) 17:18:12
vectorでは禁じ手(キリッ
というかメンバ関数がなかったんじゃないか?(キリッ
0750デフォルトの名無しさん2010/10/30(土) 17:22:15
>>747
許してやれよw
0751デフォルトの名無しさん2010/10/30(土) 17:26:10
ついでに初歩的な質問していい?
vectorの速度的な話で大規模な配列を取り扱う場合

遅い順に

reserveされてない領域へのpush_back
reserveされてる領域へのpush_back
resize等で既に確保されてる領域への代入
vectorを使わない静的配列への代入

って感じであってる?
push_backが遅いのは仕様だよね?
0752デフォルトの名無しさん2010/10/30(土) 17:31:31
resize等で既に確保されてる領域への代入
vectorを使わない静的配列への代入

これは同じじゃないかな
0753デフォルトの名無しさん2010/10/30(土) 17:42:17
>>752
そうなのかな?

適当に10個ほどの変数をもつ構造体で
静的の方は各変数ごとに代入
vectorの方は各変数ごとに代入とoperator=による代入両方で計測してみたんだけど
どうも静的のほうが微妙に速いんだ
誤差の範囲といえばそうなんだが計測に仕方が悪いのかな
0754デフォルトの名無しさん2010/10/30(土) 17:52:21
そりゃvectorのoperator[]がインライン関数に展開される保証はどこにもないからな
例えされたとしても複雑なアドレス計算が絡みそうなので単純な配列に比べたら
可哀想だ

でもEfficient C++を読むと分かると思うけど、vectorは本当に速いよ
0755デフォルトの名無しさん2010/10/30(土) 18:10:25
本当にvector自体の実装に足を引っ張られている人なんてまずいない。
0756デフォルトの名無しさん2010/10/30(土) 18:15:25
vector<Hoge> v;

vector<Hoge, Ator> va;

v = va;
swap(v, va);
//etc.

これサポートされてないんだけどなんかイカす回避手段はありますか?
0757デフォルトの名無しさん2010/10/30(土) 18:23:16
アロケータが違うなら一つ一つ要素を交換するしかないだろJK
0758デフォルトの名無しさん2010/10/30(土) 19:21:20
>>751
> reserveされてる領域へのpush_back
> resize等で既に確保されてる領域への代入

これは前者がコピーコンストラクタ、後者が代入演算子を使うことになるから、
既存の要素の取り扱いを考慮する分で、一般的には後者のほうが遅いだろう。

コピーをユーザー定義したクラスの実装によっては逆転することもあるだろうけど。
0759デフォルトの名無しさん2010/10/30(土) 19:54:16
ワテは関西人だけど、pop_frontを使うときはdequeでそれ以外はvectorって決め打ちしてますさかい「
0760デフォルトの名無しさん2010/10/30(土) 23:07:03
shared_ptrでdeleteされるタイミングを教えてください
0761デフォルトの名無しさん2010/10/30(土) 23:17:31
>>760
shared_ptrが指しているインスタンスが一つも指されなくなったら
つまりこれはお互いに指し合うと永久にdeleteされなくなるので
一個だけweak_ptrを挟む
0762デフォルトの名無しさん2010/10/30(土) 23:19:27
http://www.ogis-ri.co.jp/otc/hiroba/technical/boost/part1/index.html

ここが良くまとまっている
0763デフォルトの名無しさん2010/10/30(土) 23:33:05
>>759
関東人乙

俺関西人やけど、pop_front使うときはdequeでそれ以外はvectorって決めてるわw
07647602010/10/30(土) 23:35:20
>>761-762
thx

どうやって参照カウントが0になったことをshared_ptrは知るんですか?
0765デフォルトの名無しさん2010/10/30(土) 23:40:33
カウンターを内蔵してるんだよ
07667602010/10/30(土) 23:54:59
>>765
そこら辺少し調べてみるよ
ありがとうよ
0767デフォルトの名無しさん2010/10/31(日) 00:50:46
>>764
> >>761-762
> thx
> どうやって参照カウントが0になったことをshared_ptrは知るんですか?
07687672010/10/31(日) 00:51:51
ただの誤爆
ごめんよ
0769デフォルトの名無しさん2010/10/31(日) 01:06:04
xmlをパースしたいのですが
libxml2とapache xercesって使いやすいですか?
0770デフォルトの名無しさん2010/10/31(日) 11:52:29
初歩的な質問なんですが
http://users.rcn.com/jcoplien/Patterns/C++Idioms/EuroPLoP98.html#PromoteAndAdd
上記のウェブサイトのソースコードでconst参照仮引数に代入しているように
みえるのですが良くわかりません。
ちなみにisA関数の意味もcomplexExemplarの意味もわかりません。
教えてください。
0771デフォルトの名無しさん2010/10/31(日) 15:15:29
>>769
XML自体が使いにくい。どっちでも特に使いにくいとか使いやすいとか思わなかった。
>>770
細かいことは気にするな。コードはかなり適当っぽい。
0772デフォルトの名無しさん2010/10/31(日) 15:25:29
プリプロセッサがマクロを処理する順番はどのように決まっているのでしょうか。
例えば、関数形式のマクロに別のマクロを引数として与えたとき、引数の方が先に処理される
ようなことはないみたいですけど、単に記述順に処理されるんでしょうか。
0773デフォルトの名無しさん2010/10/31(日) 15:42:54
XMLならBoost.PropertyTreeもある。
07747692010/10/31(日) 15:55:46
>>771
やっぱり、どの言語でも使いにくい点は同じなのね

>>773
boostにもxmlパーサーがあるんだ
0775デフォルトの名無しさん2010/10/31(日) 16:05:50
パーサーというやつに限ってコンピュータとかポインタとかいうんだよなwwww
0776デフォルトの名無しさん2010/10/31(日) 16:45:51
心底どうでもいい
0777デフォルトの名無しさん2010/10/31(日) 17:32:08
そういうやつに限って消費税が1パーセントでも上がるとめちゃくちゃ騒ぐんだよなwww
0778デフォルトの名無しさん2010/10/31(日) 17:37:39
std::auto_ptr<Class> c = new Class;
こんな宣言をすることができるらしいのですが、
コンパイラが禁止しているからエラーがでるのですか?

また、この時の型は何になるんですか
0779デフォルトの名無しさん2010/10/31(日) 17:40:57
>>778
auto_ptr はテンポラリからのコピーができないので、その初期化形式(コピー初期化)では
コンパイルエラーになる。

... c(new Class) とすれば(形式を直接初期化にすれば)コンパイルできる。
型は書いたとおりの std::auto_ptr<Class> 。
0780デフォルトの名無しさん2010/10/31(日) 17:56:10
>>778
explicit を学べ
0781デフォルトの名無しさん2010/10/31(日) 17:58:03
>>780 いや、 explicit は関係ないでしょ。
07827782010/10/31(日) 18:08:58
>>780
explicitくらい知っている

>>779
thx
0783デフォルトの名無しさん2010/10/31(日) 18:14:42
>>772
基本的に記述順に処理される
詳しくは
http://www.spinellis.gr/blog/20060626/
このあたりで

>>781
explicitがなければT *からの変換コンストラクタが定義できてしまうのでは?
07847792010/10/31(日) 18:19:39
>>780-782
ごめん。間違ってた。

auto_ptr も auto_ptr_ref 経由でテンポラリから初期化ができる。
>>778 のコードでテンポラリを使った初期化にならないのは
auto_ptr<T>::auto_ptr(T*) に explicit が付いているから。

直接初期化の形にすれば当然 expliciti の制限は受けず、
auto_ptr<T>::auto_ptr(T*) が使用される。
■ このスレッドは過去ログ倉庫に格納されています