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

C++相談室 part91

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

前スレ
C++相談室 part90
http://hibari.2ch.net/test/read.cgi/tech/1310885439/

このスレもよろしくね。
http://hibari.2ch.net/test/read.cgi/tech/1312621728/

ついでに壁紙にしてね。
http://www.research.att.com/~bs/Bjarne.jpg
0153デフォルトの名無しさん2011/09/24(土) 23:45:50.29
>>149
場合によりけりかなぁ
例えばprintfはエラーを返すけどその中のどこでエラーが起きたか……なんて気にしないでしょ。標準ライブラリでなくてもPOSIXやWin32でも。

どこで起きたかって情報を完全に不要にするのは難しいしそれが必要になることもあるけど、その情報が頻繁に必要になるのは関数が持つエラー通知のインターフェースの作りがよくないんだと思うよ
これはエラー処理にC++の例外を使用するかは関係ない
0154デフォルトの名無しさん2011/09/25(日) 00:02:00.17
>>149
どこで起きたかの情報を保持する例外投げればいいんじゃない?あなたはあほなの?
0155デフォルトの名無しさん2011/09/25(日) 00:12:43.34
本当定期的に例外が使えない奴が沸くよな
組み込みやゲームとか処理がタイトなものならともかく、
普通使うだろ
0156デフォルトの名無しさん2011/09/25(日) 00:25:38.82
例外使ったほうが速度も出るってレポートどっかにあったよね
0157デフォルトの名無しさん2011/09/25(日) 00:28:49.56
>>152
主張は理解できるが
GCが便利かといわれるとちょっとどうかなw

RTTIはテストやデバッグ実行時のときは便利だよね
それ以外ではコンパイラでoffにしてる
エラー発生位置もそうだけどRTTIつかいまくりの設計もどうにかしたほうがいいと思うぞ
便利なのはわかるけど普通不要だから
0158デフォルトの名無しさん2011/09/25(日) 00:30:25.67
仮想関数を正しく使うとRTTIが必要な場面は滅多にないな
if文の羅列とかもうやめたい
0159デフォルトの名無しさん2011/09/25(日) 00:30:29.41
>>144
サイズが増える
0160デフォルトの名無しさん2011/09/25(日) 00:51:58.21
>>159
組み込みの現場ぐらいでしか問題にならんだろ
0161デフォルトの名無しさん2011/09/25(日) 00:55:55.89
>>158
dynamic_castってRTTI使ってたっけ?
仮想関数テーブルで判定してるだけじゃない?
0162デフォルトの名無しさん2011/09/25(日) 01:00:48.71
>>161
使ってる
0163デフォルトの名無しさん2011/09/25(日) 05:28:10.30
dynamic_castはクロスキャストもいけるからな
結構複雑
0164デフォルトの名無しさん2011/09/25(日) 08:33:42.66
class IItem {};
class IDrinkable {};
class IEquipment : public IItem {};
class Weapon : public IEquipment {};
class Armor : public IEquipment {};
class Potion : public IItem, public IDrinkable {};

std::list<shared_ptr<IItem>> items;

コンテナにつっ込まれた要素の、元の型を知りたい時に、IItem クラスは何を用意することがベストだろうか

1. 何も用意しない。dynamic_cast を使用する

2. virtual ItemType GetType() = 0
 enum ItemType {
  ItemType_Weapon, // Weapon クラスはこれを返す。
  ItemType_Armor, // Armor クラスはこれを返す。
  ...
 }

3. virtual Weapon * CastToWeapon() { return NULL; }
 Weapon クラスはオーバーライドして、this を返す。
 他の派生したクラスへキャストする関数も用意する。

4. その他
0165デフォルトの名無しさん2011/09/25(日) 09:17:58.62
型の判断が必要な処理は全部仮想関数にする。
そういう風に基底クラスのインタフェースを定義する。
0166デフォルトの名無しさん2011/09/25(日) 09:46:25.09
仮想関数で完結するのがベストだな
じゃないと何の為に派生してるのやら分からん

ただ、AにBの派生クラスを登録して、
Aの派生クラスからBの派生クラスを使う、
というような場合にはdynamic_castもやむを得ない場合もある
0167デフォルトの名無しさん2011/09/25(日) 13:09:59.73
コンパイラスイッチ一発でgc走るようにならんかな
メモリリーク周りのバグだけ残して、期限までに納品とかできるのにな
バックログは後々で修正してさ
0168デフォルトの名無しさん2011/09/25(日) 15:59:41.98
今どきCならともかくC++でメモリリークって起きにくくね
0169デフォルトの名無しさん2011/09/25(日) 16:08:32.66
言語に関係なく解放しなければメモリリークする
0170デフォルトの名無しさん2011/09/25(日) 18:53:08.88
デストラクタのあるC++でメモリリーク
させる奴は殺害もの
0171デフォルトの名無しさん2011/09/25(日) 19:02:43.66
>>164
なんのために抽象化したリストに突っ込むかによるだろ。
ダウンキャスト的な動作が必要なら、少々とこばっても最初から
元の型を保持したリストを別途用意しとくほうがマシ。
そもそも抽象化したリストに投入する事は、元の型を捨てるという意味だから。

std::list<shared_ptr<Weapon>> weapons;
std::list<shared_ptr<Armor>> armors;
std::list<shared_ptr<IItem>> items;

Weapon weapon;
weapons.push_back(&weapon);
items.push_back(&weapon);
0172デフォルトの名無しさん2011/09/25(日) 21:20:11.60
標準のファイルでcloseに失敗したとしてそれを復旧する方法ってあるの?
無視してそのままアプリ実行したらまずいのかな
0173デフォルトの名無しさん2011/09/25(日) 21:27:11.82
書き込み完了を確実にしたいならflush();
flush()で失敗したら、書き出し先ドライブを変えるとかユーザーにリカバリーを選択させる。
closeで失敗したら、失敗したよってユーザーに通知することぐらいしかできないだろ。
あとは、ダンプを作成してどっかに吐き出しとくことぐらいか。
0174デフォルトの名無しさん2011/09/25(日) 21:30:15.27
>>170
そうはいってもメモリ管理はミスる時にはミスります。malloc()/free() となんらかわりません。
0175デフォルトの名無しさん2011/09/25(日) 21:31:07.40
なるほど
フラッシュで失敗したばあいはいくらでも復旧可能
フラッシュで成功したばあいは直後のクローズで失敗しても特に実害は無いのでご自由に
というかんじか
フラッシュの使い道初めて知ったよとんくす
0176デフォルトの名無しさん2011/09/25(日) 21:32:57.13
コンストラクターでメモリ開放してなかったりな。
そもそもコンストラクターでオブジェクトの作成なんてする必要があるか疑問だが。
配列を確保するならまだしもね。
0177デフォルトの名無しさん2011/09/25(日) 22:00:40.25
>>176
何が言いたいのかさっぱりわからない。
コンストラクタでオブジェクト作成しなかったら何するの?って感じなんだけど。
0178デフォルトの名無しさん2011/09/25(日) 22:06:43.41
オブジェクトの作成というかnewか。
基本的にはメンバー変数に実体を置くか、
外部のオブジェクトを参照するだけで十分な筈。
メモリー操作が必要となるのは、配列かAPIのリソースぐらいじゃん。
0179デフォルトの名無しさん2011/09/25(日) 22:09:55.79
一応close()が失敗しても回復処理とる事もできなくは無いけどな。
新たに別のファイルを開き直して、もう一回出力とか。
0180デフォルトの名無しさん2011/09/25(日) 23:02:56.12
>>178
お前がそう思うんならそうなんだろう、お前ん中ではな(AA略
0181デフォルトの名無しさん2011/09/25(日) 23:10:29.50
>>176
もしかして誤字ではなく本気で open と言っているのか?
0182デフォルトの名無しさん2011/09/25(日) 23:12:39.10
他にどんな用途でオブジェクトをnewするんだよ。
まさか、クラスのメンバーにfstreamのポインター置いて、
クラス内で new と delete を繰り返してるとか?
それともfunctionクラスみたいに型をカプセル化する
オブジェクトを内包しててnewで生成してるとか?
前者は作りを見直すべきだし、後者は滅多に
つくるようなもんじゃないよな。
0183デフォルトの名無しさん2011/09/25(日) 23:13:42.92
>>181
誤爆か?
0184デフォルトの名無しさん2011/09/25(日) 23:19:33.79
ポインタにNULLを代入して何回でもdeleteしてやる
0185デフォルトの名無しさん2011/09/25(日) 23:29:25.53
>>176 はたぶん
「RAII の徹底が不十分な場合、コンストラクタの途中で例外が出てメモリリークする
 ことがある」
ということを言いたかったんだと思うんだけど、合ってるかな?
0186デフォルトの名無しさん2011/09/25(日) 23:37:28.34
コンストラクターの途中で例外でメモリーリークはその通り。
例外が発生すればメモリーリークになるわけじゃないけど、
ちゃんと例外発生時の例外処理を書いてないとメモリーリークになる。

RAIIはどうでもいいけど。いくら例外処理で対処できるとはいえ、
NULL初期化とかが必要になるコンストラクターのメモリ操作自体は減らすべき。
0187デフォルトの名無しさん2011/09/25(日) 23:38:19.03
pimplとか
0188デフォルトの名無しさん2011/09/25(日) 23:43:33.52
要するにこう書くのがミスしやすくて問題なんだろ

class Type
{
        Example *a,*b,*c;
public:
        Type():a(0),b(0),c(0)
        try
        {
             a = new Example();
             b = new Example();
             c = new Example();
        }
        catch(...)
        {
             delete a;
             delete b;
             delete c;
        }
};
0189デフォルトの名無しさん2011/09/25(日) 23:57:53.46
なんのためにスマポがあると思ってん
0190デフォルトの名無しさん2011/09/25(日) 23:57:56.14
ユニポでおk
0191デフォルトの名無しさん2011/09/25(日) 23:58:15.75
それって「素直にスマートポインタ使っとけ」で結論でてると思ってたんだけど違うの?
0192デフォルトの名無しさん2011/09/26(月) 00:05:40.59
>>186
なんでその文脈でRAIIを選択肢から外すんだよw
0193デフォルトの名無しさん2011/09/26(月) 00:07:47.94
例外とRAIIを否定する奴は大抵の場合アホ
0194デフォルトの名無しさん2011/09/26(月) 00:08:00.12
>>188
その catch の中の a,b,c へのアクセスはすべて未定義動作。ミスとか関係ない。
0195デフォルトの名無しさん2011/09/26(月) 00:10:11.32
もともとメンバーに実体で割り当てりゃいいものをいちいちスマポで割り当てる理由が解からん。
0196デフォルトの名無しさん2011/09/26(月) 00:13:14.36
>>194
なんで未定義になるんだ?
0197デフォルトの名無しさん2011/09/26(月) 00:13:43.22
>>195
実体で割り当てたんじゃ要求を満たせないときに new するに決まってんだろ。
メンバの寿命とクラスの寿命がずれてるとか、途中で具象クラスを入れ替えるとか、
考えれば出てきそうなもんだ。
0198デフォルトの名無しさん2011/09/26(月) 00:15:34.48
>>194
え?
0199デフォルトの名無しさん2011/09/26(月) 00:16:00.87
>>196
http://blogs.wankuma.com/episteme/archive/2011/02/20/197105.aspx#197169
15.3 p10 でそう決められているから、らしい。

そんなのコンパイルエラーにしろよとは思う。
0200デフォルトの名無しさん2011/09/26(月) 00:17:19.68
まともにやってるヤツは構わんけど、よくよく考えれば無意味にnewした
メンバー割り当てるヤツがいるから書いたんだよ。
pimpとかは大事だけど、単にリソース開閉のためだけにメモリ操作するなんて無駄じゃん。
0201デフォルトの名無しさん2011/09/26(月) 00:20:37.49
>>199
そこ見ても解るけど問題起きるのは規格に準拠してないコンパイラだけでしょ。
0202デフォルトの名無しさん2011/09/26(月) 00:21:09.41
>>199
ああ >>188 よく見たら function try block になってる(?)のか。
コンストラクタ本体の中で try ... catch するぶんには問題ないよね。
0203デフォルトの名無しさん2011/09/26(月) 00:23:20.69
>>200
そこから「コンストラクタでnew」まで攻撃対象を辺に拡大するから話がおかしくなってる。
ふつうにその無駄を叩けよ。
0204デフォルトの名無しさん2011/09/26(月) 00:27:23.90
すまん。
0205デフォルトの名無しさん2011/09/26(月) 00:28:21.20
>>202
そうだけど、188が function try block のつもりじゃないとしたら、 throw; が抜けてる。
0206デフォルトの名無しさん2011/09/26(月) 00:29:13.71
>>199
これは : がないからfunction-try-blockじゃなくて普通にコンストラクタ内部のtryブロックだろ
{}を書き忘れただけじゃねーかな
0207デフォルトの名無しさん2011/09/26(月) 00:29:31.45
>>201
どこにそんなこと書いてあるの?
0208デフォルトの名無しさん2011/09/26(月) 07:06:32.24
delete 0;は常に何もしないことが保証されてなかったか?
0209デフォルトの名無しさん2011/09/26(月) 07:28:53.09
親クラスで例外が出た場合、
メンバー関数が初期化された状態で、
例外処理に入るとは限らない。
的な事じゃ無いんだろうか。
0210デフォルトの名無しさん2011/09/26(月) 12:33:45.41
WinRTで>>52が望んでいたものがそのまま出てきたな
0211デフォルトの名無しさん2011/09/26(月) 13:24:29.55
>>208-209
コンストラクタでfunction-try-blockを使ってるなら
function-try-block中で例外が発生した時点で構築済みの基底クラスやメンバ変数は破棄されて無効なオブジェクトになるので
その後のcatch節の中ではアクセスしてはいけない、ってこと。
ttp://codepad.org/6zad5CVy
0212デフォルトの名無しさん2011/09/26(月) 14:12:37.12
もっとも>>188はfunction-try-blockではないようなので>>211とは関係ないんだけど
0213デフォルトの名無しさん2011/09/26(月) 15:14:06.62
もうみなさんはlambdaをガンガン使ってコード書いてるの?
0214デフォルトの名無しさん2011/09/26(月) 21:18:22.73
>>211
引数はどうなんの?やっぱり未定義かえ?
0215デフォルトの名無しさん2011/09/26(月) 22:15:43.84
発見しちゃったんだけどなんか使い道あるかな?
class a{
operator a(); // これ作れちゃうんだ
};
0216デフォルトの名無しさん2011/09/26(月) 22:30:59.94
mmapで確保したメモリー空間にヒープを構築しようと思う。
プールを渡してやったらファーストフィットやらベストフィットやらを
サクッと構築できるライブラリとかないかな。
0217デフォルトの名無しさん2011/09/27(火) 00:07:08.50
>>214
引数の寿命はfunction-try-blockのハンドラを抜けるまで延長される。だから引数にはアクセスできる。
ttp://codepad.org/0wwV4V4w
0218デフォルトの名無しさん2011/09/27(火) 01:01:19.97
延長されるっていうか、普通に考えておkってことだね。
0219デフォルトの名無しさん2011/09/27(火) 01:02:49.39
char*が引き数ってなんなんだよ…
0220デフォルトの名無しさん2011/09/27(火) 07:13:06.38
>>217
規格上はやっぱりセーフなんだ。良かった。
0221デフォルトの名無しさん2011/09/27(火) 07:36:18.86
>>215
aにキャストしても呼ばれないし、
aの派生クラスbを作ってaに代入やキャストしても呼ばれないし、
operator aを直接呼ばないと呼ばれないっぽ
環境依存かもしれないけど
使い道はなさげ
0222デフォルトの名無しさん2011/09/27(火) 08:19:27.19
C++でググったサイト見てると、C++の例外はgdgdなので使わない方がいいという意見があり、スコット・メイヤー先生の著書ではエラー処理には例外を使えとあるのですが、みなさんは例外使ってます?
0223デフォルトの名無しさん2011/09/27(火) 09:24:53.29
うん。
0224デフォルトの名無しさん2011/09/27(火) 09:48:59.65
>>222
> 使わない方がいいという意見
どこ見たの?
0225デフォルトの名無しさん2011/09/27(火) 11:42:28.77
類は群れる
0226デフォルトの名無しさん2011/09/27(火) 12:17:30.45
ラムダは割と使う
便利だし
0227デフォルトの名無しさん2011/09/27(火) 13:01:40.64
ラムダをループ毎に一回一回生成すると無駄にコストが掛かりますか?
0228デフォルトの名無しさん2011/09/27(火) 13:06:09.17
>244 本人じゃないが
試しにググって見たら、「C++ 例外 使わない」 で12,400件でたぞ。意外と多い。w
おれは、半々だな、使う部分と使わない部分がある。
0229デフォルトの名無しさん2011/09/27(火) 13:20:16.77
>>216
構造としてのヒープじゃなくて領域としてのヒープか?
ファーストフィットだけならsimple segregated storageってのがあるからそれを実装したライブラリで領域を外から与えられるやつ探せばいいと思うよ
一応boostにもあるけど領域を外から与えられるかどうかはわからん


データ構造のほうならstd::make_heapで
0230デフォルトの名無しさん2011/09/27(火) 18:50:38.32
Google先生は例外を使わないと規約で決めてるっぽいけど
それを達成するには例外を利用する標準ライブラリを
例外の出ないタイプのものに置き換える必要があるから
正直そこまでやるのもどうかと思う
0231デフォルトの名無しさん2011/09/27(火) 19:05:00.98
徹底したくなるほど過去の資産の価値がすごいんだろう
0232デフォルトの名無しさん2011/09/27(火) 19:34:48.29
1. 戻り値として true/false か NULL を返せない
2. エラーが発生したときに落ちることを許可しない

1 && 2 であれば、例外を使用する

bool TryGetHoge(Hoge * pOutput) // Nothrow
const Hoge * GetHogeOrNull() // Nothrow
const Hoge & GetHogeOrThrow() // Hoge が取得できないばあいはスロー
const Hoge & GetHogeOrDie() // Hoge が取得できない → 死
0233デフォルトの名無しさん2011/09/27(火) 19:42:16.44
>>227
無駄にコストが掛かる、ってのはどういうこと?
C++は原則的に要求された機能を実現するのに必要なだけのコストしか掛けない。
プログラマが実際には使わない機能を含めて要求していたならその分無駄にコストが掛かるといえるけど
それは具体的な状況次第。
0234デフォルトの名無しさん2011/09/27(火) 19:58:52.24
キャプチャ次第じゃないの
関数の本体自体を生成してるわけじゃないんだし
0235デフォルトの名無しさん2011/09/27(火) 20:02:51.22
キャプチャしないとただの関数に最適化される
0236デフォルトの名無しさん2011/09/27(火) 20:05:16.85
[&]ならどうせスタックフレーム渡してるだけだろうから
大した事ないよね
0237デフォルトの名無しさん2011/09/27(火) 20:15:39.34
>>232
例外が発生したところで、根っこでキャッチする限り落ちることはなくね?
それが良いわけでもないけどさ。
逆にエラー無視してたらまずくね?
いずれセグメントエラーでも起こして無断で死ぬでしょ。
0238デフォルトの名無しさん2011/09/27(火) 20:17:09.46
ごめん例外を出さないパターンとはやとちりした。
0239デフォルトの名無しさん2011/09/27(火) 20:21:25.77
int main(void)
{
try { return Main(void); } catch(...) { Message("Fackin Error !!!"); return 1 ; }
}
0240デフォルトの名無しさん2011/09/27(火) 21:34:14.78
あまり酷いエラーはそのまま死んだ方がいいってこともあるよね
0241デフォルトの名無しさん2011/09/27(火) 21:40:07.15
>>229
simple segregated storageかいいね。ありがとう。
0242デフォルトの名無しさん2011/09/28(水) 19:33:43.19
コンストラクタのメンバ関数ポインタって取得できますか?
0243デフォルトの名無しさん2011/09/28(水) 19:36:12.71
とれませんよそんなの
0244デフォルトの名無しさん2011/09/28(水) 19:57:25.79
ありがとう。そして素早い回答に感動した
0245デフォルトの名無しさん2011/09/28(水) 20:08:28.29
>>225

チムポも蒸れる
0246デフォルトの名無しさん2011/09/28(水) 20:18:05.22
コンストラクタのメンバ関数ポインタを取得する裏技はないものかねえ
0247デフォルトの名無しさん2011/09/28(水) 20:26:59.49
そんなものいらん
0248デフォルトの名無しさん2011/09/28(水) 20:27:37.84
コンストラクタはメンバ関数じゃないから
0249デフォルトの名無しさん2011/09/28(水) 20:32:50.41
>>246
初期化のコンスラクタを呼びたいだけじゃないのか?
それならるぞ。
0250デフォルトの名無しさん2011/09/28(水) 20:42:54.84
可変テンプレートを自作すりゃ見せかけは出来なくはないがね。

Type (*constractor)(int) = &Constractor<Type(int)>;
Type object = constractor(10);
0251デフォルトの名無しさん2011/09/28(水) 20:45:30.98
標準のnewやmallocはスレッドセーフですか?
0252デフォルトの名無しさん2011/09/28(水) 20:52:11.40
>>251
マルチすると一部の人はヘソを曲げて答えてくれなくなっちゃうぞ
■ このスレッドは過去ログ倉庫に格納されています