1 :
デフォルトの名無しさん :
2008/11/01(土) 21:32:27
2 :
デフォルトの名無しさん :2008/11/01(土) 21:33:19
STLつかうと一気に実行ファイルサイズが なぜ今たてる
4 :
デフォルトの名無しさん :2008/11/02(日) 00:52:16
下のjavaのコードをC++にしようと思ったんですが、コンパイルエラーが出てしまいます。こういうとき、C++ではprotectedの代わりに何を使えばいいんでしょうか?あきらめてpublicなのかなぁ。 [Main.java] abstract class A { protected abstract void foo(); } class B extends A { protected void foo(){System.out.println("foo!");} public void bar(){pa.foo();} public void set(A p){pa = p;} private A pa; } public class Main { public static void main(String[] args) { B b = new B(); b.set(b); b.bar();}} $ javac Main.java; java Main foo! [protected.cpp] #include <iostream> class A { protected://public:とすれば問題無し virtual void foo()=0; }; class B : public A { protected: void foo() {std::cout << "foo!" << std::endl;} public: void bar() {pa->foo();} void set(A* p) {pa = p;} private: A *pa; }; int main() { B b; b.set(&b); b.bar(); return 0;} $ g++ protected.cpp protect.cpp:4: error: ‘virtual void A::foo()’ is protected protect.cpp:10: error: within this context
>4 なんで、A を継承してるのにさらに A を内部に持とうとしてるの?
6 :
デフォルトの名無しさん :2008/11/02(日) 10:46:50
<<5 Strategyみたいなことをしたいんじゃね? <<4 インターフェースなのに公開しないというのが不思議だけど どうしてもfooを呼ばれたくなければAの方をpublicにして、 protected継承すればよいと思う
まだ早いだろw
>>4 それ、Javaでもprotectedだから見えるのではなく、
同一パッケージのデフォルトアクセスのおかげで見えているだけだぞ。
BとAを別のパッケージに置くとJavaでもエラーになる。
ubuntu上で開発しているのですが、自分で作った共有ライブラリを使うときに、 実行ファイルとライブラリを同フォルダに置いても、ライブラリがありませんと言われます。 LD_LIBRARY_PATHにカレントディレクトリをセットすれば動くのですが、毎回セットするのも 面倒で、だからといって/usr/libなどを汚したくもありません。 何か良い方法はないのでしょうか?
/usr/local/lib か或いは全く別のディレクトリを決めて、そこに入れるようにすれば?
>>10 やっぱりそれがいいのかな
自分が作った共有ライブラリを放り込むフォルダ作って、
パスを通しておく方法でいってみます。
フォルダじゃなくてディレクトリと言ってね。
C++の便利な機能って コンストラクタ、デストラクタ、メンバ関数、ポリモフィズム、 以外に何かあります? テンプレートって使いどころが今一不明
必要がないと感じなければ使わない自由があるのがC++
全然答えになってない 流石C++スレ
個人的にはテンプレートなしでのC++はありえない
reallocよりはvectorのresizeのほうが便利だ。 テンプレートで要素の型を指定するから適宜よろしくやってくれる。 qsortよりはsortのほうが便利だ。 比較関数の引数がvoid*でないだけでも随分便利に感じる。 ソート対象と比較対象で要素の型を間違えれば警告やエラーになる。 まあエラーメッセージがわけわかめなのは御愛嬌。
同じインターフェースの中で、 型によって異なる動作をさせたい時に使うのがポリモーフィズムで、 異なる型に同じ動作をさせたい時に使うのがテンプレート。
>>19 同じ動作をさせたい時にテンプレート?
動作が同じなら普通にその動作を書けばいいだけじゃないの?
同じアルゴリズムを適用したい時、かな。
>>20 型が違うので同じ処理には渡せない。
同じ処理をソース上複数書くと保守性に欠ける。
>>21 それは同じ基底クラスから派生させてポリモーフィズムで解決することもできるだろ。
プリプロセッサで…いやなんでもない
>>23 具体的に、何が良いのか言えるかな?
「スマート」とかいうあやふやな価値観でヘッダの依存関係を強制されるのは受け入れがたい。
効率。
そもそも、
>>19 がポリモーフィズムとテンプレートを並べていることに疑問を感じる。
ある種のポリモーフィズムを実現する1つの手段としてテンプレートがあるというのが自分の認識。
ここまで「ジェネリクス」という言葉無し。
ポリモフィズムは、is a だろ。 インタフェースとか継承とか使って、クラスA B Cが同じように見えて、同じように扱える。 使う側はABCの実装なんか気にすること無い。それぞれが勝手によろしくやってくれる。 で、ジェネリクスは template<typename T> G だろ。型 T を引数で渡すんだ。 型による違いは T を使う側、つまり G が面倒見なきゃならんのだな。 クラス X Y Z で G<X> G<Y> G<Z> とか。X, Y Z はお互いの違いなんて気にすること無く同じ機能を使える。 G が勝手によろしくやってくれる。 ところが T は型なんだ。つまり class なんだ。ってことはポリモフィズムが使えるんだ。 T をインタフェースにして、A B C がインタフェースを実装してたら、G は楽になるよな。 わざわざ場合わけする手間が省ける。A B C は同じ手続きを提供しているわけだから。 A B C が自分自身に関する情報を共通の手段で G に提供する。 ジェネリクス G は A B C のポリモフィズムを利用して、 さらに高レベルな手続きや機能を、A B C に付加するんだな。 そんなこんなで STL であり Boostなんだろうな。
静的ポリモーフィズムというのもあってのう・・・
コンパイル時ポリモーフィズムとも言う。 元々は関数のオーバーロードなどを指したけど、異なる型に対するテンプレートの実体化もある意味オーバーロードだからな。
OOPの用語と区別できるように、 Interface -> Concepts Inheritance -> Refinement ってSGIのドキュメントに書いてあった。
error LNK2019: 未解決の外部シンボル "int __cdecl import_features(char *,int,struct feature * *)" (?import_features@@YAHPADHPAPAUfeature@@@Z) が関数 "void __cdecl readfeatures(void)" (?readfeatures@@YAXXZ) で参照されました とかいうエラーがでるんですけど、 どういうことをここではいってるんですか?
未解決な外部シンボルが関数で参照されているということを表しています。 恐らくは、readfeatures()で呼んでいる筈のimport_features()が見つからないのでしょう。
リンカでエラーになるってことは、大抵は宣言はあるんだけど定義がない関数が呼ばれたってこと。 宣言と定義が微妙に食い違ってて別物扱いされてるとかな。
とりあえず前スレ使いきろうな
だからって無理に前スレで このスレにレスしなくても
38 :
デフォルトの名無しさん :2008/11/12(水) 23:41:47
親子関係にあるクラスで、クラスParentがChildを複数持っているとします Parentのコンストラクタ内で複数のChildを生成します。 ここで、ChildからParentの情報を参照したくなったので、 ParentへのポインタをChildに持たせ、コンストラクタでParentへのポインタを渡そう思ったんですが、 Parent::Parent() : child1_(new Child(this)),child2_(new Child(this)) //←これはヤバス?{} デバッガで覗くとあやしげな値が入っていて、どうやら無効なポインタぽいです まだできてないインスタンスのポインタを持ってもしょうがないって事ですかね こういう場合うまいこと子クラスに親の参照を持たせる方法ってないですか 適当にInit()関数とか用意して、そこで全ての子に親への参照を持たせるのが手っ取り早いのですが 子が親への参照を持ってない状態ができてしまうのと、 Parentクラスの利用者に余計な手間を強制してしまうのでイマイチな気がします
コンストラクタでもthisは有効だが、それ以前に相互参照なので気持ち悪い。
俺だったら、親クラスのコンストラクタで子供なんか作らない。 必要になったときに作る。
>>38 Childのコンストラクタで、渡されたParentオブジェクトをアクセスするのはNG
参照を憶えておくに留め、Parentのコンストラクト後にならいくらでもアクセスしてOK
>>39 Parentのスーパークラスに依存しているのかもしれない。
その場合は相互参照ではないね。
本体ではもちろんthisポインタは有効だけど、初期化リスト中でも有効だっけ?
有効でなければ初期化リストでインスタンス変数の初期化ができないだろ。
有効じゃないぞ 値が変更されないだけ
error LNK2001: 外部シンボル ""int __cdecl import_features(char *,int,struct feature * *)" (?import_features@@YAHPADHPAPAUfeature@@@Z)" は未解決です。 MfSift.obj というエラーが出るんですけど、何が原因なんだと思いますか? ヘッダに宣言、別ファイル.cに定義をしています。 他のソリューションでは動いていたんですが、このソリューションにコピペしたら このエラーが出るようになり、困っています。
関数import_featuresの宣言にextern "C"つけろ
.c に定義をしている? もしかしてそれを .cpp から呼び出そうとした?
48 :
デフォルトの名無しさん :2008/11/14(金) 12:56:10
double numer, denom; // ... numer / denom; としたときに,0除算の例外が起きるときは denom == 0.0 が常に true になるときだけでしょうか? それとも denom == 0.0 が false のときでも上記の除算で0除算の例外が生じる可能性はありますか?
普通は例外なんて飛ばずに無限大が返ってくるだけだろ その辺の挙動を何とかしたいならアーキテクチャのマニュアル嫁
偉そうなこと言って使えねー奴ばっかだな。
スルー汁
DLLの扱いについてなんですが、 Aというプログラムのヘッダで、 #include hoge/hoge.dll として、hoge.dllを読み込み、 ProgramA.dllを作成したとします。 そしてこのProgramA.dllを全く別のディレクトリに入れて動かすことを考えているのですが、 この際、 hoge.dllは必要になりますか? また、必要だとしたら、ProguramA.dllのあるディレクトリにhogeを作って、その中にhoge.dllを入れる必要がありますか?
DLLの扱いについてなんですが、 Aというプログラムのヘッダで、 #include hoge/hoge.dll として、hoge.dllを読み込み、 ProgramA.dllを作成したとします。 そしてこのProgramA.dllを全く別のディレクトリに入れて動かすことを考えているのですが、 この際、 hoge.dllは必要になりますか? また、必要だとしたら、ProguramA.dllのあるディレクトリにhogeを作って、その中にhoge.dllを入れる必要がありますか?
> #include hoge/hoge.dll C/C++ の #include ディレクティブを正しく理解するほうが先です
バイナリを#includeするという発想はなかった コンパイルしたら何が起こるんだろう こえー
56 :
53 :2008/11/14(金) 21:47:34
あ、そういやそうですね(汗 vs2005の設定で読み込ませるだけです。
C++/CLIはちょい特殊だから別扱いしないとだめ。 同じDLLでも.NETのアセンブリはだいぶ性格が違うから。
#include </dev/tty>
60 :
59 :2008/11/15(土) 02:57:37
うおー,ごめんなさい BOOST_STRONG_TYPEDEF ってのがありました…
>>60 それは数値型でだけしか意味を成さなかったような記憶が
62 :
デフォルトの名無しさん :2008/11/17(月) 23:30:13
namespace内のクラスを前方宣言しようと思ったんですが、 (namespace fugaのFooクラス) class fuga::Foo; //これだとコンパイルエラー namespace fuga{ class Foo; //これならおk } class Hoge{ fuga::Foo* f_; }; なぜなんでしょうか
>>62 そういうもんです、としかいいようがないやね
>>62 ::は名前空間解決をするのであって
名前空間を生成するわけじゃないから
65 :
デフォルトの名無しさん :2008/11/18(火) 00:09:06
visual studio2008のコンパイル方法がどっかに載ってたと思うんですけど どこか分かる方教えて下さいませ。
>>65 visual studio2008のソースって流出してたっけ
67 :
デフォルトの名無しさん :2008/11/18(火) 00:16:58
68 :
デフォルトの名無しさん :2008/11/18(火) 00:18:34
コマンドラインからコンパイラを起動するって意味か?
遠まわしに失せろと言われてるんだよ
72 :
デフォルトの名無しさん :2008/11/18(火) 00:32:37
Visual C++ 2008 Express Editionで流体の数値解析を行っています。 暫定的なプログラムが出来上がり、ビルド→デバッグなしで開始、と実行出来たのは良いのですが、 結果出力用のファイル名をscanfで受け取るように変更し、ファイル操作等を行っているところでおかしくなってしまい、 最終的には初めの上手く動作していたソースコードに新たにprintf文を付け加えただけで上手く動かない状態となってしまいました。 アルゴリズムはSIMPLEという半陰解法を用いており、未知数である圧力、速度をループ計算で解くというものです。 ループ内で、各回の収束判定変数の推移をprintfで出力していますが、これは正常に動作して16回のループで終了します。 新たなprintf文を加えると、この変数が2ループ目から#QNAN0となってしまい、圧力、速度を得ることができません。 このprintf文はループ内においても、その外側のmain文中においても同様です。 stdio.hに問題があるのかと思い、改めてscanf文を入れてみたところ、特に問題はありませんでした。 しかしputs("")では同様に異常が見られます。 収束判定用の変数には何も関与していないのに、こんなことがあるのでしょうか。 プログラミング環境の問題かとも思いますが、何か情報があれば力を貸していただきたいです。
何かの変数の初期化を忘れてるとか (たまたまいい具合に初期値が入っていて偶然動いていた)
どうせscanfでスタックの破壊でもしていると予想
書き込みありがとうございます。
>>74 初期化せずに扱っているものはないと思います。
>>75 現在scanfは用いていないのですが、スタックの破壊は具体的にどういう現象がおきていそうなのでしょうか。
スタックの破壊 の検索結果 約 239,000 件中 1 - 10 件目 (0.27 秒)
scanf スタックの破壊 の検索結果 約 3,230 件中 1 - 10 件目 (0.19 秒)
スタック破壊は怖いぞー 一見何も関係なさそうな変数がいつの間にかぶち壊れてるからな
デバッガ使えばすぐわかると思うぞ?
取り敢えず、そのprintf()の周辺だけでも貼ってみたら?
>>73 デバッガ使えるなら、問題の変数の値がQNANになる所で
ブレークしかけておけば原因がすぐわかると思うよ。
>>77-78 スタックの破壊については昨日調べました。
>>81 参考になるか分かりませんが、プログラムの概略を載せます。
1 int main(void){
2 grid(); //格子を切る関数
3 init(); //初期値を代入
4 while(sorce>sormax){
5 cal_U(); //それぞれ速度U、V、Pを計算する関数
6 cal_V();
7 cal_P();
8 sorce = maxof3(resorm, resoru, resorv); //maxof3()は3数の最大値を返す
9 printf("%lf %lf %lf %lf\n", sorce, resorm, resoru, resorv);
10 }
11 output(); //結果を出力
12 }
だいたいの流れはこのような感じです。
11行目以降はprintfを入れても問題なく走ります。
デバッガのことは知らなかったので、とりあえず今Visual C++ Express Editionのデバッグ機能を使ってデバッグをしてみました。
2行目にprintf("aiueo.\n");と入れてステップインで一行ずつ実行していくと、これまでと違い、このprintf文も実行され、ループも問題なく回っています。
これは何を意味しているのでしょうか…。
グローバル変数でデータのやり取りしているならどこかの関数で同名のローカル変数を定義しているんじゃないの。 ていうか関数間のデータのやり取りにグローバル変数使うのヤメロ。
デバッグモードに変えたりprintf入れたりした影響で挙動が変わったんだろうな しかしひでープログラムだな ローカル変数を知らないのか?
>>85 流れであって実際のコードじゃないです。
ローカル変数に見えているのは実際にはファイルのstatic変数なんです
BCBを持っていればCodeGuardの出力したログファイルを ロダに上げてもらえば一発でバグの原因が分かるんだが・・・
>>87 CodeGuardはいい機能と思っているが
いま、バカのC++を使ってるのってほとんどいないだろ。
VS用CodeGuardやVS用CodeGuardもどき ってないのか?
>>86 83のコードにローカル変数なんか一つもないじゃないか
てか変数壊してるかもって話なのに変数定義省略するとかふざけてるのか
やっぱりわかってないのね
とりあえずCの勉強し直すのをお勧めする
>>89 聞いているのは、どうしたら問題の部分を発見できますかじゃないのか?
問題箇所発見方法を聞いているのであって、(トンでもないプログラム構成だろとは想像できるが)
文法、コーディングスタイルは聞いていないと思う。それにCの勉強し直すのをお勧めする じゃ
ある意味的外れだろ(ググれカス的かな)
問題箇所部分の推定すら出来てない状況じゃ、かなりな部分のコードさらさないと駄目な気がする。
%lf が1つ多いとかいうオチなんじゃないか?
printf("%lf %lf %lf %lf %lf\n", sorce, resorm, resoru, resorv); で、コンパイル通るんですか? 試してないですが、通らないですよね で通った場合、最後の%lfは何を(どこを)表示するんですか
>>92 スタック上の適当なデータを勝手にIEEE実数だと仮定して読んだ積もりになる。
しかも、恐ろしいことに%fを生で使っているので数百桁出力することも有り得る。
×%lf ○%f C++ はまだこうだな。 そして、printf のフォーマットまでチェックするコンパイラもあるけど、 全くチェックしないコンパイラもある。 まあ、ログ入れると動くっていう変なバグは大抵スタックを破壊してる。 スタックを破壊する原因は、 ・ 配列のインデックス計算にミスがあり、配列外の領域に書き込んだ ・ 配列のインデックスに未初期化の変数を使って、配列外の領域に書き込んだ ・ ポインタの演算にミスがあり、予期しない領域に書き込んだ ・ 未初期化のポインタを使用し、予期しない領域に書き込んだ など、色々あるが、どれも原因特定には地道な作業が必要だ。
まあ基本的にスタックを破壊してるから、 ローカル配列変数の扱いにまずいところがないかチェックだな。
>>93-94 >全くチェックしないコンパイラもある
ガクガクブルブル、信じられな
それはprintf系だけで話で、
自分で関数f(a,b,c)を作り、たとえば、これをf(a,b)とか、f(a,b,c,d)とか書くと
この場合は全てのコンパイラーでエラー絶対に起こりますよね? 起こらないのあったりして
97 :
96 :2008/11/20(木) 00:25:27
天下のVisual C++ 2008はチェックしてないってこと!? なんか、orzです。
>>96 C++では通常有り得ない。Cで未宣言の状態で関数を呼ぶ場合は、大いに有り得る。
まぁ、C++でもprintf()の例で判るように可変個数引き数(...)があればチェックされないが。
printfのフォーマットって言ってるから 可変引数は普通チェックされないけど printf系とかだけ、第一引数の内容と残りの引数の整合性を見てくれるコンパイラがあることを言ってるんじゃないの?
100 :
96 :2008/11/20(木) 00:39:35
>>98 ありがとうございます。CでもC++で(.cpp拡張子つけて)コンパイルすることにします。
ただ、printfは引数の数チェックしていないと覚えておかないといけないですね。
そうしないと、printfが終わった時点でまだ使うスタック変数を失う可能性がありますね。
>>100 >そうしないと、printfが終わった時点でまだ使うスタック変数を失う可能性がありますね。
何を仰っているのかよく判りませんが、なにやら勘違いをなさっているとお見受けしました。
void* p; printf("%x", p); だと警告が出る(vs2005) printf("%p", p); は当然でない
103 :
96 :2008/11/20(木) 00:46:54
あ、可変個数引き数(...)関数はですね printf,sprintfでも変数は可変個数引だから、チェックなしは当然かな
寧ろ、チェックしてくれていると考えるんだ。
105 :
96 :2008/11/20(木) 00:53:40
>>101 どう、勘違いしていると思っているんですか?
>>102 printf("%p %d", p); じゃどうですか?
>>105 printf()の使い方をどう間違えたところで、ローカル変数がおかしくなるなんてことは(%nでも使わない限り)有り得ない。
それはさておき、「スタック変数」なんて妙ちきりんな言葉を使いなさんな。
>>83 もしかしてcal〜とかmax〜の関数の中で配列使ってないか?
使ってるなら配列に値を代入する直前にインデックスをprintfして
配列のサイズを超えた値になってないか確認してみ。
俺の予想では、そんだけグローバル変数が多いところを見ると、
きっとインデックスもグローバル変数になってて、
初期化もせずに使い、2回目以降のループで死んでるとみた。
C++だと for(int i=0; i<MAX; i++) がその類のミスを除く常套句として使えるな 多言語だとforかforeachで書くループがwhileになってるFORTRANを逐語訳して死んでるのはたまに見るな
Fortranからの移植だと、判定を<=にしてしまったり、 index-1するのを忘れる可能性がw
しかしSingle Pass Rangeに対応させようと終端チェックを!=で行う実装では無限ループする <>比較演算子だとRandom Access Traversalを要求するからのう
ATLのCFindFileみたいに、UNICODEのdefine状態に応じて、メソッドの FindNextFileA と FindNextFileW を内部で自動的に切り分けているような クラスを使う時に、MBCSとUNICODE両方に対応するコードは どうやって書いてる? #ifdef UNICODE #define FindNextFile FindNextFileW #else #define FindNextFile FindNextFileA #endif は邪道??
それは常套手段だね
それでいいと思うけど、それはWin32APIの関数と同名だから、自分でその#ifdefを書く必要はないよ。
114 :
111 :2008/11/20(木) 16:18:24
>>112 そうだよね。
ただ、クラスのメソッドだけと取り上げてdefineすると、
インテリセンスに違和感ない?
ドット打っても、こんなメソッドねーYO!なのにコンパイル通る不思議。
保守で胸やけしそう。
みんなこんなもんなのかな。
>>113 メソッド名に流用しても平気?
流用が気持ち悪いなら _FindNextFile とかにしようかな。
>>114 コンパイルできるという点では平気。あとは好みの問題。
ちなみに、ATL/WTLではUNICODE切り替えに関して全面的にWin32API用の#ifdefを流用している。
_から始まるトークンは使ってはならない。
117 :
111 :2008/11/20(木) 16:27:51
>>115 ほぉー!そうなのか。
勉強になりました。ありがとう。
>>116 なんかそれ以前誰かにも言われたな・・・
互換性の為に残してあるとか。
そういえば今だに _ の意味がよく理解できてない俺は所詮VB厨
_ と __ との違いとか意識して使ってる?
1.グローバルスコープにあり、_で始まる識別子 2._で始まり、英大文字が続く識別子 3.__を含む識別子 以上は処理系のために予約されており、ユーザが使うことは規格違反になる。
めんどくさいから、自分は1と2をまとめて_で始まるのは駄目と簡略化して覚えている。
>>106 105は、たぶんprintfとscanfを混同しているのだと思う。
スタック変数というのは確かに変な用語だがw
スレも、あまりに自然な流れで話題が scanf→printf へ移ってるからな
>>105 とりあえず俺からできるアドバイスは、
そのようなバグは、対処療法的に直すというよりも、プログラムの書き方を改善すると
自然に治るというパターンの方が多い。急がば回れ。
とりあえず、そのstatic変数を、*すべて* ローカル変数と関数の引数にすること。
数値計算のプログラムだったら、static変数なんかいらないだろ
struct God { int foo, bar, hoge; int a, b, c, d, e, f, g; unsigned char h, i, j, k, l, m, n; double piyo, piyopiyo, baz, foobar; int x, y, z; }; int main() { God god; Foo(&god); Bar(&god); Hoge(&god); FooBar(&god); Baz(&god); } と書いて満足されるかもしれない恐怖。
#define retrun return #define cahr char #define unsinged unsigned
retrunはときどき普通に変数名に使うから困る
勝手にすればと言う気持ちも半分あるが 変数名retrunはやっぱ普通に困るよ
C++の例外って std::bad_alloc 以外に何がありますか? 例外一覧が乗っているサイトとかありますか?
別に飛ばす気になればどんな型だって例外で飛ばせるが。
c++標準の例外です。
std::exceptionで検索
例外にぬるぽってないんですか? ぬるぽは、何でcatchしたらいいんですか?
>>131 ない、つーか無効なポインタ参照しちゃっても例外投げない
ぬるぽアクセスは未定義動作です。 つまり、何が起きるのか (例外が発生するのか、シグナルが発生するのか、 何事もなかったかのように動作し続けるのか、鼻から悪魔が出るのか)、 C++の規格では定義されていません。
try{ int* p = 0; *p = 100; // SNT(スーパーぬるぽタイム) }catch( int e ){ printf( "%d exception\n" , e ); }catch( std::exception e ){ printf( "exception(%s)\n" , e.what() ); }catch( ... ){ printf( "misc exception\n" ); } 一応、misc exception って出るんですお
Releaseだと出ないPO げにおそろしきぬるぽ
>>134 そういう変なものを例外で受け取れてしまうのはWindowsだけ(構造化例外)
ポインタが壊れていると、 SIGBUS とか SIGSEGV のようなsignalが送られるOSもあるし。
例えばポインタがメモリマップトのI/O領域を指していると ポインタを出リファレンスしたりするとI/Oには読むだけで 動作するものもあるので、鼻から悪魔としか言えない
139 :
デフォルトの名無しさん :2008/11/22(土) 03:38:26
ある初期化関数を呼ばないといけない処理をラップしたクラスを作るとします たとえばWindowsのコモンコントロールを使うには InitCommonControl()を事前に呼んでおく必要があります class hoge{ public: static once_init(){ legacy_global_init(); } }; hogeを使うユーザが明示的にonce_initを呼ぶ決まりにしておけばいいだけの話なんですが、 なるべく初期化関数を呼ぶ必要がない様にしたいです そこで、翻訳単位内に struct static_initializer{ static_initializer(){ legacy_global_init(); } }; というクラスを作って静的なインスタンスを作成し、 namespace{ static_initializer s_inst; } 自動的に初期化させる様にしました。 他の翻訳単位の初期化関数に依存する時はまずそうですが、 その他気をつける事はありますか? というかこういう処理をするのはどうするのがセオリーなんでしょうか
コンストラクタが初めて呼ばれたときだけ実行するとか? class hoge{ static int x; hoge() { if (x == 1) { x = 0; legacy_global_init(); } } }; hoge::x = 1;
静的オブジェクトは初期化の順序が保障されないから、あまりそういう用途で使わないほうがいい。 精々、互いに無関係な変数の初期値設定くらいだろうな。 複数のコントロールをまとめて一つの単位として扱いたいなら、ビルダーパターンとか、ファクトリとかのクラスを作って そのクラスの初期化関数を一発呼ばせる。それくらいはさせるべきだろ、 ユーザーがコントロールの初期化の前に何かやりたいと思ったときにそれが出来ないんじゃ困る。
142 :
139 :2008/11/22(土) 03:50:40
>>140 そちらの方が初期化が遅延されるので、hogeクラスを全く使わない時には
初期化関数が呼ばれないので無駄が無くていいですね
マルチスレッド環境で気をつけないといけないですが
143 :
139 :2008/11/22(土) 03:53:36
>>141 >ユーザーがコントロールの初期化の前に何かやりたいと思ったときにそれが出来ないんじゃ困る。
確かにこの視点は抜けてました
ユーザの自由度はなるべく下げたくないですね
デザインパターンですか
ちょっと勉強してきます
VS2005 C++です 仮想関数から、基底クラスのメンバー変数を参照する、クールな方法を教えて、もらえませんか 基底クラスには、そのメンバー変数に対する、アクセッサー(set/get関数)は、実装しているのですが 当たり前のことですが、基底クラスで、その、メンバー変数をセットしたものは、派生先の、基底クラスから、 呼び出しても、コンストラクターが、呼び出されだけで、初期化されたメンバー変数しか、取得できません(当然のことですが) 基底クラス、派生クラスに関係ない、普通に、C言語タイプの関数を定義して(クラスを定義しないという意味です) そこで渡す方法とか、有ると思うのですが、2ちゃんねらー諸兄のテクニックを、伝授してください、長文スマソ。
×当たり前のことですが、基底クラスで、その、メンバー変数をセットしたものは、派生先の、基底クラスから、 ○当たり前のことですが、基底クラスで、その、メンバー変数をセットしたものは、派生先クラスから、 すみません
>>144 こうか? 普通に取得できるようだけど
class Base {
private: int foo;
public: Base() : foo(0) {}
int GetFoo() { return foo; }
void Bar() { foo = 42; Hoge(); }
virtual void Hoge() = 0;
};
class Derived : public Base {
public:
virtual void Hoge() { cout << GetFoo() << endl; }
};
int main() {
Base *p = new Derived();
p->Bar();
}
>>144 意味が分からん。クールとか無理。
とりあえず自分で書いたコードでも見せてくれないか?
長文が問題なのではなく悪文が問題だな。 意味がわかりづらい上に、なんだその西村京太郎みたいな読点。
protedted「お困りのようですな」
何かの暗号じゃね?
VS2005 WindowsSDKで エディットボックス内の背景色の変更の仕方がわからない。 とりあえず、色を指定してブラシを変更して再描画命令出してみたけど書き換わらないんだけどどうすればええん?
オナニードロー
WM_CTLCOLORかWM_CTLCOLOREDITをマップ
>>153 WM_CTLCOLORでブラシの設定はさせてみたけど変わりませんでした
int配列をenum配列にキャストしたいんですが、何かいい方法ないでしょうか? テンプレート使って要素1つ1つキャストするクラス作ろうとしたんだけど、 テンプレートってenum型はダメなのね。。 enum HOGE { A = 0; B = 1; }; HOGE hoge[] = { 0, 0, 1, 1 }; // ↑暗黙キャストされないからエラー
>>154 hDC弄るんじゃなくて、返り値にヒープに作ったブラシハンドルを返すんだ
どうしてもintで初期化しなければいけないのか。 enumの使い方が間違ってないか。
>>155 HOGE hoge[] = { A, A, B, B };
でいいんじゃないか?
159 :
155 :2008/11/22(土) 20:25:34
>>157 >>158 うーん、やっぱ使い方がおかしいか。
配列初期化するときだけはintで書いた方がわかりやすいんだけど、
それはそれで別途変換コード書いたほうがいいか。
どうもありがとう。
vitrual関数のメリットが良くわからない。 継承したクラスのメソッドを置き換えるってイメージなんだけど 何でわざわざ別の処理に変更させるの?
デザインパターンを勉強するといいよ
>>161 了解。
一応ググってみたけれどけどもう少し解りやすい
メリットを提供して頂けると僥倖。
動物がワンと鳴いたりニャーと鳴いたりするためです
int hoge[] = { HOGE::A, HOGE:;B}; とかで
165 :
デフォルトの名無しさん :2008/11/22(土) 21:45:18
>>162 全然関係ないですが"僥倖"って言葉初めて知りました
でも、明日には忘れてそうです><
これが、クールな表現なんだな。
すみません、感動のあまり上げてしまいました。 その上、本来カキコする内容すら忘れてしまいました。orz
DLLからico読み出すってどうすればいいんですか?
171 :
デフォルトの名無しさん :2008/11/23(日) 00:43:26
void* と関数ポインタは互換性がないらしいですが、 では任意の関数を格納できるポインタはどう宣言すればいいでしょうか 一応 int bar(int i){ cout << "bar arg = " << i << endl; return i + 2; } //関数ポインタに入れて void (*fp)() = reinterpret_cast<void(*)()>(bar); //取り出して int (*fp_arg1)(int i) = reinterpret_cast<int(*)(int)>(fp); //実行する std::cout << "return value = " << fp_arg1(3) << std::endl; とむりやりキャストしてみると一応動きます
> void* と関数ポインタは互換性がないらしいですが、 そうなの? 「互換性」がどういう意味か分からないが、キャストは出来ると思うが。 メンバ関数ポインタは無理だけどね。
sizeof(X*)はXがvoidかデータ型なら同じになることが保証されてるけど 関数ポインタはその保証がない もしかしたらvoid*より大きいかもしれない
175 :
171 :2008/11/23(日) 01:08:15
boost::functionがその手の処理をやってそうなので 今ソースを見ているんですが、心が折れそうです
テンプレートを変態的に使うと、void*間のキャストは避けられるぜ。
>>174 > sizeof(X*)はXがvoidかデータ型なら同じになることが保証されてるけど
いや、それは無いだろ。
察してやれ・・・・・・・・
>>177 ごめん、そんな保証なかった
>>171 5.2.10.6
関数へのポインタは、別の関数へのポインタに明示的に変換することが出来る。
ある関数の定義で用いられた関数型とは異なる関数型へのポインタを介して関数呼び出しを行った結果は、未定義とする。
型"T1へのポインタ"の右辺値から型"T2へのポインタ"(ここでT1及びT2は、関数型とする)へのポインタ変換の結果は、
それを元の型に戻すと元のポインタ値に戻ることを除いて、未規定とする。
これ読む限り、関数型同士ではreinterpret_castし直せば戻ることが保証されてるみたいだから
void (*)()にでも格納すればいいんじゃね
180 :
171 :2008/11/23(日) 01:43:44
>>179 なるほど
元のシグネチャでちゃんと取り出せば、
とりあえずは何の関数ポインタに格納しておいてもいいんですね
void(*)()に入れておきます
ありがとうございました
ファンクタもテンプレートもあるんだから、そんなことすんなってことですね。
関数ポインタとデータポインタのサイズが違う事があるのは、 例えば MS-DOS のミディアムモデルやコンパクトモデルだな。 このあたり知ってれば互換性が無いのは当然の話と分かる。
DSPだとハーバード・アーキテクチャが多いから データポインタと関数ポインタはビット幅が違うこともあるよ
Cの話題になってしまうが printfのフォーマット文字列に、関数ポインタ用の%pが無いのは規格の不備ではないかと思っている
そういやそうだな。 流石にメンバポインタはどう表現していいものか分からんから 無くても仕方が無いとは思うが・・・。
186 :
デフォルトの名無しさん :2008/11/23(日) 17:23:04
>>182 i8086 を持ち出すならデータポインタ同士、関数ポインタ同士でもサイズが違ったりするだろ
すいません、私、MS-DOSって全然使ったことがないんですけど それを語ることの出来るってことは、このスレにはおじちゃん世代が かなり居るってこと?おじちゃん世代ってもう現役PGじゃないですよね
MS-DOSは20代でも知ってるだろ・・・
>>186 near ポインタと far ポインタは標準じゃないし・・・。
>>187 「自分で興味があるから小さい頃から触ってた人」と
「他に何も出来ないから専門学校を出て職業コーダーになった人」の違いですよ。
MS-DOSって確か1981年ぐらいに出たと思ったし 未だにVistaでもDOSプロンプト積んでるんだからおぢいちゃんとかおぢちゃん世代って言われる筋合いねぇっていうか 未だにバッチ処理させるのに使ったりするし、今現在「定年まで勤めたプログラマ」は存在しない
>>190 その前者はいつまで現役でプログラミングしてるもんなんだろ
当然,やりたい仕事ができるかぎりは引退までなん?
むしろコーダーの将来のほうが心配ですけどね。 どちらもまだ20代でしょうけど。
プログラミング云々ではなく「MS-DOSを触った経験」について言うなら、
Win3.1以前のユーザーなら誰しも少なからずDOSに触れたことがあるはずだから、
たとえば小学校の真ん中くらいに、最初に買って貰ったPCに入ってたのがWin3.1、
なんて人は、DOSの使用経験があってもまだ20代の半ばくらいだね。
>>190 が言いたいのはそういうこと(年齢よりは本人の"PC歴"に依存する)では。
MS-DOSとコマンドは違うとするのか? それとも同じとしているのか? 厳密に言うなら、Win2000以降はDOSプロンプトじゃないんじゃない?
>>192 自分では現役でいたくても、会社が強制引退にするのがほとんど
フリーには多いのかもしれないが、40代で主業務がプログラミングなのうちでは
ほとんどいないな
今は、コマンドプロンプトだな。MS-DOSじゃない。 そもそも、16bitコマンドってまだVistaでも動くのか?
エミュレータ積んでるから無問題
>>197 動くけど、16bit用の日本語のデータが無いから日本語使うプログラムは動かないし
最初のWindows向けに書かれたプログラム何も弄らなくってもVistaで動くものもあるっていう・・・
MS-DOSってソフトで直接I/Oいじることが可能だったはず そんなことをしているソフトもほとんどVistaのコマンドプロンプトで動くのか
コマンドプロンプトって debug ってうってみそ。 ハンドアセンブルできるよ。
そういえばMEは9x系だから一応MS-DOSプロンプトだよな。見たこと無いけど。 98SEとかはまだ現役なところもあるって聞くし。 それと、自作暦が数年以上あるような人は BIOSのアップデートとかで(無意識かもしれないが) DOSに触ったことがある人も居るだろう。 だから何だと言われればそれまでだが。
>>200 というか仮想メモリの概念がない
OS含めて全プロセスが同じアドレス空間を共有する
EMM386が火を噴くぜ
おじちゃん多いなら CP/M-80、FLEX、OS9 とか使ったことあるよな
今 flex とか言うと、flashの話になっちゃうよw ちょっと前に「flexって知ってる?」って聞かれて 「yacc/lexのlexのgnu版のflex?」って答えて恥かいたw
>>200 vistaはもう保証外のはずだけど
9x系のDOSプロンプトは、リアルモードじゃなくて仮想86モードで動いてた(
>>204 で)。
で、その場合はI/Oは全てトラップされて9xのカーネル内でエミュレートされて
正常に動くようになっていた。
もちろん、単純にI/Oを発行しなおしても調停等が無ければ正常に動くわけ無いので
それをうまく動かすために、MSは個別対応等多大な努力をしたと聞く。
ビデオやディスク等BIOSを使うのが普通だったものはともかくとして、
サウンド関係なんかはI/O直が普通だったので相当苦労したらしい。
>>206 俺はflexと聞くとflexlmを思い出す
>>205 アセンブラM80、リンカL80、ライブラリアンLIB80
aseg
.z80
org 100h
まずこれで始めたよな。
BASICの次にハンドアセンブルだろ、JK。
>>207 それどころか、9xだとWin32アプリからもIOできて、DOSアプリ同様トラップして処理される。
自分がやったのは直接ディスクアクセスで、使ったのはint割込だったけど。
Win32APIスレでやれ
すいませんあそこはちょっと・・・
C++、WindowsSDKでGUIソフトウェアを作ってるんですが、ショートカットキーってどうやって実装すればいいんですかね?
キーボードアクセラレータでググれ
class clsA{ public:const int a; }; class clsB{ public:clsA ca; }; 上記のような2つのクラスがあります。 この場合、clsBのcaのaの定数を指定する場合、どのようにしたら良いのでしょうか。 教えてください。
clasB.clasA.a
219 :
デフォルトの名無しさん :2008/11/24(月) 18:31:28
すみません。出来ませんでした。 後だしですみませんが、コンパイラはVC++2008です。
>>219 どうやったら、どうなったのか書けよ。
読んでるほうはエスパーじゃない。
221 :
219 :2008/11/24(月) 18:36:10
そもそも何処に記述したら良いのか分かりません・・・
222 :
219 :2008/11/24(月) 18:37:14
あー、すみません。今思ったら質問の仕方が悪かったですね。 clsBのcaのaの値を設定したい、ということです。
class clsA{ public:const int a; clsA( const int a ) : a( a ){ ; } }; class clsB{ public:clsA ca; clsB( const int a ) : ca( a ){ ; } }; int main( void ){ clsB b( 10 ); std::cout << b.ca.a; return 0; } こういうことか?
225 :
219 :2008/11/24(月) 18:40:23
>>223 正にそれを求めていました!ありがとうございます。
エスパー乙
>>223 clsA( const int a ) : a( a ){ ; }
の;をとったらコンパイルエラーは直りますか?
どんだけゆとりかよ。>227 ここに出て来るaはどっちがどっちのaなのか調べろよ。コンパイラも混乱するわ。 C++なんてトラップの多い言語使わずにPythonとか使っとけ。
>>228 これ
エラー:E0000、あなた嫌い
でつ
>>232 それはどういうことですか?
分かりやすく教えてください
;はその行の終わりを示すんだからあろうがなかろうが変わらない 何も無い関数の中に;つけておくのもここ何も無くて終わるよって人間の為だし ;の有無でかわるか?って聞く前にコンパイル通して試してみろよと。 頭の中でコンパイルできないなら、機械を使え、機械に使われるなバカ
つか#include<iostream>と
>>223 でコンパイルできるんだが
Visual C++ 2008 Express Editionで確認した
>>234 > ;はその行の終わりを示すんだからあろうがなかろうが変わらない
行の終わりは改行だと思うのですが?
> 何も無い関数の中に;つけておくのもここ何も無くて終わるよって人間の為だし
そういう人は何も無い関数の中に;がないと何か続きがあると思うのでしょうか?
>>236 > 行の終わりは改行だと思うのですが?
いいえ。
> そういう人は何も無い関数の中に;がないと何か続きがあると思うのでしょうか?
そういう人を探して訊いてみればいいと思います。
セミコロンが行の終わり? バカとバカががっぷりよつに組んでるようにしか見えん。
あーではいつもの厳密な定義をお願いします
厳密な定義が欲しけりゃ仕様書を読むのが早い
>>237 > > 行の終わりは改行だと思うのですが?
> いいえ。
では行の始まりだというわけですね?
> > そういう人は何も無い関数の中に;がないと何か続きがあると思うのでしょうか?
> そういう人を探して訊いてみればいいと思います。
では
>>223 の人に訊いてみてください
>>238 > バカとバカががっぷりよつに組んでるようにしか見えん。
同感ですね。
>>239 > あーではいつもの厳密な定義をお願いします
いつもの?
>>241 > では行の始まりだというわけですね?
いいえ。
> では
>>223 の人に訊いてみてください
意味不明です。
>>240 > 仕様書
別名「馬鹿には見えない文書」ですねw
245 :
デフォルトの名無しさん :2008/11/25(火) 00:01:04
自分が読んでないことを露呈する用語だな
説明できない=仕様書読んだ事ありませんと 言っているようなもんか
";" 単体は空文であって文の一種だから文法的に問題ない…でいいんじゃないのかな
>>231 みたいな面倒くさい人に絡まれたときには相手にしないのがいいと思うけど、
>>234 で「行」ではなくてexpressionとでも書いておけば揚げ足もとられなかったのだね。
expressionじゃまだつっこまれるぞ
ちなみに、
>>231 がしてるのは";"じゃなくて";"の話だからな。
細かい違いに絡む人なんだから、勝手に";"の話とか解釈すると
これも揚げ足とられるから注意ね。
>>249 ちょっと気になるなぁ・・・。
>>250 それこそ文意を汲んであげないと可哀想。
そういえば最近「鼻から悪魔」ってよく聞くんですが流行ってるんですか。
>鼻から悪魔 C++を使おうという人ならこの程度は読んでなきゃ話にならない、という本で使われてたね。 もちろん、その本を読んで無くてもその程度のことが当たり前に身についてる人も居るだろうけど。 それと、最近じゃないよ。昔から。
元々はなんかのフォーラムのネタじゃないんですか? 最近よく聞くようになった気がするのは仕様の話をする人と接する機会が増えたせいかな・・・。
>>251 えー。困ったちゃんキャラになって文意を汲まない遊びをしてる人なんだから、
乗ってあげなきゃ逆に可哀相じゃん。
>>253 1992年ごろにcomp.lang.cあたりに投稿された記事が由来だそうだが。
まあ最近っちゃ最近だわな。
>鼻から悪魔 自分、この言葉にはなにこれって感じで、なんか、ぽかーんって感じ 英語ではぴったりの表現なんかな?それとも、良く使われる表現?
>鼻から悪魔 自分、この言葉にはなにこれって感じで、なんか、ぽかーんって感じ 英語ではぴったりの表現なんかな?それとも、良く使われる表現?
お前らこぴぺすんなよ、絶対だぞ
「未定義動作はどんなに突拍子もないことも起こりうる」っていうことの 突拍子もないことの喩えなんだからその印象であってる
なんかあっちの人っぽい言い回しだよな。 日本的な言い方に変えた方がいいんじゃね? モニタから美少女とか。
有りうるからダメ
>>259-260 目ん玉が飛び出す の方が日本的でいい
鼻から悪魔じゃ、日本語能力低すぎて、ひどい翻訳している翻訳者と同じレベルだな
鼻からではないけど、ハクション大魔王が元ネタだと思っていた。
鼻から牛乳が好きなのだが
>>262 そこで「既存の慣用句に使われている表現」を出すのは、ちょっと違うんじゃないかなぁ。
未定義の世界に踏み込んだ結果起こりうる、まったくの「予測不可能」を表現するには、
他で一切使われていないナニか、のほうが相応しいと思う。
たとえばの話、「物凄い金額を見せられる」という定義された行動でも「目玉は飛び出る」ものだから、
「未定義だと、こんなことさえ起きかねないんだぜ!?」っていう、未定義ならではを表現する言葉としては、
それだとインパクトが薄いのではないかと。
ここまで書いてやっと気付いたけど、すげえどうでもいい話題だなこれw
変に凝らずに「パソコンが爆発しても仕様に反しない」でいいじゃない
ケツからタケノコでどうでしょう。
ボスに挑発的なメールを送ってもよい 競合他社にソースコードをFAXしてもよい 試験ではうまく動いて一番大事な顧客の前で突然動かなくなってもよい
> 競合他社にソースコードをFAXしてもよい どうせならFTPでファイルください
270 :
デフォルトの名無しさん :2008/11/25(火) 22:47:34
チップから煙なら出たことある
ただし魔法は尻から出る
>>268 > 試験ではうまく動いて一番大事な顧客の前で突然動かなくなってもよい
Effective C++だっけ。サラッと流すような書き方が逆に笑えた。
5次元ベクトルを格納する領域をn本 (nはわからない) を1グループとしてそれをmグループ持つデータ構造ってどんなのが 考えられるでしょうか? nの数はグループによって違います グループ1 double[5] double[5] ・ ・ ・ --------- グループ2 double[5] double[5] ・ ・ ・ アクセス時は、グループ2の1本目を見る、2本目を見るみたいにアクセスしたいです
std::vector<double[5]>
グループのタグ(stringかcharで)も付けたいんですが・・
あとvectorの中に配列使った場合の値の入れ方がわかりません・・・ vect.push_back( ) みたいには入れられませんよね ;
vector<double[5]> test; double tmp[5]; tmpに入れたい値を一回入れる test.push_back(tmp);
STLコンテナの要素にはCopyConstructibleかつAssignableなものしか使えないよ
stringとdoubleの構造体にしてその構造体のvectorをつくればいい
>>280 良く分からないんですけど
struct neko {
string* nyah;
long piki;
vector<double[5]>* otte;
};
vector <neko> nekos;
こんな感じですか...うんーーん
グループ内の順序とか、速度やメモリ効率を気にしないなら、 std::map<std::string, std::map<std::string, double[5]> >でいいんじゃない。 あ、タグは外側グループ、内側グループの両方につけた形だけど、そこんとこどうなの?
どういう使い方を想定しているのかもうちょっと詳しく書けないものか 使い方次第で,適したデータ構造などは変わるものだが
自分が何を望んでいるのかを、 質問してから先の問答で初めて真剣に考える奴って 割といる。 「俺は何かを望んでいるけど、どうやらそれが上手く行かない、誰か助けて〜」 死ねばいいと思う。
C++の初心者向けの本でオススメの本があったら教えて下さい。
accelerated C++ C++ coding standard 101
C++ Primer
>>284 あなた自身のことですね。死ねばいいと思う。
Modern C++ Designマジお勧め
WindowsSDKで行数取得とかってある?
C++初心者向けって聞いてるのにModern C++ Designはないと思う。 Accelerated C++はマジお勧め。 学部のプログラミング演習等の副読本にも適していると思う。
ロベール
いやいや C++が学ぶべき価値がある言語か判断するために最初にMC++Dを眺めとくのは重要 アレに興味を持って、理解できるようになるまで勉強しようと思えない限りC++には触らない方がいい
ごめん、APIスレと間違えた
>>293 は
Modern C++ Designの内容を完全理解し、書いてあることを使いこなしているいるのか
自分で使いこなせなくても、既存のテンプレートライブラリを使うことはあるだろうし トラブルが起これば中の汚物を読まなきゃならなくなることもあるはずだ その時にMC++Dの知識は役に立つ
俺もModern C++ Designは好きだけど初心者にオススメする神経が分からんな。 普通はマナちゃんのやさしいC++とか柴田望洋とか林晴比古あたりじゃないの。
理解できなくてもパラパラめくるだけでいいよ そこで吐き気を催したら引き返した方がいいというだけ
>>298 じゃ、本屋でパラパラ見るだけで良いってことか
パラパラ見て、お前は
アレに興味を持って、理解できるようになるまで勉強しようと決意してC++
を始めたのか。で、最初のステップとしてどの本を読んだ?
おれは 独習C → ポインタの極意 → 独習C++ → Effective C++ で独習C++は選択を間違えたと思えた
ここまで林本なし ま、いいことだw
>>300 独習C++ って俺のC++の最初の本だ
なっ、なぜそう思うんだ
標準C++/STLの基礎知識3部作 柏原正三著 ちょっとあちこちに記述に癖があるけど、それをわかってて 読むなら結構易しい入門書
Cのリファレンス→C++のリファレンス→やさしいC++→猫でも分かるCからネットワークまで→その辺のSDKリファレンス
>>302 300じゃないけど、独習C++とかC++入門の類って基本的にどれも同じ匂いがする。
それぞれ記述に工夫はしているだろうけど、どれもC++の大味なダイジェストにしか過ぎないというか。
学ぶという点ではAccelerated C++に一票。
独習C++は罠 絶対途中で飽きる…
307 :
デフォルトの名無しさん :2008/11/27(木) 09:31:19
適性試験用に禿本
>>302 ,305
独習C++の入門という意味では普通に読了できたんだけど
その後読んだEffective C++で知らないものばかりでてきて
独習C++だけじゃ全然知識足りないのかよ,って当時の自分は困ってしまってたから,こういう印象かな
そのあとは結局大学の図書館でいろんな本あさりまくってしまい効率悪かった
独習C++の後はこれ読むといいよ,っていうオススメな本とかも思い当たらないしなあ
でもそういう過程で知識がついたっていうのもあるけど
309 :
302 :2008/11/27(木) 18:33:54
>>308 入門書で必要十分な知識なんて得られないと思っている
独習C++ -> accelerated C++ -> 詳説C++ ってな感じだったな。
独習C++:C++さわりの勉強
accelerated C++:C++らしいコーディング、使い方
詳説C++:より詳しく
これら全ての読み終わってようやく入門過程終わりって感じかな。入門過程復習を兼ねて
禿げ教科書を詳説C++の後あたりに読むのも良いかもしれん。
次は初級過程でEffective C++、Effective STLなど自分の興味に応じて読めって感じだな
Effective C++は必須だろ 興味なくても読んでくれないと困る
Cは大学の講義で習い、C++は独学 C++専用ライブラリを使い倒して学んだ その後、流行りのJAVAを興味本位だけで理解してみようと 入門書『明解JAVA』を購入 結構良かった 何が言いたいかっつーと、同じ著者で『明解C++』も出している 読んだことはないがちょっと期待
Effective C++読むくらいならExceptional C++のほうがいいと思う。 Effective C++は当たり前の事ばかり書いててあんま役に立たんかった。
その「当たり前の事」が大事なんだろ 平気でコンストラクタで仮想関数呼んだりデストラクタで例外投げたりするんだぞ初心者は
Effective C++を初めて読んだ後 基底クラスの非virtual関数と同名のメンバ関数を派生クラスで定義していたのを 納品前にこっそり修正したのは 今となってはいい思い出だ
C++ depthシリーズ読んだ後で作ったコードレビュー時の俺チェックリストが凄い事になった 自動化できそうなチェック項目も結構多いんで こういうのを自動的に点検してくれるようなコードチェッカーってのが欲しいと思ったな 精度の高いパーザがあればそう苦労せずにできそうだとは思うけど gccならコンパイラオプションでeffective c++に載ってるような間違いに対してある程度警告してくれるんだよね
-Weffc++だな しょうもないのしかチェックしてくれないけど
>>285 初心者向きなのは
プログラミング言語 C++
Effective C++
上の2つを読んだらこれがおすすめ
More Effective C++
C++ In-Depth Series
More Effective C++は原著(英語)の方がオススメ 間違いなく日本語訳より読みやすいから
高橋麻奈のやさしいC++やロベールのような最近の本は こういう時ろくに話に出てこないよな。
C++を「やさしい」なんて言う本はそれだけで信用ならない
基本機能一通りなんてどれでやっても大差ないだろうし それより、言語仕様上やれるけど辞めてください項目を知ってもらうのが
>>319 おっさん、じじいが多く、最近の入門書なんて読んでないから
話できないんじゃね。
厳しいと思うよぉ
コードを書く奴に厳しいのが多いだけ。 言語自体はやさしい。
C++はそこまで難しいとは思わない だがしかし、GoTo文とかあるんだけど滅多に使うなって言われるものの説明が無い本が多いw
ダメなC++本の見分け方 ひとつでも該当したらその本は捨てろ ・void main() ・定数をマクロで定義してる ・コンストラクタの初期化リストを使わない ・using namespace std; ・意味もなくキャストが旧形式 ・_で始まる名前を勝手に使う ・ヌルポインタがNULL ・X x = new X(); if(x == NULL){ ... } ・ポリモーフィズムの例え話にAnimalクラス ・void operator +=(X) ・X& operator +(X,X) ・多重継承をとりあえずこきおろすが理由は書いていない ・「グローバル関数は危険です、全部メンバ関数にしましょう(キリッ」 ・「コンストラクタから例外を投げてはいけません(キリッ」 あと何かな
>>327 using namespace std;を一方的にダメだというのがダメだと思う
古臭い本 #include <iostream.h> auto_ptrをコンテナの要素にする。 nothrowでないnewの結果をヌルと比較している。
>>328 説明を簡素にするためには必要悪だよね。
>>327 入門者用Good本の見分け方,please
ソースファイルの全てのincludeの後だったら別にいいんじゃね? >328
実際のプログラムでは使うなよ、って書いてあれば十分
334 :
デフォルトの名無しさん :2008/11/28(金) 01:35:51
using namespace ATL;
というか、初めてC++に入る人間に対して名前空間がどうだあーだって説明してもわからんだろう。 はじめから順番にやっていってクラスが終わった辺りででてくりゃまだ実感沸くだろうけど。
>>327 >ヌルポインタがNULL
現行でどうせいっちゅーんだ?
C++0xはまだドラフトだぞ。
現行ではヌルポインタは 0 と書くのが一番いいんじゃね
あるコンパイラで浮動小数がIEEE754かどうかを判別するためのマクロってありますか?
>>338 標準には、ない。実装上は、なくもない。
ヌルポインタはreinterpret_cast<void*>(0)だろ常考
__STDC_IEC_559__ とかいうやつかな
bccで64bitの整数使いたいんだけど・・・long long intが通らない どうすりゃいいの?
bcc捨てればいいんじゃね
__int64 で
>>340 それをまたキャストするんですね分かります
今まで上がってる本は、C言語を把握している事が前提? 本当にズブのド素人が読むには何がオススメ?
せめてstatic_cast<void*>(0)だろ… reinterpret_cast<void*>(0)はバイト列0x0をポインタと見做したものであってヌルポインタとは限らない
まあ偶然うまく行く環境が多いだろうけど それで正しいことにはならないぞ 規格読んで出直してこい
なるぽ
今日、コンストラクタでは 変数の初期化以外はするなと指摘されたんですが・・ わざわざCreateや、Initなんてメソッド作るメリットって何ですか?
例外が嫌いな人はそう言うかもね。 コンストラクタは例外以外で直接はエラーを表現できないから。
355 :
デフォルトの名無しさん :2008/11/28(金) 19:13:29
そうなんです。 コンストラクタの例外も突っかかれました・・・
取り敢えず引き数なしで定義しておいて、後から初期化処理を呼ぶことができると フレームワークのようなライブラリでは便利なのかもしれないという程度だと思う。
別にコンストラクタから例外を投げても何ともないんだけどね。 RAII を使う場合はエラー時にコンストラクタから例外を投げるのは常識的な行為。 Google みたいに「例外を使ってはいけない」とかいうコーディング規約がないのであれば。
>>356 初期化のタイミングをコントロールしたい場合は便利だよね。
new する手もあるけど、new は失敗するかもしれないし・・・。
あとコピー代入演算子の実装が楽になる
しかし、デメリットとしては、初期化が十分に行われていないうちに 色んなメンバ関数を呼ばれると困るという点があるね。
361 :
353 :2008/11/28(金) 19:25:19
RAIIという言葉は今はじめて知りました。 でも自分が理想としてるのは、まさにこんな感じです。 wikipediaチラ見ですけど。
どっかで仮想関数呼んじゃったらアウトだからな だから逆に「コンストラクタでメンバ関数を呼んではいけない」ルールがよいという主張もある どっちが正しいと言うもんでもない
まあ setter 使っても RAII できないわけじゃないので (語源的にどうかと思うかもしれないけど、 重要なのはデストラクタで自動的にリソースが開放される点なので)、 コーディング規約によっては setter 使っても悪いわけではない。
364 :
353 :2008/11/28(金) 19:43:09
>>358 自分は、おそらくそういう意図で指摘されたんだと思います。
new でタイミングをコントロールしちゃまずいんでしょうか。
その方は高速化がどうのこうのとも言っていました。
>その方は高速化がどうのこうのとも言っていました。 寝言は兎も角w >new でタイミングをコントロールしちゃまずいんでしょうか。 タイミングコントロールだけが目的なら感心しないが。
まあ new は遅いからね。 ベストは両方可能にすることな気もするが。
367 :
353 :2008/11/28(金) 20:06:13
考えてたら、両方可能にしとけば 問題ないような気がしてきております。 既存のクラスって結構そういうのが多い気がしますし・・ いろいろご教授ありがとうございます。
イラネ
ハゲはむしろC++0xの本を
VC++2008を使っています。 無名名前空間にプロトタイプだけ突っ込んで、定義は他の場所で行おうと思っているのですが、どうにもうまくいきません。 func1()の方は特に問題なく動くのですが、func2はerror C2825が出てコンパイルエラーとなります。 何故でしょうか、、、 #include <windows.h> namespace{ int func1(); BOOL func2(); }; int ::func1(){ return 1; } BOOL ::func2(){ return TRUE; }
::だとグローバルネームスペースになるんじゃなかったっけ?
:: いらないよ
374 :
デフォルトの名無しさん :2008/11/29(土) 15:01:34
template< typename BaseType = char > class ChTraitsBase { public: typedef char XCHAR; typedef LPSTR PXSTR; typedef LPCSTR PCXSTR; typedef wchar_t YCHAR; typedef LPWSTR PYSTR; typedef LPCWSTR PCYSTR; }; って言う記述があった場合、これってどういうこと? クラスなのにメンバ変数とか、関数とか物理的なものが何もない。 これはtypedefの及ぶ範囲をChTraitsBaseクラスおよびその派生クラスで限定したいテクニックなのかな?
特殊化と併用して 参照の参照を回避するのに使ったり
376 :
374 :2008/11/29(土) 15:09:37
レスありがとう。 でも何のことやら理解できない(TT)
>>374 ChTraitsBaseはwchar_tで特殊化されているはずで、
全体としてみると、charかwchar_tでの使用しか念頭に置いていないCStringTで、
X〜は自身のテンプレート引数と同種、Y〜は違うほうの文字の型になるようにできている。
例えば、ChTraitsBase<char>::YCHARがwchar_tで、
ChTraitsBase<wchar_t>::YCHARがcharになるという具合。
具体的には、コンストラクタなどでは、X系の型ならそのまま格納、
Y系の型が来たら変換して格納なんて区別に使っている。
なるほど。。考えた奴頭良すぎ こういう使い方はC++の世界では、そういうテクニックとして認識されるものなのですか?
>>378 標準ライブラリに std::char_traits や std::iterator_traits やらあるから、まぁそうだね。
最近は ..._traits みたいにひとつの型に複数の要素を入れるより、テンプレート引数から
一つの結果(型 type またはコンパイル時定数 value など)だけを取得できるようにして、
関数のような使いかたができるようにした「テンプレートメタ関数」のほうが好まれる。
他の場所でnewで確保されたオブジェクトのポインタを持っているとき、 そのオブジェクトがすでにdeleteされたことを ポインタを保持している側が判断することは可能ですか?
>>380 面倒だから、削除された時に中身NULLとか書いておけば?
shared_ptrならば、weak_ptrがある。
「Effective C++があたりまえ」って言うけど、C++の言語仕様を読んだだけでこれらのテクニック全て を当たり前だと理解できるのはすごいと思う。 普通に使ってても、テンプレート関連のテクニックとかを悟るのは相当厳しいんじゃないか? あとみんなクラスのメンバ変数はどんな時でも全てprivateにしてるの実際?
実は大抵のSTLの実装では vectorやらlistやらのメンバ変数は protectedか、実装によってはpublicだったりする。 継承すべきclassじゃないのに。 まあstackやqueueに使うためなのかな、と後で思ったが。
protectedメンバ変数は悪だと言われてるけど実際は使っちゃうなぁ 派生クラスからしてみれば「自分の一部」として扱いたいこともあるし protectedなアクセサ書くのもダルいし publicにはしない
386 :
383 :2008/11/30(日) 00:42:08
実際俺も仕方なさそうな時はprotected使ってます。 OSSのコードとか見ても「メンバ変数は絶対private」を守ってるのはすごく少ないように思いますね。
>>383 前半部分に付いて。
Effective C++(やその他Must Readな本)の内容は先人たちの長年の試行錯誤の成果だよ。
だから普通のC++ユーザは、自分で悟らなくてもそれらを享受すればよいだけ。
ただ、読んで盲目的に倣うんではなくて、勘所を理解した上で効果的に使って欲しいと思うけどね。
protected なメンバはほとんど使わないな。 使いたくなった時はカプセル化の単位を見直せば、だいたい片付く。 this 以外を通しては同じクラスでもアクセスできないとか、 private/public には無いわかりにくいルールもあるんで、あんまり 使いたくも無い。
俺なんかクラス内でさえprivateメンバはアクセサ経由してるさ
ほう アクセサもアクセサ経由で書いてるのか
アクセサにアクセサ用のアクセサがあり、そのアクセサ用のアクセサにはアクセサ用のアクセサのためのアクセサがある。
private変数使わずにstatic変数でがんばります
まぁ俺は開き直って全部publicだけどね。 もはや構造体でも十分かも
例外もprotectedも気にしなくていいC言語使えばいいじゃない
cobolでも使ってろハゲ
御大にcobolでも使ってろとはなんたる暴言
397 :
デフォルトの名無しさん :2008/11/30(日) 08:06:22
publicにすると楽で良いぞ〜 マルチスレッドで排他でもしない限りまったく必要ないしな ウインドウズアプリだけどさw
マルチスレッドは関係ないと思う あとウィンドウズアプリも
399 :
デフォルトの名無しさん :2008/11/30(日) 08:19:40
マルチスレッドでアクセスさせるときはアクセサつくって排他制御したほうが楽ジャン ウインドウズアプリって言ったのは規模がオモチャ程度ってことを言いたかっただけさ
オモチャ程度(笑)
Scott Meyers氏も、Effective C++だったか、More Effective C++だった、俺の記憶が曖昧なのだが、protectedの存在意義について、明確な ではないということを、書いてたな、 ただ思うに、何でもかんでもprivateにして、アクセッサーを作れば良いのかといえば、そういうもんでは無いと思う コンストラクタの動きを熟知したうえで作られた、genericのコードを見ると、思わず、なるほどと感心する事もあるからな
402 :
デフォルトの名無しさん :2008/11/30(日) 12:30:24
>>368 ∧ ∧ ∧ ∧
(・ ∀・) (・ ∀・) ビャ〜ン
(〜)〜 (〜)〜
┘| ┘|
>>401 の続き
C++再考、古い本だが、良書である
この本では、「仮想関数を使うべきでない場合」という章があって、パフォーマンスの面で
仮想関数を使う場合は、そのコストも良く勘案して使うべしのような、ことが書かれているのだが
その解決手段の一つに、protectedを用いて、継承を可能にする事例が掲載されている。
デザパタでいうところのFactoryパターンで、インスタンスの生成を制限するのに、
protectedを上手に使うよね。
ようするに、適材適所、使い方次第ってことかな。
終わり。
protectedメンバ関数に疑義を唱えてる人は少ないだろ 問題はprotectedメンバ変数の方 こっちは禿もD&Eで後悔してるって言ってるしHerb Sutter氏は邪悪だと言い切ってる
ただ、悪魔の囁きで使いたくなるんだよねって話。
ねーよ。
407 :
デフォルトの名無しさん :2008/11/30(日) 18:59:47
splitみたいなのATLにないかな・・・
>>401 アクセス制御のprotectedと
protected継承は明確に区別しような。
newしたオブジェクトをそのコンストラクタが実行し終わるまでにdeleteするのは合法ですか?
>>409 どうやるんだ、それ?
コンストラクタが実行し終わらないと「newしたオブジェクト」が存在しないと思うんだけど。
コンストラクタで delete this とか? どう考えてもやばいだろ
>>412 どうしてそれが合法かもしれないと思うの?
>>413 違法であるとは定められていないかもしれないからです。
そもそもどんな動作を期待してるんだ? new の戻り値がまったく使えないことになるだろ、どう考えても。
コンストラクタで例外を投げるというのなら当然のようにするけど、 コンストラクタでdelete thisは聞いたことがない。 コンストラクタが完了してない、つまりオブジェクトの構築が終わっていないのに デストラクタを呼ぶというのはC++のオブジェクトに対するモデルにそぐわないと思う。
つまりコンストラクタでdelete thisが呼べてしまうC++の欠陥というわけだ。
free(this)じゃ駄目?
>>420 問題外。newしたものをfree()で解放した場合は鼻から悪魔。
せめてメモリだけでも開放させてあげたい親心なのに... 水子霊が成仏できなくて夢枕に毎晩たつようになる(T_T)
一体どうしてそんなことをしたいだろうか。 例外を投げるようなライブラリを初期化処理で使いたいとかだったら、 FactoryMethodパターン使えばいいだけだし。
コンストラクタで例外投げたら、自動的にメモリ解放されるだろ
端的すぎるだろ
>>424 何のメモリ?コンストラクタ内で確保したメモリとかも?
newしようとしたオブジェクト用に確保された領域
>>422 コンストラクタ内で動的に確保したメモリは、コンストラクタ内で例外が発生した場合はコンストラクタ内で解放する必要があります。
Foo::Foo():
m_p1(NULL),
m_p2(NULL)
{
try {
m_p1 = new P1;
m_p2 = new P2;
}
catch(std::exception & e) {
delete m_p1;
delete m_p2;
}
}
だからこれは二重deleteで落ちる struct A{ A(){delete this; throw 1;} }; int main() try{ A *a = new A; }catch(...){ return 1; }
>>428 変なサンプル載せんな。バグってるし。
その問題に対する修正は RAII を徹底することだ。
>>428 みたいなおぞましいコードを平気で書いて人に見せびらかすような輩の存在に恐怖する
たまには関数try-catchのことも……
>>432 それがこの流れと関係あると思うんなら、たぶん何か勘違いしてる。
434 :
432 :2008/12/01(月) 01:31:17
そんな、ネタにつっこまれても困ります。
>>428 ってバグってるか?
delete 0 はOKらしいから大丈夫じゃね?
一定周期で話題になるよねコレ
>>436 そこは関係ない。
>>428 まず、この場合は throw される型に関係なく delete したいんだろうから、
catch (...) じゃないと不完全。
そしてもう一点、 new P2 で例外が投げられた場合に delete 済みの m_p1 を
メンバに残したままコンストラクタが完了してしまっている。これは catch の最後に
throw を置けばいい。
ただし >430 の言うとおり、 RAII による対処が望ましい。コードが減るうえに
上記2点の対処もコンパイラに任せられる。
>>436 例外が中で握り潰されるから、delete済みの無効ポインタを持ったゴミオブジェクトが生成されてしまう
多分デストラクタでm_p1とm_p2をdeleteしてるはずだから、
ゴミオブジェクトが破壊される時に二重deleteが起こる
>>437 >>438 catch(...)は微妙だが、それ以外は
全部仮定の上の話じゃん。バグとまでは言えない。
と、馬鹿が申しております
>>439 デストラクタでdeleteしてない変な設計だったとしても、
newしてる以上どっかで必ずdeleteしてるはずだ(それをしてないならメモリリークのバグ)
中のメンバがnewに成功してるのか、失敗してゴミになってるのかは移植性のある方法で確認できないから
「ゴミならdeleteしない」という方法で逃げることも出来ない
よってnewに失敗すればメモリリークか二重deleteのどちらかがどっかで必ず起こる
これをバグでないと思うような奴がC++のプログラム書いてると思うと恐ろしい
とりあえず delete m_p, m_p = 0; とかしとけばいいんじゃないの
>>441 だからそれも仮定の話じゃん。
バグと思うか思わないかは知らないが
>>428 のコンストラクタのコードだけみて
バグであるとは言えないと言ってる。
>>437 ぐぐったら出てきましたが、auto_ptrをこういう使い方をして大丈夫でしょうか?
class RAII {
std::auto_ptr<Test> m1;
std::auto_ptr<Test> m2;
public:
RAII() : m1(new Test), m2(new Test) { }
};
>>443 それを強弁して何がしたいの?
バカがあのコード見て見習ったら困るじゃん。
>>443 本当のバカみたいだから丁寧に説明する
>>428 を含むプログラムがバグを持たないためには、次のどちらかが保証されなければならない
・Fooクラスのインスタンスがどんな実行パスでも一切生成されない
・new P1とnew P2が絶対に例外を投げない
前者ならFooクラスの定義自体が無意味だ
後者ならわざわざあんなtryブロックを書く必要はない
よって
>>428 のコンストラクタのコードを含むプログラムは
全く無意味なことを書いてるか、バグがあるか、どちらかと言うことになる
428がチラシの裏に脈絡のない落書きをしたつもりでない限り、あれはバグだということだ
>>445 ありがと、メンバで使ってるのははじめてみた。
みんな delete なんか書かずに auto_ptr なり何なり使ってくれよ。 デストラクタで delete してるクラスなんか半分ぐらいコピーコンストラクタや 代入演算子でバグってるのが実情だろ。
450 :
デフォルトの名無しさん :2008/12/01(月) 06:05:15
>>421 鼻から悪魔、なつかしいw
えぴすてーめーさんだっけ?この言い回し好きだったのは.
>>449 そういう場合だとauto_ptrを使ってもなんの解決にもならない
それはしらん
453 :
428 :2008/12/01(月) 08:12:56
すげー変なサンプルですまんかった。
>>437 に全面的に同意するよ。
酒に酔ってたと思いたいorz
454 :
デフォルトの名無しさん :2008/12/01(月) 14:21:51
C++をCに変換するツールみたいなのってありますか?
つ[派遣社員]
456 :
デフォルトの名無しさん :2008/12/01(月) 14:41:11
一瞬まじめに答えろやって思ったけど ジワジワ来て結局笑ってしまった
>>457 自分のツールとなる自前の派遣社員を調達する
459 :
デフォルトの名無しさん :2008/12/01(月) 17:35:26
enumについて質問です。 enum A{b,c,d}; enum E{f,g,h}; のように書いた場合、例えばcからタグ名であるAを取得する方法はあるのでしょうか?
decltype (c)って言っていい?
まだ早い
typeid(c).name() とか
なんちゃって
いつも忘れちゃうんですが、コンストラクタ内でのthisポインタを通した操作は合法ですよね?
仮に違法だったとしようか コンストラクタの中で出来ることがまともに残ってるか? 少しは考えようぜ
グローバル変数にthisポインタを渡して 別スレッドに操作してもらえば コンストラクタ外だから問題ないですよね
>>468 理由と結論にまったく脈絡が見られないんだが。
C++使いって屁理屈好きばかりで、いやーね。
意味のわからない理屈は往々にして屁理屈に見えるものだよ。 自分を大きく越えちゃってる世界に行くと、住人すべてが屁理屈ばっか言ってる馬鹿に見える。
まあでも例外安全の強い保証とか移植性・汎用性確保のためのテンプレート技法とか 大半のC++プログラマにとって意味不明っつーか知らなくても問題ない話が 粗大ゴミじゃねえ、醍醐味なんだよな
C++使いは優秀な人多いと思うんだけど、それでも仕事は底辺ITドカタなのかな? まぁ別の意味で使えない人種なのかもしれないけど。
C++を本当の意味で「使えてる」ひとならそこそこ優秀だろうよ。 残念ながら勘違いしてる人が多い。
475 :
デフォルトの名無しさん :2008/12/02(火) 09:16:08
本当の意味で「使えてる」ひと(笑)
使えないひとがヒス起こしました。
オレがC++を使うのは計算実験プログラムや各種のツール作りで 一人で作っていいものがターゲットだから 手段のC++が大好きなだけで 他人に発注するプログラムや 面倒そうなターゲット依存GUIアプリ作りにはC++を決して使いませんよ 共同開発もストレスたまりそう
日本では大多数を除いて プログラミング能力のある人間ほど、プログラミング自体を職に設定していないと思われ それなりの能力と社会的常識があれば、他の待遇の良い職についてるだろうし 仕事で行うコーディングは決して楽しいとはいえないわけで
>>472 例外安全を知らないのは C++ に限らず大問題じゃね?
例外安全性の検証とか機械にやらせたいわ あるメソッドが呼び出しグラフを追って例外を吐く可能性のあるメソッドの呼び出しを含むか否か を手作業で確認あるいは脳内dbに問合せするなんて人間様のやる事じゃねー
>>480 べつにそんなことしなくても例外安全に作る方法はわかってるでしょ。
「呼び出しグラフを追って〜」なんて、コードに不備があるときにそれが実害に
結びつくかどうかを検証するだけのこと。
コードに不備があるかどうかの検証はその場のコードと、そこから呼び出される
関数それぞれが例外を投げるかどうかを見ればわかる(はず)。これは戻り値で
エラーが報告される場合と同じ。
>>481 その場のコードと、そこから呼び出される関数群とさらにそれらの関数群が呼んでる関数群
例外危険性は伝搬するから(例外安全で無い関数を呼ぶ関数は例外安全では無い)、
結局「安全性」の確認にはその場のコードを根とする木の全探索が必要になるよね
それらを馬鹿で面倒臭がりですぐ忘れたり間違えたりするという厄介な特性を持った
人間様が一つ一つチェックするわけ?
例外安全性をコンパイラで保証するのは無理だよな constのような修飾子を手で加えて例外安全でない呼び出しを追跡させるのが精一杯だろうが 正直そこまでいらないぜ
そういう静的コード解析ができるツールがあったらいいのになぁっていう 関数名指定したら再帰的にチェックして例外安全性の有無を判別してくれたりとか
>>484 C++プログラマなら自分で作る。
C++コーディング出来るだけじゃドカタ。そんなツールを作れてプログラマ。
俺は底辺ドカタだからクレクレだがな、orz
>>480 半手動みたいな方法だけど
C++ Sourceに、関数が例外安全かどうかをタグ付けして、コンパイル時にタグを検証する方法が投稿されてたよ
C++初心者です。 list<int> list[M][N]; みたいな2次元配列って出来るんですか?
できますよ。
「みたいな」っていうのは良い訊ね方ではないなぁ。
もうちょっとこう、譲れない要求がハッキリしていないと、
二次元配列であるという以外にコトを絞れなくて、当然のように
>>488 が答になる。
C++のライブラリ設計のノウハウ的な良書ってない? 実装の本はいっぱいあるけど、設計的な視点なのってあんまない気がする。
>>489 >>487 です。
確かに尋ね方が悪かったと思います。
とりあえず二次元配列を用意したのですが、
・初期化
・for文を使った要素の挿入
・displayの仕方
がわかりません。
御教授お願いします。
>491 まずそもそも欲しいものは list の二次元配列で正しいのか?二重の list (list<list<int> >)だったりしないか?* for 文を使った要素の挿入って挿入したいのは list でいいのか、int なのか? 挿入っていうからには後の要素は後ろにずれないといけないのか? やりたいことを正確に説明しようぜ。
>>492 二重のlist(list<list<int>>)とlistの違いがわかりません。どう違うのですか?
挿入するのはint型の要素です。
挿入したら後の要素は後ろにずれるようにしたいです。
二重のlistは二次元構造だけど、listの二次元配列は三次元構造だ どっちが欲しいんだ?
欲しいのは2次元構造です。
じゃあどっちかだな 好きな方にしろ list<list<int> > list<int>[]
list<list<int>> lst1; ↑このような形で宣言するのですか? 使い方がわかりません。
>>497 list<list<int> > lst1;
な。
> と > の間にスペースが要る
そもそもint hoge[M][N]でいいんじゃないか? ひょっとして。
list<list<int> > lst1; で定義しました。 後はint型の要素を入れていきたいのですが、pushでは、 「error C2664: 'std::list<_Ty>::push_front' : 1 番目の引数を 'int' から 'const std::list<_Ty> &' に変換できません。」 と出ます。 要素はどうやって入れればいいのですか?
list<list<int> > lst1; の lst1 の要素は list<int> だ。
>>499 それじゃ、要素の削除、追加大変だからだろ
2次元に連なる要素の削除、追加を高速にしたいんじゃね
>>502 それでもせめてvector<vector<int> >じゃね
もっと勉強してから来いというのが一番優しい回答ではあるまいか
どういう風にしたいのが図に書いてくれればまだ理解できそうな気がする。 答えるほうも聞くほうも。
list<list<int> >はlist<int>のlistなんだからlist<int>を入れるに決まってるだろ エラーメッセージでそっくりそのまま言われてるじゃないか 少しは自分で考えろや
いろいろ省略しますが、 #define M 10 #define N 10 main() { list<list<int> > lst1; list<int> list1; int i, j; for(i = 0;i < M;i++) { for(j = 0;j < N;j++) { list1.push_front( 値 ); } } } こんな感じでいいのですか?
もうこの人にはmap<pair<int,int>,int>が一番いいような気がしてきた
boost::multiple_arrayのドキュメントとテストとサンプルをよく見ればいいよ
>>503 vectorの要素削除、追加速度で問題なければ良いと思うが
>>507 その「こんな感じ」は、最初の質問の「みたいな」と同じ問題を抱えてると思う。
基本的に、君が頭に抱くイメージ、及びモノの表現には、隙間がありすぎる。
事の本質は、君がなにかとすっ飛ばしたがるディテールの中にあるんだよ。
きちっとした本なりサイトなりで勉強するべきだと思う。
現状だと、説明されても、説明の為の説明が必要になるだけ。
507の使い方とかどう見ても末尾にしか追加してない vectorが一番だな
追加速度気にするなら deque でいいんじゃね
>>512 構築過程だからじゃね
構築したら、ビシバシ途中要素の追加削除するんだよ
lst1.front().push_front(値); でもダメ?
コンストラクを避けるだと…
むしろC++を避けろw いやもちろん他の言語でも例外安全の概念は意識すべきだと思うよ。
メソッドの命名規則って 動詞+名詞だっけ? 名詞+動詞だっけ? どっちだっけ
知らネェよ
セッ詞+クス詞
>>482 > 例外危険性は伝搬するから(例外安全で無い関数を呼ぶ関数は例外安全では無い)
これが間違いじゃないの?
「バグってる関数を呼ぶ関数はバグってる」なんて言わないでしょ。
int main() { std::puts("Hello"); } という関数にバグがあるかないかの検証をするのに
puts() の実装まで確認する必要は無いよね?
同じように int main() { std::puts("Hello"); } という関数が例外安全かどうか検証するのに
puts() の実装まで確認する必要は無いよね?
>>522 確かに実装まで確認する必要はないな
putsは例外安全ではあり得ないからmainも例外安全ではあり得ない
例外安全でぐぐってから出直してこい
ごめん強い例外安全ではあり得ないだけだな putsでも基本保証は出来るか だからってバグと例外安全が一緒ではないけどな
522が強い例外安全でない関数を呼ぶ強い例外安全なコードを披露してくれるそうです そんなのがあったらHerb Sutterが泣いて喜ぶぞ 早く見せてくれよほらほら
527 :
522 :2008/12/03(水) 02:02:59
>>523 std::puts() には最強の例外非送出保証があるよ。そうでなければ規格違反。
528 :
522 :2008/12/03(水) 02:08:43
>>526 だれもそんなことは言ってないよ。
例外安全性の検証をするのにすべての関数呼び出しツリーをたどる必要があるという話に
異を唱えているだけ。
まぁ基本例外保証の処理に一時変数を加えて強い例外保証を与えることができたり
するんだけどね。そんなもの見せてもあたりまえすぎて誰も喜ばない。
たしかにC標準関数は例外を外に投げちゃいけないって規格に書いてあるな(17.4.4.8) throw()例外指定されてるだけかと思ってた でも中で例外を握り潰してはいけないとは書いてないな 握り潰してたら安全じゃないし、そういう関数を呼んでる関数も安全じゃない
530 :
522 :2008/12/03(水) 02:30:19
>>529 > 握り潰してたら安全じゃないし、そういう関数を呼んでる関数も安全じゃない
そうなるとどんなコードも例外安全とは言えないことになるのには、気づいてて言ってるの?
たとえば >444 にある class RAII のコンストラクタは例外安全と言えると思ってるんだけど、
違うの?
要は、例外安全性はあるコード辺について評価されるものだと思ってるんだけど、
実行結果に対して評価されるものだと思ってる人が多いってことなのかな?
握りつぶしているってことは 例外を処理したってことで 例外安全なんじゃ?
>>531 握りつぶした結果、変なことが起こってるかもしれないっていいたいんだろ。きっと
でもそんなの関係ねぇ
でもそんなの関係ねぇ
例外を握り潰してる関数はcatch節や例外に伴って破棄される可能性のあるクラスのデストラクタでは呼べない 呼んでたら二重例外で未定義動作になる
>>536 断定口調で嘘を書くな。
二重例外がまずいのは、例外に伴うスタック巻き戻し中に実行されたデストラクタが
例外を「送出する」場合。中で握りつぶしてれば握りつぶしたなりの動作をする。また、
その場合でも未定義動作になるんじゃなくて terminate() に直行することになっている。
規格内の該当箇所は 15.5.1 "The terminate() function" ね。あと、 catch 内でも
同様に、握りつぶせばそのとおりに動作する。
なんなんだ昨日からの流れは。10年も前になろうかという間違い混じりの記事を
いまさら貼るやつまでいるし。 C++ の例外を誤解させようという組織でも活動してるのか?
basic/strong guaranteeでいうbasic invariantsが何であるかを 構文解析だけで特定できるのだろうか? あと「例外を投げ得るコードを含まない」に合致するのは no throw guaranteeの一部だけなのではないか
>>538 何言ってんのかわからん。
静的解析で例外安全性を検証したい、とかいう話?
yes
>>538 とりあえず invariants が何かというのは既存のコードを解析するだけじゃ無理なのは
明白だろう。明示的な記述の追加が必要だと思う。いくつかの言語がサポートしている
DbC に関する機能を真似ることになるだろう。ただし invariants の評価を静的に
行うことができるかどうかも大きな問題になるはず。
例外安全性と言えば、これに加えてリソースリークの有無を判別する必要もある。
これについてもリソースの確保・解放を行うコードを何か統一された書式で記述しないと
無理だろう。
さらに strong guarantee の検証には、観測しうる状態が変化しないことを確かめる
必要がある。グローバル変数や volatile 変数へのアクセスを考えると、これについても
何か追加の情報を与えてやらないと機械的に判別できない。
現状から考えるとあまりにも非現実的と言うしかない。ドキュメント化された
インターフェースの仕様から invariants やリソース確保・解放や副作用に関する
情報を集められる人間が検証する以外に考えられない。
最後の no throw guarantee についての話はあたりまえで、内部に例外を投げうる
コードを含んでいても、外部に漏らさないように補足して処理できていれば
no throw guarantee は達成できる。
オープンソースのC++のコードで、最近のちゃんとしたC++で書かれているものって ありますか? 「ちゃんとした」ってのは曖昧ですが、勉強のために読みたいという感じなので 主観でかまいません。 たとえば話題に上ってる例外安全とか。
>>542 デザインパターンも含め、スタンダードで模範的なコードか?
優等生ベンダが保有するソースじゃないと、C/C++でそういうのは
少ないと思うぞw
boostでは駄目?
>544 勉強のためには変態的すぎるんじゃないかと思うんだ。
C++が変態だから、しょうがないよ
boostにはシンプルなのから変態的なものまで色々あるよ
boost の中では何がお勧めでしょう? shared_ptr とか?
boostなんて見ない方がいい あんなもの真似しちゃダメだ
progress_barがオススメ
boost::preprocessorおすすめ
やめろぉおおおおおおおおおおお
boost::date_timeおすすめ
お前らそんなboostのなかでもアレげな奴紹介するなよw boost::mplマジお勧め
boost::lambdaとか
boost::spiritだろ
boostの乱数は普通に勉強になる。乱数の
Boost Graph Libraryに決まってるだろ
program_optionsの放置されようはひどすぎ。 ワイド文字がまともに使えねーし。 所詮一文字一バイトの世界で生きてる南蛮人の書いたコードなんだなと。
BOOTSまじオススメ
boost::optionalマジお勧め。
boost は互換性を保つという事がいかに大変かという教材になるっしょ。 char で new して placement new する時に いかにしてアラインメントを揃えるかとか。
動的生成vector用のスマートポインタは何を使ってますか?
とりあえずスマートポインタは置いといて vectorを別のコンテナに突っ込むかな
それって、どうするんですか?
とりあえず日本語でおk
vectorの要素にできるスマートポインタという意味ならshared_ptr。 vectorを指すスマートポインタという意味なら、状況に応じて適切なものを選ぶ。 vectorだからといって特別扱いする必要はない。
void file_read_test(const char* filename) { std::vector<char> temp; std::ifstream ifs( filename, std::ios::binary ); std::copy( std::istreambuf_iterator< char >( ifs ), std::istreambuf_iterator< char >(), std::back_inserter(temp) ); std::cout << "read size =" << temp.size() << std::endl; } ここのtempを他のところで処理したいんです。 そこで動的にこのvectorを生成し、そのdeteteをスマートポインタに任せたら良いんじゃないかと。 ただ、ポインタでアクセスが->になるのが不便なんですが
ケースバイケースだが、呼び出し側から渡してもらうのも検討してみたら?
>>568 そのtempがそれほど大きくないならそのまま返しちゃっても高が知れているけどね。
http://d.hatena.ne.jp/tetsuarossa/20070307/p1 Windowsに限った方法ではあるが、俺はこのサイトで、例外処理の勉強をさせてもらった
このようなクラスに改造しているので、stlの例外も、捕まえることができる。
class Exception : public std::exception
{
protected:
std::vector<char> msg_;
public:
/// コンストラクタ
Exception();
Exception(const char *fmt, ...);
/// 構造化例外処理コンストラクタ
Exception(PEXCEPTION_POINTERS pInfo);
/// デストラクタ
virtual ~Exception(){}
/// エラー内容の取得
const char* what() const;
/// 構造化例外をC++の例外に変換
static void set_transrator();
};
ほほう。それで?
windowsに限ったってより・・・・・・
C++はコンパイラとランタイムの手抜きを補うための尻拭きがマンドクセー もうC#とCでいいよ
>>572 >>573 >>571 です
先に掲示した、サイトの作者が意図したところは、「C++の例外処理とWindowsの構造化例外処理が同時に使えない。」ので
全ての例外をキャッチ出来るクラスを作って使っている。更に俺は猿真似して
stlの例外もキャッチさせたくて、改造を施した。
発案した、先のHPの作者は、賢いし、ヒントを与えてくれて感謝している。
俺の作ったクラスも、思い通りの振る舞いをしてくれているので、とても役立っている。
>>571 ,575
「stlの例外を捕まえる」の意味がわからん。
そのせいか、リンク先の記事と比べて改良されてるように見えないんだが。
改造されてるのはわかるけど。「キャッチするクラス」も合わせて意味不明だな。
クラスが例外をキャッチするわけじゃないだろうに。
「Windows 構造化例外処理を C++ 例外に変換している」とだけ言えば何も
おかしなことは無いんだが。
で、その例外トランスレータの使い方は >516 のコラムの最後、 2000 年発表の
「例外処理、第 17 部」にずっと先に載ってるものなので、発案したのが
その人なわけじゃないと思うよ。どうでもいいけどね。
自分で作ったコンテナもどきでイテレータを実装したいんだけど、 これって、やっぱり STL で提供されているイテレータの流儀にのっとって (std::iteratorを継承するとか) 作ったほうがメリットあるのかな? それとも、適当にシグネチャを合わせておけば十分?
>>577 自分しか使わないんならエラーが出るたびに不足してるメンバを調べて足していく
方向でもいいかもしれない。ごく狭い範囲で基本的なメンバしか使われないなら、
こっちのほうが早いかも。
汎用的に使いたいとかエラーが出るたびに調べるのが嫌なら、最初からイテレータの
要件をひととおり揃えておいたほうがいい。
どのみち足りないメンバを足す時には要件を見ることになるわけだから、やっぱり
後者がおすすめ。
>>571 コピー時に多重例外でterminate
>>569-570 どうもありがとうございます。
ファイルサイズが大きい時で10MBになるんで
return std::vector<char> temp; じゃなく
void file_read_test(const char* filename, std::vector<char>& vect)
にすることにしました。
enum OPPAI { hinnyu = 0, hutsuu, kyonyu }; static const unsigned int OPPAI_N = 3; void gen_girl(OPPAI oppai); void gen_all_girl(OPPAI oppai) { for (unsigned int i=0; i<OPPAI_N; ++i) { gen_girl( static_cast<OPPAI> (i) ); } } こんな風にenum型使ったがためにキャストする機会があると なんかenum使うべきじゃなかったんじゃないかと思っちゃうんだけど、 こういうときって typedef unsigned int OPPAI; const OPPAI hinnnyu = 0; const OPPAI hutsuu = 1; const OPPAI kyonyu = 2; の方がデザイン的にベターなのかしら? どうでもいいことなんだろうけど、気になって夜も眠れない。 誰か教えてくださいm(__)m
↑あ、gen_all_girlの引数はいらないね。ごめん
enumを無名にはしたくない状況?
OPPAIでありつつ(i)とはこれいかに
enum { chinko } gen_girl(chinko); これは困るから型付けはしたいとです・・・。
>>582 キャストが嫌なら、そういう操作はなるべく enum 提供側で用意してあげればいいんだよ。
たとえば class oppai_iterator 作るとか。
そこまでする必要があるかどうかは疑問だけどね。
演算子多重定義でやってみた。 enum OPPAI { hinnyu = 0, hutsuu, kyonyu }; inline OPPAI& operator ++(OPPAI& o) { return o = static_cast<OPPAI>(o + 1); } inline OPPAI operator ++(OPPAI& o, int) { OPPAI r = o; ++o; return r; } static const OPPAI OPPAI_N = static_cast<OPPAI>(3); void gen_all_girl() { for (OPPAI i=static_cast<OPPAI>(0); i < OPPAI_N; ++i) { gen_girl(i); } }
数学の組み合わせ(combination)の実装のことなんですが、 「n個のアイテムの中からk個のアイテムを選ぶ」はどうやって実装するのが良いのでしょうか? 考えたのは、 ・0からn-1までの乱数をk回取得して、同じ数字が出たら乱数を取得しなおす方法。 ・コンテナにアイテムのインデックスを入れて、1回選ぶ毎に選んだアイテムをコンテナから取り除く方法。 前者は、乱数の精度に影響がでそうで良くない気がします。 後者は、コンテナの構築とコンテナからアイテムを取り除くのにコストがかかるのが嫌な感じです。 nが大きく、何度も繰り返し実行される部分なので、高速なのがいいのですが、うまい実装はないですか?
nが大きいなら前者で良いじゃない。
>>590 確かに同じ数字を引く確率は低く、影響は気にしなくていいのかもしれません。
問題はシンプルなのに、実装にすっきりしない感が残るのですが、仕方ないんですかねぇ・・。
取り出すアイテムが完全にランダムでいいなら前者でいいんじゃないかね ある程度コントロールしたいんなら後者のほうがやりやすそうな気はする
ちょっと気になったんで聞くだけだけど、 前者の「同じ数字が出たら」っていうのは、例えばコンテナに既に出た数字を詰めたりして判断するんだよね? で、後者の「1回選ぶ」っていうのは乱数で選ぶの?
インデックスを詰めたコンテナをrandom_shuffleして先頭からk個選択して出力先にコピーとか そんな感じじゃないかな
n, k の大きさによって、どうすべきかが大きく変わりそうだ。
>>594 >>589 の文に不備がありました。
×「n個のアイテムの中からk個のアイテムを選ぶ」
○「n個のアイテムの中からk個のアイテムをランダムに選ぶ」
前者についてはその通りです。
同じ数字は取り除いて、コンテナの要素数がkになるまで乱数を詰めます。
>>595 ,596
kは10以下で、nは1000以上も想定しています。
>kは10以下で、nは1000以上も想定しています。 なら >・0からn-1までの乱数をk回取得して、同じ数字が出たら乱数を取得しなおす方法。 が、けっきょく一番じゃありませんか。
>>599 実際には、乱数の取得しなおしは必要なくて、ちょうどk回の乱数の取得で十分。
vector<T> v;
int n = static_cast<int>(v.size());
for (int i = 0; i < k; ++i) {
int j = random_int(i, n); // [i, n) の範囲の整数をランダムで取得する
swap(v[i], v[j]);
}
// v[0] ... v[k-1] に選択された要素が入る
>>595 の言っている random_shuffle とほぼ同等だけど、全体をシャッフルするんじゃなくて
最初のk個のシャッフルで十分であるところがポイント。
1000個ぐらいなら、vを0..999で埋めておいて、 v[0..k-1]がインデックス配列になるというのでもいいか。
603 :
デフォルトの名無しさん :2008/12/10(水) 00:06:33
=== hello.cpp === #include <iostream.h> main() { cout << "Hello World\n"; return 0; } ================== $ gcc hello.cpp 参考書を見ながら入門しようと思ったのですが コンパイルできませんでした。 OSはLinuxでgcc-4.1.2です。
604 :
デフォルトの名無しさん :2008/12/10(水) 00:08:36
=== hello.cpp === #include <iostream.h> using namespace std; main() { cout << "Hello World\n"; return 0; } ==================
$ g++ hello.cpp
#include <iostream> int main() { std::cout << "Hello World\n"; return 0; } C++では古い入門書で勉強するのはやめたほうがいい それ以前の問題も含んでるけど
#include <iostream>
608 :
デフォルトの名無しさん :2008/12/10(水) 00:19:53
#include <iostream> int main() { std::cout << "Hello World" << std::endl; return 0; } $ g++ hello.cpp 出来ちゃいました
609 :
デフォルトの名無しさん :2008/12/10(水) 00:22:51
endl付けてないと改行が二つほど入るね
なんのこっちゃ。
611 :
あ :2008/12/10(水) 18:09:52
名簿管理プログラム ・データの一覧表示 ・キーボードからのデータ追加 ・名前によるデータ検索 ・学生番号によるデータの整列(昇順) ・ファイルからデータ入力 ・ファイルへデータ出力 ただし単方向の直結リストを使わなければならない。 教えてください。。
>>611 宿題は宿題スレに、丸投げしないということなら初心者スレに。
613 :
デフォルトの名無しさん :2008/12/10(水) 18:20:38
むずい・・・
C++に限ったことではないですが、 C++でスレッドセーフという場合は、 一つのインスタンスにおいてセーフにするべきか、 複数のインスタンスにおいてセーフにするべきかが、 よくわかっていません。 これってどうなんでしょう? 複数のインスタンスにおいてセーフなものを作るのって大変な気がします。 また、この辺に関していい例がありましたら、URL等を教えてもらえると助かります。
なるほど。
パーサは複数のインスタンスでスレッドセーフなのですね。
http://naoyuki.hirayama.googlepages.com/caper_more.html (逆に、1つのインスタンスではスレッドセーフではない? 少なくとも上のURLにはそう書いてあります。)
今はデータベースを作っているのですが、
その場合は複数のインスタンスにおけるスレッドセーフティを実現するのが
難しいと思ってますが、どうなんでしょうか?
(細かい話になってしまいますが、
クラスのメンバとして、staticなpthreadオブジェクトを持っていると、
他のデータベースに対するインスタンスに対しても同じpthreadオブジェクトが使われてしまうなど。)
それはそもそもstaticなのがまずいのでは 異なるデータベースに対して異なるスレッドを使いたいのなら、 staticではなくデータベースインスタンスのメンバであるべきだろう
俺がイメージするのはシングルトンとプロキシを使った解だけど もうちょっと具体的に状況を説明して欲しい
色々教えて頂きありがとうございます。 今の状況を説明します。( 以下、説明のためのコードです。) class DataBase { // constructor and destuctor bool put(/* key and value */) { pthread_rwlock_wrlock(&rwlock_); // update the database pthread_rwlock_unlock(&rwlock_); } bool get(/* key and value */) { pthread_rwlock_rdlock(&rwlock_); // some retrieval action from the database pthread_rwlock_unlock(&rwlock_); } private: pthrad_rwlock_t rwlock_; }; このような感じで、今は1インスタンスにおけるスレッドセーフを実現しています。 これを複数インスタンスでもスレッドセーフにしたいのですが、 どうやっていいのかを悩んでいます。
>>619 各インスタンスで共通に参照するpthread_rwlock_tオブジェクトをプロセス内に置いて
利用すれば、複数インスタンスによるアクセスも大丈夫ではないでしょうか。
pthread_rwlock_tオブジェクトをstaticにするということでしょうか? そうすると、1プロセス内の複数のスレッドが別々のデータベースを開くと問題になると思いますが、 いかがでしょうか? 何か勘違いしてるようでしたら、ご指摘ください。
>>621 一般に、同じクラスから生成した各インスタンスが、それぞれ全く別々のデーターベースをアクセス
するような設計には至らないでしょうが、もしそのようなケースであれば、普通にデーターベースの
参照と更新において競合関係があり、排他制御をしなければならないインスタンス間だけでロックの
共通をすれば問題ないでしょう。
しかしそんなクラスは作れない(作れたとしてもトリッキーで無駄に時間を費やす)場合が多いので、
データーベースへのアクセス単位でクラスを分けて、static属性のクラス内メンバオブジェクトにします。
>>619 そのコードで何が問題なの?
「複数インスタンスでスレッドセーフ」とか意味わかんないから、具体的な問題を書いて欲しい。
>>622 ありがとうございます。
参考にさせていただきます。
>>623 説明不足ですいません。
上のコードだと、以下のパターン1はOKですが、パターン2がNGなので、
両方ともいける良い方法はないかと考えているところです。
* パターン1
---
DataBase db;
db.open(/**/);
// thread作成
// 各threadはdbを共有 (dbへのポインタを各スレッドに渡す)
---
* パターン2
---
// thread作成 (下記のprocを処理するようにする)
// 各スレッドが処理する関数
void proc(void *p)
{
DataBase db;
db.open(/**/); // 各スレッドは同じデータベースをopen
// なんか処理
}
---
>>625 オープンを失敗させればいいんじゃない。
すでに開かれていますとかなんとか言って。
クラスAをクラスB、Cが継承しています。 B、Cにほぼ同じ処理があるのでAにその処理を書きたいのですが、 if(dynamic_cast<B*>(p))... と if(dynamic_cast<C*>(p)).. の違いなのです。 thisから型を得て、それでキャストできればAに書くだけで済むのにと思っているのですが、 そういったことは出来るのでしょうか?
if (typeid(p) == typeid(this)) こんな感じ?
Aを継承するAImplクラスを作ってそこに実装を書き、 BとCはAImplを継承するって形にするのは駄目?
630 :
627 :2008/12/11(木) 16:53:53
>>628 確かにそんな感じならAに書けますね。
ありがとうございます。
ただ、書いてなくて申し訳ないのですが、
p2 = (B*)p; 、 p2 = (C*)p; と言った処理もあって、
これもthisを使って p2 = (thisの型)p; のようにできますか?
>>629 B、Cもそれぞれ派生クラスを持っていて、
その処理から返ってくるポインタがBならBの派生、CならCの派生かそうじゃないかで処理を分岐させています。
だからAImplを作っても結局はAに書くのと変わらないです。
分かり難くてごめんなさい。
p2の型ってどうなってるの?
> p2 = (thisの型)p; それをどう使うつもり? BあるいはCにキャストしたいということは、 BまたはCに固有の、共通でないメンバを使いたいということだ 共通のコードで書けるはずないと思うのだけど 共通のメンバならAに持ってくればいいだけだし
>>631-632 p2の型はB*、C*です。
よく考えると
>>632 さんの言うとおりです。
すみませんでした。
いろいろ変更すれば
>>628 の書き方でいけそうな気がしてきました。
皆さんありがとうございました。
>>625 パターン 2 の問題を解決する自然な方法がパターン 1 ということだろ。
無関係なオブジェクト同士が非同期に動いて大丈夫なわけがない。
どうにかして情報(たとえば排他オブジェクト)を共有する必要がある。
DataBase インスタンス同士を明示的に繋ぐコードを書きたくないなら
static な何かで繋げるほか無い。
そのパターン 1 で何か不満なのか?
635 :
デフォルトの名無しさん :2008/12/12(金) 03:53:31
636 :
デフォルトの名無しさん :2008/12/12(金) 13:15:20
http://www.open-std.org/jtc1/sc22/wg21/ > News 2008-12-12: The 2008-12 mailing is available
> News 2008-12-12: The C++ Standard Core Language Issues List (Revision 60) is available
> News 2008-12-12: The C++ Standard Library Issues List (Revision 61) is available
マジで0xがコンパイラ標準になるのは老後の楽しみになるかもorz
Zip32.dllを使用して、Zipファイルを作成するプログラムを作成しなければ、なりません。 とりあえず、ネットで色々調べた結果、以下の流れで関数を発行していけば可能ということはわかりました。 ZpInit→ZpSetOption→ZpArchive しかし、それ以上の詳しい情報が全くわかりません。 なるべくなら日本語で詳しく説明されているサイトやドキュメント等はないでしょうか?
スレ違いだボケ、どっか他所に逝けって旨を 非常にソフトなテイストで且つ皮肉たっぷりに伝えたいんだが、 自分にそんな文才がないことが非常に悔やまれる。
>>638 zpinitをグーグルで検索してヒットしたページにサンプルが置いてあるけど、それでは何かご不満?
残念ながら、私にはそれ以上に詳しい説明なんてものが存在し得るとは思えないのですが。
まぁ、どうしてもこれ以上話を続けたいと言うのでしたら環境依存スレでどうぞ。
あー、その際はどこまで理解できたかを書いたほうがいいかもしれませんね。
案外、日本語の勉強から始めないといけないかも知れませんし。
わからないならレスしないでくださいウザいです
>>641 おいばかやめろ
Win32APIスレへおかえりください^^
WIN32APIスレ。。 戻ってこなければどこのスレいったっていいんだけどさ。 どこにいったって同じ事聞いて、同じ事かえすんでしょ? ダムすれでもいいんじゃね?
644 :
638 :2008/12/13(土) 10:03:48
スレ違いの質問をしてしまったようで、申し訳ありませんでした。 C++で作成使用としていたため、ここに書き込んでしまっていました。
645 :
638 :2008/12/13(土) 10:06:11
あ、一応誤解されたままは嫌なので、
>>641 は私ではないです。
646 :
644 :2008/12/13(土) 11:24:08
ローカルクラスなんてのが、あったんだね・・・知らなかった 何処までC++って奥が深いんだろう と、C++の淵に佇む void Fun() { class Lcal { ...メンバー変数... ...メンバー関数定義... }; Localを使用するコード... }
訂正 void Fun() { class Local { ...メンバー変数... ...メンバー関数定義... }; Localを使用するコード... }
動的にメモリを確保してくれるitoa見たいな関数ってありますか?
std::ostrstream
ostrstreamは古いからostringstream使え。 boostならlexical_castとか。
関数ローカルクラスってテンプレートパラメータに渡せない っていう制限があった気がする それで一気に萎えた記憶がある
そんなあなたにC++0x 関数ローカルクラスだろうと無名クラスだろうと何でもテンプレートに渡せるぞ!
0xはsyntaxが果てしなく汚いhaskellみたいな感じになってて吹く
>>652 そんなあなたにD
関数ローカルクラスだろうと関数リテラルだろうと
メンバメソッドだろうと何でもテンプレートに渡せるぞ!
656 :
デフォルトの名無しさん :2008/12/13(土) 16:28:03
ATLスレかこっちか迷ったんだがプロが多いこっちに。 ATL::CSimpleMap のキーを順に全部取得する場合ってどうやってやってる? インデックスで対象のキーを拾えればいいんだけど、できないっぽい。 GetStartPosition/GetNext 使わなきゃむりぽ?
657 :
656 :2008/12/13(土) 16:54:39
ごめん、Simple の方はそんなのなかった。スマソ。
スレ違いです。
659 :
デフォルトの名無しさん :2008/12/13(土) 17:08:33
たすけてください>< 関数Aに書かれている_tfopen_sは成功(戻り値:0)なのに、 関数Bに書かれている_tfopen_sは失敗(戻り値:EBUSY)するんです。 引数はともに全く同じで、_tfopen_sの前や処理後には必ず_fcloseallしてます。 なんで2回目は失敗するんでしょうか・・・
660 :
デフォルトの名無しさん :2008/12/13(土) 17:18:45
それだけじゃ分からん 引数が実は違う 実はcloseしてなかった どっかでスタック破壊してる 等々いくらでも原因が・・・
661 :
デフォルトの名無しさん :2008/12/13(土) 17:22:53
>>660 そうですよね…すみません。
引数1は単純なFILE*で、モードは"r"、パスはフルパスで正しい。
呼ぶ前に_fcloseall()しても閉じ忘れとか考えられます?
EBUSYってどっかで開かれてますよー状態ですよね。
あとはメモリ破壊をチェックか…長旅になりそうです><
ソースみせれば早いと思うよ
663 :
659 :2008/12/13(土) 17:51:07
>>662 けっこうでかいソースだけど、とりあえず端折って・・・
DWORD CClass1::hogeFunc(ATL::CString* szFormatfile){
// Open file
FILE *filebuf;
DWORD dwRet;
_fcloseall();
dwRet = _tfopen_s(&filebuf, (LPCTSTR)szFormatfile , _T("r"));
/* なにやらな処理 */
_fcloseall();
}
こんな感じです。
dwRet に 16 が返ります。
そもそも_fcloseall()を使うのってどうなのって思うんだが。
CString*をLPCTSTRにキャストするって頭大丈夫か?
他で複数のファイルハンドル使ってたらドツボにはまるし 普通に閉じた方がいいと思うよ
"他で複数の" じゃなくて "他で" だた
668 :
659 :2008/12/13(土) 18:32:11
>>664 ,666
fclose でもだめですたorz でもこれからは fclose にします
>>665 読んだとき、「operator LPCTSTRがあるだろーが」と思ってしまったんですが、
よく見直してみたら「CString::operator LPCTSTR を使った char* を指定する動き」じゃなくて
「CString* を LPCTSTR と見做す動きに」になってしまっていたorz
dwRet = _tfopen_s(&filebuf, (LPCTSTR)szFormatfile , _T("r"));
を
dwRet = _tfopen_s(&filebuf, (LPCTSTR)(*szFormatfile) , _T("r"));
に直したらうまくいきました!
本当にありがとうございました。反省して精進します。
そこで明示的にキャストする必要ってあるのか?
キャストするなら static_cast にするべきかもな。
いや、キャスト要らないだろ。
#include <iostream> using namespace std; 上のほうでusing使うなみたいなこと書かれてたけど、どうして?
>672 つ “More Exceptional C++” 詳しい解説があったから、確認してみ。 大雑把に言うと、「名前空間を汚染する/順番依存な問題を発生するから使う場所に気を付けないとダメ」つうこと。
上で書いてあるのは、とにかく何も考えずにおまじないで「using namespace std;」と書けと言ってる クソ入門本がいっぱいあるから
>>670 は、
「余計なキャストしたからこそ、ケアレスミスを見逃した」
ってことを言いたいんじゃねえのかなと思った。
677 :
デフォルトの名無しさん :2008/12/14(日) 02:44:58
0x03A40000 4d 5a 90 00 03 00 .... で、 DWORD* dwOffset = 0x03A40000; したときの、 *(dwOffset + 0x00000002) の値って、0x00030090 になるよね!?(もちろんIA32) なぜか 0x00000004 になるorz
*((char*)dwOffset + 0x00000002)
そらそうよ *(dwOffset + 2) = dwOffset[2] だもん それやるなら BYTE *dwOffset=0x03A40000; *(DWORD*)(dwOffset + 2) みたいな感じでは 規格見てないけどw
>>677 とりあえずこのスレ的には未定義動作と言っておこう。
実際、アライメント違反で CPU 例外が発生する環境もあるし。
あ、 "IA32" なら大丈夫なんだっけ?
>>677 dwOffset + 2 だと8バイト移動するんじゃないか?
正解
683 :
677 :2008/12/14(日) 03:43:18
ΩΩ Ω<ぱ、ぱんだってー!? それは、例えば DWORD に 0x0 が入っているとして、 DWORD + 2 っていうのは、0x0 + 0x2 = 0x2 ではなく、 0x2 + sizeof(DWORD) * 2 = 0xA っていう事か!? ポインタ変数に対し + 演算子を使う時は単純合計と考えてはいけないって事なのか!?
>>683 いや、ポインタとその内部表現であるアドレスとを混同しなければ
その結果で十分単純だから。
生のアドレスで考えるから混乱するんだよ。 DWORD a[2]; DWORD p = &a[0]; で p + 1 は &a[1] になるってだけの話だ。
ポインタ演算の超基本なんで Cから勉強し直すことをお勧めする
-- それは、例えば DWORD に 0x0 が入っているとして、 DWORD + 2 っていうのは、0x0 + 0x2 = 0x2 ではなく、 0x2 + sizeof(DWORD) * 2 = 0xA っていう事か!? -- だめだこいつ、落ち着きがなさ過ぎる。
689 :
672 :2008/12/14(日) 08:03:49
あまり流行っていないがusing宣言で使うものだけにする方がベター using std::vector; とか。
>>677 *(dwOffset + 0x00000002)
↓
↓コンパイル時の解釈
↓
*((DWORD*)((BYTE*)dwOffset + sizeof(DWORD) * 0x00000002))
dllファイルの中の関数を使ってtry文を書いたんですけど 構文エラーがでてしまいよくわからないので dllファイルの関数の使い方を教えてください
ヘッダをインクルードして .lib をリンクすれば あとは普通の関数と同じように使える。
>>693 すいません.libのリンクはどうやればいいのですか?
さすがにスレ違いだし、少しは調べてから聞けよ
すいません.lib探したんですけど見当りませんでした dllだけの場合最初に#using <XXX.dll> だけでいいんですか?
>676 言葉が足りなかった。 キャストをつける必要はないけど、キャストをつけるんだったら static_cast にしておけば 誤りには気づいたかもね、ぐらい。 暗黙のうちに変換されるものについてはキャストつけた方が呼び出しが明確になるという 考え方もあるかと思って。
>>696 その辺はもうC++の範囲外だから、適切なスレでやってくれ。
>>696 どのDLLが使いたいのか隠さずに言ってみろよ。
>>696 VS2008スレが妥当かな。ここは言語のスレだからすれ違いだ。
DLLはいろいろ種類があるから何のDLLかも移動先に書いとけ。
DLL だけしか提供されてないなら コンストラクタで LoadLibrary と GetProcAddress をして デストラクタで FreeLibrary するラッパクラスを作っとけ。
Baseというクラスを継承したDer1、Der2といったクラスがあり、 関数に対しDer1,Der2のポインタを、基底クラスであるBaseのポインタを用いて受け渡しています。 現在は、関数内部では、受け渡せれたクラスがDer1なのか、Der2なのかをdynamic_castで判定し、 Der1であったばあいはvector<Base*>に対し、push_back(new Der1) Der2であったばあいはpush_back(new Der2) といった処理を行っているのですが、この方法であると、dynamic_castを多用するのでパフォーマンスが心配なのと、 派生クラスを増やすとpush_backを行う関数の書き換えも必要となるといった点で、問題があるかなと思っています。 そこで、Baseクラスに純粋仮想関数としてgetInstance()を持たせ、各派生関数で Base* Der1::getInstance(){return new Der1;}とし、 push_back(p->getInstance()) することも考えたのですが、getInstanceというとsingletonパターンみたいに見えるので、 可読性が落ちるのでやめたほうがいいよ といった意見もありました。 今回のように、基底クラスのポインタを用いて渡されたオブジェクトの型が「new 型」するためだけに必要な場合は どのような手法を用いるのが最適なんでしょうか?
> 基底クラスのポインタを用いて渡されたオブジェクトの型が「new 型」するためだけに必要 AbstractFactory?
ちがう、Factory Methodだ
>>702 受け取ったオブジェクトを vector に入れるんじゃなくて、同じ型の
デフォルトコンストラクタで生成したオブジェクトを入れるの?
なんかおかしくない?
>>702 とりあえず関数名はgetInstanceからcloneあたりに変えたほうがいいかな。
cloneじゃなくて「自分と同じクラスのデフォルトコンストラクタで生成されたオブジェクト」だろ 見たことないけど名前どうするのがいいんだろうな、createDefaultとか? そのデフォルト生成のオブジェクトにセマンティックな意味があるならその名前を付けた方がいい 例えば空のレコードならcreateEmptyRecordとか
ふつう newInstance() じゃん。
命名スレかと思った
711 :
702 :2008/12/14(日) 23:15:40
回答ありがとうございます。 やはり関数名がgetInstance()では混乱をきたしそうなので少し考える必要があるみたいですね。 上であげた例のような完全にデフォルトのコンストラクタを呼ぶ場合は newInstance()あたりが良いのかなと思います。 また、実際に利用する際は、デフォルトをそのままpush_back()するだけではなく、 例えばpushObject(Base *obj,int ID) といったように付加情報を付ける場合も多いので、 そういった場合は Base *nObj = obj->newInstance(); nObj->setID(ID); push_back(nObj); といった形をとり、より複雑にオブジェクトを構築する必要がある場合は FactoryMethodの利用も考えたいと思います。
eastlでヤフれ
質問です。 自分で確保したメモリ上のクラスをコピーするにはどういったコピーをすればいいのでしょうか。 たとえばstd::vectorをコピーするときってどうやって内部を複製しているのでしょうか。 コピーコントラクタがいいのか、イコールがいいのか。 最悪memcpyって手もありますけど、これは気持ち悪いからしたくないです。 どなたかご教授ください。
定石としてはコピーコンストラクタと代入演算子を両方作る 中身は「メンバをひとつずつコピーする」だけ (コピーコンストラクタの場合はメンバ初期化子でやるのがいい) これ守っていればどんなクラスを作ろうと同じやり方で済むし 引数に渡しても戻り値でもらっても他クラスのメンバにしても ローカル変数で実体作られても例外で投げられても問題ないし 何よりstd::vectorなんかに突っ込むときに余計な心配がいらない memcpyが気持ち悪いと感じているのは感覚として正しい でも理屈を理解したほうがいい
自分で確保したメモリ上って表現が気になる、というかよく分からないから詳しく。
>>715-716 レス感謝。えぇっと。書き方悪かったです。
コンテナの方を再発明してるんですが、コピーするときの方法を知りたかったのです。
ってこれ最初にかいてれば・・・。すいません。
自分で確保って言うのは、クラス配列を自分でnewしたときの事です。
newして確保時にコンストラクタが動いてそこからコピーする2重苦は避けられないのでしょうか??
お願いします。
えーっと
>>717 です。妥協しました。
一応コピーコンストラクタで解決ってことにします。
セオリーの代入とコピーコンストラクタを同時に実装するというのはコンテナはコピー方法を選ばないと解釈しました。
そういう感じで回答ありがとうございました。抜けます〜。
>>712 STLとか、わけのわからんくくりで考えてるうちは一生答えは出ないだろうよ。
せっかく部品に分かれてるんだから、問題ないものは使う、問題があれば使わない、と
個別に考えないと何も見えてこない。
>>718 > 自分で確保って言うのは、クラス配列を自分でnewしたときの事です。
> newして確保時にコンストラクタが動いてそこからコピーする2重苦は避けられないのでしょうか??
vectorなんかの実装見れば分かるけど、allocatorで領域だけ確保した後placement newしてる。
template< uint_t u > struct c_t { uint_t m; c_t() : m(u){} }; const uint_t u = 0; c_t< u > f0; uint_t xx = 3; *const_cast< uint_t * >(&u) = xx; c_t< u > f1; stream << _T("c_t< 0 > = ") << f0.m << std::endl; stream << _T("c_t< 3 > = ") << f1.m << std::endl; 結果: c_t< 0 > = 0 c_t< 3 > = 0 これってバグってると思う?
コンパイル時と実行時がごっちゃになってないか
const宣言した定数にconst_castで無理矢理代入するのは未定義動作
テンプレートで無駄に複雑にしてるけど本質はこれだろ int main(){ const int i = 0; std::cout << i << ","; *const_cast<int*>(&i) = 3; std::cout << i << std::endl; } このプログラムは「0,3」を表示しても「0,0」を表示しても「0,924877096」を表示してもよい 何も表示せずPCを炎上させても良い 要するに未定義だ
関数内のstatic const はリテラル扱いで const は、読み出しオンリーのauto変数扱いだと 思ってたけど違うのか const uint_t u が templateのパラメータに使えてしまうのが、そもそもおかしいのかと思ったので
初期化されているconst変数は、全てコンパイル時定数として扱われる。
うそ乙
>>728 static じゃないconst メンバ変数は?
>>729 それをどうやってコンパイル時に"初期化されている"状態にするんだ?
>>726 については規格の5.19に書いてあるよ
>>730 726 には「コンパイル時に」とは書いて無かったから嘘だと突っ込まれてるんだろ。
規格の 5.19 に「初期化されているconst変数は、全て」なんて記述も無い。
>>724 volatile constにするとどうなる? それでも非定義?
どうでもいいが非定義なんていう未知の用語を 使いなさんな。
>>720 placement newてそういう風につかえるんですね。新発見です。
volatile const だとどうなるんだろう・・・。 大丈夫そうなイメージはあるが。
const-qualified type なことには変わらないから未定義だと思う。 じゃ、volatile const にどんな意味があるのかと言えば、読み込み専用のメモリマップド I/O とかだったら 有り得るような気がする。
volatile constのポインタならもちろん意味あるけど プログラムの管理領域にvolatile constの変数取って意味あるかなぁ…
リンカが特定の領域に割り当ててくれるという状況なら存在意義があると思う。
MFCのシングルドキュメントでゲームを作っているのですが、効果音の挿入方法を教えてください。
741 :
デフォルトの名無しさん :2008/12/18(木) 04:06:17
シフトってエンディアンの影響受ける?
いいえ
unionを使わない限りは、影響無いと思うぜ
744 :
デフォルトの名無しさん :2008/12/18(木) 04:55:47
ありがと。
>>736 ああそうか。
そのプログラムには書き込み禁止だけど
別な所で値が変更されるような場合もあるだろうしな。
解の公式を加算減算だけで表したいんだがどういうプログラムになるのかわからない・・・
何の解の公式だよ
>>746 まず、解の公式を加算減算だけで表した数式を書くのが先では?
コンピュータというのは、人がやったら物凄い時間がかかるのを単に高速にやってくれる
だけのものなんだから。自分が分からないものを自動的にはやってくれないよ。
ニュートン法を使いなさい
bad_allocがcatchされません。コンパイラはg++です。どうしてでしょうか。 #include <iostream> #include <new> using namespace std; int main() { double *p; unsigned long int count = 0; cout << "double一個のサイズは" << sizeof(double) << endl << endl; for (;;) { try { p = new double; count++; } catch(bad_alloc ba) { cout << "error:"<< count << "回目に起こった" << endl; return 1; } } cout << "outside of loop" << endl; return 0; }
>>750 1が返らないかチェックした?
bad_alloc がthrowされた時点でメモリが不足してるから標準出力されないと予想。
最初にメモリ確保しておいてcatchの先頭でdeleteして空きメモリを作れば
出力されると予想
俺も試してみたけど、 cout なくても terminate 内で terminate が呼ばれたというメッセージが出てで死んでた。 例外機構を実行すること自体にメモリ足りなくて また例外投げて落ちてるのかもしれない。
>>750 多分、newするだけでメモリアクセスしてねーから、ページを予約だけして
実際にページインは発生してない、
ゆえにいつまでたってもエラーにならないんじゃないか?
まあ、C++言語仕様の範疇の話ではないな
って、内部的にはヒープツリーをゴリゴリ書き換えてんだろうから 流石にそれはないか
>>753 ちゃう。malloc に失敗自体はする。
ただ、catch される前に死ぬ。
え?badallocの補足って意味ないん?
B は A (8バイト)をコンストラクタで作って保持する 参照カウンタ式のスマートポインタで、 参照カウンタは A が保持しているとする(侵入型)。 んで、 int main() { try { std::list<B> v; for (;;) { v.push_back(B()); } } catch (const std::bad_alloc& e) { return 1; } return 0; } とすれば catch される前にメモリが開放されるはずなので 大丈夫かと思いきや、それでも死んだ。 多分、throw の実装が例外オブジェクトをヒープに確保するようになってて、 そこでメモリ確保に失敗して死ぬんじゃないかと予想する。
>>756 常に失敗するわけじゃなくて、
細かいバイト数ずつ確保していった場合のみ、こういう現象がおこるらしい。
bad_alloc 例外を受ける事は普通は全く問題ないんだが、
こういう極端な例の場合は問題が発生することもあるようだ。
これは GCC か何かのバグと言ってもいいような気がするね。
760 :
750 :2008/12/19(金) 22:24:15
大学のmacでやったらダメだったのに、家のlinuxでコンパイル・実行したらちゃんとcatchしてcoutされました。 (error:201046784回目に起こった) どちらのPCでもg++でコンパイルしたのですが、、、不思議です。
巨大な領域の確保に失敗する場合は有益だが、 double 1つごときが確保できないような状況では、 はっきりいってなにもできないに等しい
「BINARY HACKS HACK #38 g++ の例外処理を理解する(throw 編)」 によると、throw では __cxa_allocate_exception() によって例外オブジェクト用メモリが割り当てられるらしい。 で、gcc 4.2.1 の libstdc++/libsupc++/eh_alloc.cc では、32 bit 環境では、512 バイト×32 個の緊急回避用バッファを 用意しているものの、それを使い尽くしてどうにもならなかった場合には std::terminate() を呼んでいるようだ。
>>760 へー…
これは個人的な興味だけど、
new_handlerで出力しようとするとどうなるの?
764 :
750 :2008/12/19(金) 23:13:35
>>763 new_handlerを知りません。
とりあえず細かくメモリを割り当てると今回のようなことが起るかもしれないと思って置きます。
いままで逐一例外処理を書いてたけど無駄な作業になっていたのも多かったかもw
>>762 オフトピで申し訳ないのだが,そのソース中の
__cxa_allocate_exception() 内の goto の使い方は正当なのだろうか
どうでもいいが例外って普通参照でキャッチするんじゃないか?
何をとつぜん?
>>760 coutのせいじゃねえの?
printfは意外とヒープにデカいメモリ要求することがあるから
シビアな環境でのデバッグには使えなかったりする
coutのoperator<<はよく知らないけど同じようなことしてるんじゃね
>>768 おまいさんは今までの流れの何を見てたんだ・・・
ごめんよく読まずに書いてた cout外しても症状同じなのな
772 :
デフォルトの名無しさん :2008/12/20(土) 10:46:38
下のサンプルのようにmain()のなかのスコープ内でDataオブジェクトを作成して そこにDBからデータを読み込んでいます。 スコープから出ればローカルのDataオブジェクトは完全にメモリから解放される はずなのになぜかメモリリークっぽくなっています。 C++の書き方が問題なのかSQLiteのバグなのか検討がつきません。 ところどころでgetchar()で止めて確かめたメモリ使用量はコメントで 記しています。アドバイスお願いできないでしょうか。 // DBのデータを格納するデータ構造 class Data { public: vector<string> data; }; int main() { cout << "before scope" << endl; getchar(); // 2.7MB { Data d; func(&d); cout << "push data" << endl; getchar(); // 83MB } // ここでdは解放されて元の2.7MBに戻るはずなのに戻らないでリーク? cout << "out of scope" << endl; getchar(); // 22MB return 0; }
773 :
デフォルトの名無しさん :2008/12/20(土) 10:48:05
SQLiteのコールバック関数とfunc()は下のようになってます。 // SQLiteのコールバック関数、Dataオブジェクトにデータを流し込む int callback(void *unused, int columnCount, char **values, char **columnNames) { Data *d = (Data*)(unused); for (int i = 0; i < 10; i++) { d->data.push_back(*(values+30)); d->data.push_back(*(values+25)); d->data.push_back(*(values+30)); d->data.push_back(*(values+30)); } return SQLITE_OK; } void func(Data *d) { sqlite3 *handle; string query = "select * from Table1"; sqlite3_open("test.db", &handle); cout << "before exec" << endl; getchar(); // 2.9MB sqlite3_exec(handle, query.c_str(), callback, d, NULL); cout << "after exec" << endl; getchar(); // 83MB }
sqlite3_close() は?
775 :
デフォルトの名無しさん :2008/12/20(土) 11:11:23
もしかしたらそれかもしれませんが、オリジナルでは確か書いたと思います。 手元にないのですぐに確かめられないのですが それ以外で怪しいところがあったらご指摘お願いします。
環境とコンパイラにもよるが、一般に free/delete でメモリが全部 OSに返されるわけではない。 new/delete、malloc/free のすることは、 (1) ページという単位でOSからメモリを取得し (2) 必要なサイズにぶつ切りにしてプログラムに渡し (3) 解放されたら再利用できるようにリストにしておく という感じ。 だから、delete/freeでプロセスのメモリ使用量が完全に元に戻るわけではない。 その処理を1000回繰り返してメモリ消費量がどんどん増えるようなら 確かにリークしているが、1回だけの実行では何とも言えない
777 :
デフォルトの名無しさん :2008/12/20(土) 11:34:13
自分ではnew/delete使ってませんが、確保してるのはDataのメンバのvectorとかstringの内部でしょうか。それともsqliteの内部かな。今度繰り返して試してみます。もし他にC++の書き方としてまずい点があったらヒントをいただけると助かります。
リークっぽくなる、というのはどうやって確かめたの? まさかタスクマネージャ・・・
このプログラムでメモリリークするとしたらsql_lite部分位じゃね? まあ、stlとか信用していないならvectorとstringも怪しいが。
780 :
デフォルトの名無しさん :2008/12/20(土) 12:20:31
>>778 Windowsのタスクマネージャのメモリ使用量ですが・・・ダメですか?
あとLinuxではps alx | grep a.outでRSSを見てます。
781 :
デフォルトの名無しさん :2008/12/20(土) 12:22:10
>>779 SQLiteの最新版を使ってはいるんですが、Googleで調べてみたらメモリリークのバグありとかなんとか・・・
>>776 さんの方法で確かにリークしていたらそこくらいしか思いつかないのです。
>>781 さっさとループにして試せばいいじゃん
5秒でできるだろ
せめて10秒はください
784 :
デフォルトの名無しさん :2008/12/20(土) 12:50:16
>>782 ごもっともだと思うので今試してみます。
環境がMacしかないうえのsqlite3もDBも手元にないので5秒では無理ですが報告します。
>>785 782から15分経ってるからとっくに出来てるよな
早く見せろ
787 :
デフォルトの名無しさん :2008/12/20(土) 13:04:31
ためしてみました。 cout << "before scope" << endl; getchar(); { Data d; func(&d); cout << "push data" << endl; getchar(); } cout << "out of scope1" << endl; getchar(); { Data d; func(&d); cout << "push data" << endl; getchar(); } cout << "out of scope2" << endl; getchar(); こんな感じで5回繰り返しています。使ってるDBは同じじゃないです。メモリ使用量はps alxのRSSです。sqlite3は3.6.6です。 最初: 356 DB読み込み直後: 74884 out of scope1: 70808 out of scope2: 71784 out of scope3: 72752 out of scope4: 73720 でした。やっぱリークかな・・・
5回かよ
5回といわずずっと回し続けてみてよ
そして1年後、、、
まさかコードコピペで繰り返すとは思わなかった
そういのはものすごい回数くりかえして、リークしてなきゃありえない使用量になるぐらいまでやれよ
793 :
デフォルトの名無しさん :2008/12/20(土) 13:41:26
では、100回ループしてみました。 cout << "before scope" << endl; getchar(); for (int i = 0; i < 100; i++) { { Data d; func(&d); cout << "push data" << endl; } } cout << "end of scope" << endl; getchar(); 1回目ループ後:75860 100回目ループ後:166840 うーん。やっぱり少しずつもれてるんでしょうか。
そういうのは100回、200回、300回、400回・・・と回数変えてループして グラフにするんだよ。
sqlite3_close()は?
sqlite_closeくらい当然のようにすでに書いた 上でループコードを回してるんだよな・・・ 当然だよな・・・ ・・・
sqlite3_closeって、全処理の最後にDBファイルのクローズを行うものだから、 少なくともこの現象とは関係無いよ。
>>773 コールバックの中でpush_backしてるのをコメントアウトしてみたらどうなる?
>>801 いやいや、開いた handle をクローズしなきゃまずいだろ
sqlite3_close のシグネチャは
int sqlite3_close(sqlite3*);
だよ?
あの、そのhandleは何かというのは分かってる? 例えれば、FILE* と同じものだよ。おまえは、ファイルの読み書きをする時に、 readのループで毎回fopenしてfcloseしてるのか?
というか、sqlite3_closeが無いとか言ってる奴は、 元の質問とコードを全く読んでないだろ。 それとも読解能力が無いのか?
「オリジナルでは確か書いたと思います」 とは
言ってるけど、正しい位置で呼び出してるかどうからわからんし、
コピペされたコードにない以上、答える側が疑うのは当然だろ
>>805 func でsqlite3_open して、closeしてないじゃん?
ここでいうループってのは、メモリ使用量を測るための
処理全体の恣意的なループのことを言ってるんだから、毎回解放するべきに
きまってるじゃん
ていうか、おまえは 普通のプログラムで fopen 読んでおいて fclose を
呼ばないのか?お前らこそコード読んでないだろ
#fcloseは自動的に呼ばれるってのは無しな
デストラクタにsqlite.close()入れておけばいいじゃん
closeは例外返さないの?
おまえら今気づいたけど、スレ違いじゃねコレ
まぁいいじゃないか相談室なんだし
質問です。
newで確保したメモリはヒープ領域から割り当てられて、
ヒープ領域は双方向リストで構成されてますよね。(wikipedia調べ)
下の図で分割されてる四角が双方向リストを表してます。
この左側には次の空き領域のアドレスが入り、0が入ってるのは次の空き領域がない状態です。
右側には空き領域のサイズが入ってます。
この空き領域と割り当て済の領域はスタック構造なのでしょうか?
メモリについてよく理解していないので変なこと言ってるかもしれないです。
ttp://kita.kitaa.net/10/s/10mai81022.jpg
3行目ですでに違う と思うが、これからWikipedia見てくる ヒープが双方向リスト構造をしているわけではない
メモリブロックがリストで管理なのは普通じゃないか?
ヒープ領域をどのように管理するかは実装依存。 使う側としてはどのように管理されているのか意識しなくていいはず。 自分でカスタムアロケータを書く際の参考にするとか、アセンブラレベルでコードを 追っかけてるとか、メモリダンプを解析しているとかでなければ。 とはいえ、リスト構造によって管理するのはありがちな実装だとは思う。 「スタック構造」が何を指しているのかよくわからないけど、領域の割り当てと解放は 任意の順序で発生しうるので、先入れ後出しのスタック構造とは言えないと思う。
ヒープという言葉自体C++の用語じゃないでしょ。 C++の用語としてはフリーストアが正しい。 C++の規格内にヒープという言葉は std::make_heap などのヒープ構造の操作関数以外存在しない。
wikipediaの記事も微妙だな・・・ たしかに間違ってはいないんだが、いろんなレイヤーの話がぐちゃぐちゃに 書いてあるから、初心者は混乱するような気がする OSとページングとプロセスモデルの話があって、 その上に libc の話があって、 その上にC/C++の話があるわけだけど
wikipediaは、大人になりたくて背伸びをしてる若者が、うまく整理できていない 雑多な知識の風呂敷を広げるところでもあるからな。
>>812 まず、「スタック」 には2つの意味があって、
「プロセスが利用するメモリ上のスタック領域」 と、
「スタックと呼ばれるデータ構造」 がある。この両者の区別はついてる?
両者は、別物。正確には、メモリ上のとある領域が、「データ構造のスタック」 と
似ているから「スタック領域」 などと呼ばれる、ということだけど。
同様に、
「メモリ領域のヒープ」 と 「データ構造のヒープ」 も完全に別物。
まずはこの区別を付けること。
ちなみに、質問にストレートに答えるなら、答えは 「NO」
>>816 malloc()やfree()がC++の標準に入ってないとでもお思いですか?
>>812 メモリ割り当ての構造やアルゴリズムを知りたければ
ベストフィット/ファーストフィットなどのキーワードでぐぐれば
それなりに詳しいものに当たれるはず。
フリーストアは別にヒープを使わなくても仕様上構わないお。 実際にヒープが使われる事が多いだけであって。
メモリ領域をスタックとかヒープとか呼ぶのは Perlで連想配列をハッシュと呼ぶのと同じようなもんだな。
malloc や free を使う分にはヒープを使ってるということだろう。
規格と実装を混同すんなよ
malloc や free を「直接」使う分には、と言わないと分からんか
背伸びしたい年頃の子には、そういう思い込みが多いのですよ。
829 :
812 :2008/12/20(土) 20:57:41
スタック領域、ヒープ領域はメモリの一部分に名前をつけたもの。 スタック領域はプログラム開始時に変数作り終了時に一斉解放する場所。 ヒープ領域は動的に確保する変数をリスト構造使って割り当ててく場所。 この認識であってますか?
フリーストアとヒープの違いって何?
スタックについては違う ヒープについてはおおむね正しい
>>828 C++の標準関数であるmalloc()が持ってくるのはどこの領域ですか?
>>830 正直なところ、名前が紛らわしいから付け替えただけ、というのが本当な気がする。
名目上は、ヒープはプロセスの仕組みとかと比較的結びついていて
どこから割り当てられるかある程度決まっているけど
フリーストアはその出自を問わない領域、ということにはなってる。
もちろん、malloc()が割り当てるのはヒープで
operator new()が割り当てるのがフリーストアであり、
フリーストアの割り当てに失敗すると
new_handlerが呼ばれたりbad_allocが投げられたりする、という違いはあるけどね。
間違ってる点を教えてもらえないでしょうか? 俺にはどこが違うのかわからないので・・・。
とりあえず「スタック」という言葉にも データ構造としてのスタックと CPUの動く仕組みとしてのスタックがあるから混同するなよ。 もちろん、由来は同じなんだが 「スタック領域」と「スタック構造」は違うから。
840 :
デフォルトの名無しさん :2008/12/20(土) 21:30:37
>>793 書いたものですが
ループ100回回したのサンプルでsqlite_close忘れてましたorzすみませんorz
sqlite_close入れたらループ100回回したあとのメモリ使用量は70812で増えてはいませんでした。
ただ完全に解放されてはいないようです。
これは
>>776 さんの言う通りにあとで使い回すためにキープしてあるのかもしれません。
vectorにもswap技法なんてのもあるようなので強制解放できないか調べてみます。
結局closeかい
ヒープ違い ヒープという言葉には2通りある
すまん答えになってなかった 正しい
>>838 たしかに、そのページは全体的にいろいろおかしい。
参考にするべきではないね。
「autoと宣言することによるメモリを効率的に使えます」 ってなんだ
>>844 標準関数のmalloc()はヒープからメモリを割り当てるのに
>C++の規格内にヒープという言葉は
>std::make_heap などのヒープ構造の操作関数以外存在しない。
が正しいのですか?
>C++の用語としてはフリーストアが正しい。
のならば、malloc()のところにも「フリーストア」と書いてあるのですか?
あ、何も書いてないんですかね。
本人が「ヒープ」という言葉を使っている、 つまりmallocで確保したメモリのことを言ってる可能性もあるのに 「C++の用語としてはフリーストアが正しい」なんてわけないだろ。
C++の企画において、C言語は 「参照によって」 含まれる
C99の7.20.3 Memory management functionsより The order and contiguity of storage allocated by successive calls to the calloc, malloc, and realloc functions is unspecified. The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated). The lifetime of an allocated object extends from the allocation until the deallocation. Each such allocation shall yield a pointer to an object disjoint from any other object. The pointer returned points to the start (lowest byte address) of the allocated space. If the space cannot be allocated, a null pointer is returned. If the size of the space requested is zero, the behavior is implementationdefined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object. どこに確保しろとは一言も言ってないな アライメントちゃんとしろとかallocationからdeallocationまで寿命持てとか 別に確保したのは被らないようにしろとか失敗したらNULL返せとか要件しか書いてない
つまりフリーストアとは書いてない、と
まあC99の規格なら当たり前か
少なくとも、mallocはフリーストアからは確保しない。これは正しい。 だから、mallocで確保した領域について話す場合は、 「C++の用語としてはフリーストアが正しい」は正しくない。
>>845 > 「autoと宣言することによるメモリを効率的に使えます」 ってなんだ
Cの話だな。
関数内で修飾子を付けずに宣言した int x; みたいなのは auto int x; の省略形とみなされている。
このautoの意味は領域が必要なとき(スコープが有効になったとき)に自動的に確保されて
不要になったら(スコープから抜けたら)自動的に解放されるということをstaticとの対比で明確にしたもの。
必要になったときに確保されて不要になったらすぐに解放されるんだから
プログラム実行中は確保されっぱなしの静的なものよりはメモリを効率的(容量的な意味で)に使えるってこと。
・・・何をいまさらって説明だな。
>>854 auto修飾しない場合、コンパイルオプションでレジスタ変数への最適化を許容させていた名残かもね。
auto 修飾した場合にそういう最適化をしないコンパイラがあった頃の名残、と言いたいのかの? 今でもレジスタへの最適化は普通にするし。
longjmpしたとき、volatile修飾されてないauto変数の内容は復元される保障がない というのを思い出した
いずれにせよ今のautoは全く意味のない修飾子だし C++0xでは型修飾子ですらなくなるし 型修飾子autoを使ったC++コードを今書くことは有害なだけだな 解説ページに書くことではない
そろそろ register の活用も考えてやるべきだと思うんだ。
スタック領域、静的領域、ヒープ領域のそれぞれの使える容量はコンパイラによって違うのでしょうか? 一般的にそれぞれどれくらいの割合が普通なのでしょう?
>>861 とりあえず大小関係は スタック < 静的 < ヒープ が一般的かなぁ。
割合は、同じぐらいの環境から 1000 倍の違いのある環境まで見たことあるし、
どれぐらいが一般的とかわかんないねぇ。
コンパイラによってっていうか、実行環境によっても変わるし、大抵、設定によっても変えられる。 単なる興味本位でなければ、なぜそういう質問をしているかという背景があると望みの答えが得られやすいかも。 どのデータをどの領域に割り当てるか、について考えるために聞いているなら、サイズがどうこうより そのデータの使用方法によってどの領域に割り当てるかがほとんど決まるので意味がない。 ・関数内のみ→スタック ・プログラム中維持、サイズ不変→静的 ・プログラム中の任意の時点で確保、解放、サイズ変更あり→ヒープ サイズによって変える場合があるのはでかすぎてスタックに入らないパターンくらい。
スタックは普通結構小さいからな。
いや、おまえら元ページを見ないで そんな議論してると思うけど、元ページはそんなレベルじゃないと 思う。めっちゃくちゃなページだから
#define PI atof("3.1415ちんころり") 動いた!?Σ(゚д゚lll)
>>865 > いや、おまえら元ページを見ないで
> そんな議論してると思うけど、元ページはそんなレベルじゃないと
> 思う。めっちゃくちゃなページだから
見てきたがそれほどひどくない、
っていうかああいった方向でだめなプログラマはめずらしくもないので正直どうでもいい。
すじまんこ!?
マルチスレッドの書き方がよくわからないのですが、 もっと簡単に関数にマルチスレッドフラグのようなものはないんですしょうか?
ない
>>872 何がしたいからマルチスレッドにするの?
スレッドを複数動かせばマルチスレッドだけど・・・
NowLoading?
マルチコアCPUで一つの処理を速くしたいために マルチスレッドにするならOpenMPでも使えば良いんじゃね。 本質的にマルチスレッドな処理がしたいなら マルチスレッドな処理をプログラムすればいい。
boost::thread func(); すいません、調べたらBoostライブラリを使えばいいと書いてありました。
完全に独立できる処理ってなかなかないからマルチスレッドも定型処理じゃないとあんまり役に立たないよね CPU2つあるからって処理に2つ使っちゃったらレスポンス最悪だしね 処理時間長めでも軽いほうが大抵いいよね って考えると余計なお世話的場面のがどうしても多くなる
C言語に特化したリファクタリングの本知らないですか?
なんでここで聞くの?
仮想関数で、継承クラスを書かず基本クラスの仮想関数を呼び出した場合、 基本クラスの仮想関数が実態になる、であってますか?
あいまいすぎる コードで書け
class a { virtual void funk(); } class b : public a { funk(); } a::funk() でb::funkが呼び出される b::funk() でb::funkが呼び出される まではわかったんです。 この場合、class bが存在していない場合 aのfunkが実態になるんでしょうか?それとも起動しないんでしょうか
実態とかいう意味不明な言葉は置いておいて bが存在しなかったらa::funk()が呼び出されるに決まってるだろ
質問の意味は分らんが試してみれば?
a::func() が純粋仮想関数ならclass aはインスタンス出来ないからコンパイルエラー a::func() が純粋仮想関数で無いなら a::func() が実行される
a::funk()で呼び出されるのはa::funkだろ。
Boostの1.36以降の追加ライブラリを日本語で調べられるのはどこかにありますか?
日本語の情報は常に不足している 君が書くんだ
名前の衝突と,クラスとスコープについてよく分かりません class A { public: char* hoge = "A::hoge"; void func(); private: void piyo(); } A::piyo() { cout << "A::piyo()"; } A::func() { cout << hoge; piyo(); } A::func() 内で int hoge; などと別に宣言した場合の曖昧性を回避するにはどうすればいいですか あと,グローバルスコープで別に定義された piyo() を A::func() の中で呼び出すにはどうすればいいのですか
890 :
デフォルトの名無しさん :2008/12/24(水) 18:34:53
891 :
デフォルトの名無しさん :2008/12/24(水) 18:37:34
つか曖昧性云々の前にA::func()でint hoge;宣言したら以降のhogeはこのint hogeが使われるんじゃね A::hogeでないとメンバ変数のhogeにはアクセスできないんじゃね
this->hoge って出来ないの?
>>889 実務的には命名規則とか決めて名前が重複しないようにする。
言語仕様的なことは置いといて。
m_XXXとか、_XXXとか。
>>894 そうか、C/C++は予約されてたな。
他の言語では使うこともある。
896 :
デフォルトの名無しさん :2008/12/25(木) 12:19:52
>>895 ここはC++のスレだ
他の言語ってなんだよw
std::list::sort() は安定なソートなのでしょうか?
>>897 うん。
規格に std::list のメンバ関数 sort() についてに以下の記述がある。
23.2.2.4 "list operations" p31
> Notes: Stable: the relative order of the equivalent elements is preserved. ...
質問です。 C++のクラスの初期化についてです。 メンバー変数を増やしたり減らしたりしていると、ついつい増やした際にコンストラクタでの初期化を書くのを忘れてしまうことがあります。 もちろん「メンバー変数を増やしたら、コンストラクタに初期化処理を書け」を守ろうとはしているのですが、たまに忘れ、Releaseビルドだとうまく動かない!ってことが起きます。 この手のヒューマンエラーを無くす方法で、何か良いものはないでしょうか。 例えば「クラスのメンバー変数が全て0で初期化されていることを保証するコンパイルオプション」とか、そういう類のものがあれば・・・と思うのですが
>>899 コンパイルオプションを例に挙げながら
コンパイラが何なのかは書かないんだな
気になるならメンバ変数のクラスのデフォルトコンストラクタを protectedにでもしておけばいいんじゃね かなり不毛だけど
boost::value_initialized
>>900 gccならこんなオプションがあるよ。って答え方すりゃいいんじゃね?
まー初心者くさいからVC2008だと思うが
質問です クラスAAAのメンバ関数の引数にクラスBBBのインスタンスがあって クラスBBBはメンバ変数としてクラスAAAのインスタンスを持っているとき class AAA { void test(BBB inst); }; class BBB { AAA mem; }; というコードにすると、最初のクラスAAAの部分で、まだクラスBBBが定義されてないためにエラーがでて、 順番を逆にすると、今度は逆にAAAが定義されていないと、同様のエラーが出ます こういう場合、どうすればよいでしょうか?
class BBB; って先頭におけば
どうしてC++は、純粋仮想関数の宣言に =0 と書くルールを採用したんだろうな 気持ちは分からんでもないが、知らないと理解できないルールは実用上良くないだろ
C++のルールなんて知らないと理解できないようなものばっかりだろ
そもそも何で仮想関数と呼ぶんだ? virtualというキーワードでは直感的に意味が分からないから、よろしくない
910 :
デフォルトの名無しさん :2008/12/25(木) 20:45:02
何だったらよろしいんだ? 例えば?
a.foo()と書いた時に、呼ばれるべきfooがどこにいるかは aの実体(具体的にはvtbl)を見るまでわからない だから仮想
abstractとでも言いたいだけだろう。
日本語にすると意味分からんよな。仮想。 virtual = (表面的には違うけど)実質上の、事実上のっていう意味だから。 てか、virtual = 仮想って誤訳だよな。まぁ定着しちゃったから別にいいけど
>>914 は?煽るんならまずお前の解釈とか意見を書けよ
前提抜きで考えれば、仮想関数は意味的におかしいだろ。
別にvirtual=仮想と訳すのが世の中全部で間違ってるとは言ってねえよ
日本語にはしっくりする訳語はないだろう polymorphicだって多態だの多相だのとわけわからん訳しかないから 結局「ポリモーフィック」で通ってるんだし
ニュアンスとしては、「virtual X」は「ほんもののXではないが、 Xのように見える/振舞うもの」じゃないの。 C++では「インタフェースの一致」に主眼を置いてvirtualといっているんだと 思うが、virtualという言葉は「偽」「〜もどき」「バッタもん」という イメージがとても強いので、イメージ的に混乱が生じる 仮想派生とかになるともっと意味わからん
overridable か derivable あたり もしくは indirect とか
抽象関数でいいよ
動的メンバ関数はどうだ
動的だと静的の対義語みたいじゃないか
>>917 > virtualという言葉は「偽」「〜もどき」「バッタもん」という
> イメージがとても強いので、
そのへんのニュアンスは、マスコミのゲーム批判とかネット批判で
強化されてきた感が、個人的にはある。
virtualは英語的には「実質」とか「実際の扱いでは区別しなくてよい」くらいの強めの意味があるからなあ。 その意味ではvirtual関数はインターフェースとしての性質をよくあらわしている。 バーチャルリアリティは目標としては「現実と区別できない」だが実装された技術はそこまででもない、みたいな。
class IA{...}; class IB{...}; class A : public IA{ private: IB* pB_;// Bにアクセスするために使う(デストラクタでdelete pB_;とするわけではない) }; class B : public IB{ private: IA* pA_;// Aにアクセスするために使う(デストラクタでdelete pA_;とするわけではない) }; newされたAとBの寿命管理は別のクラスがするとします。 メンバ変数として保持された参照(pA_またはpB_)が生きているか死んでいるかを検知するにはどういう方法がいいのでしょう? 考えたのは ・ハンドルを使う(boost::weak_ptrなど) ・デストラクタで相手に死んだことを伝える(pB_->NoticeDeleted(this)など) ・メンバ変数で参照を保持するのをやめて、参照が必要なときに寿命管理クラスに問い合わせて参照を取得する ケースバイケースな気はするのですが、この中で絶対にやめたほうがいいとか、これにするべきというのはありますか? また、他にも方法があったらお願いします。
それだけ密接に関連したクラスの寿命管理を別々のクラスにさせること自体がそもそもおかしい
>>924 そのコードを「参照を保持する」と呼ぶのは止めて欲しい。
>>925 > newされたAとBの寿命管理は別のクラスがするとします。
これはAの寿命管理はBでなくC、Bの寿命管理はAではなくCという意味です。
わかりにくくてすみません。
>>926 すみません、型名&で宣言される参照と紛らわしいですね。
そのままポインタと呼ぶべきでした。
オブジェクト設計からやり直し
>>928 相互参照が発生してる時点で失敗してるということですか?
スマートポインタ使え
AもBも、直接お互いの参照を持たないで、Cに問い合わせる形にするべきじゃないか? AとBはお互い同じ「偉さ」(主従関係にない)なんでしょ? 実質Cが親みたいなもんじゃない。 CはAやBがいつ死んだのか知ってるわけだから、安全でしょ。 (Aから「Bのポインタが欲しい」って言われた時、Bが死んでいたらNULLを返すとか)
>>928 Cがどういった形でAとBを管理してるのかわからんが
俺だったらCにshared_ptrでAとBを保持させて
AからB、BからAへのアクセスはweak_ptr使うかな
A が B にアクセスして B が A にアクセスする なんとなく構造が変だよな 依存しあってる code smell
循環参照ねー・・・ STGで、敵は主人公の位置が知りたいので主人公へのポインタを持つ。 主人公も敵の位置を知りたい(オートロックオンとかそういう機能があったので)ので敵へのポインタを持つ。 って設計になったとき、これはおかしいぞって思った。 確かにお互いがお互いの情報を欲しいから、参照を持つと楽そうなのはわかる。 でもなぁ。 というわけで、主人公は「敵達を管理するクラス」から敵の位置を取得するようにしたし、 敵は「ゲーム全体を司るクラス」から主人公の位置を取得するようにした。
そうして、ゲーム全体を管理するクラスを更新するたびに 敵を管理する cpp 全てを再コンパイルするはめに…と 気づいたら、何を更新しても全てを再コンパイルする羽目になった
Relationをオブジェクトにしてしまえ
>何を更新しても全てを再コンパイルする羽目になった 良いではないか、良いではないか。
ゲームでの性能がシビアだったらしらんがインターフェース実装で依存切れるだろ。
普通はインターフェース実装だわなぁ。 でもインターフェースが増えるとやっぱり再コンパイルとなるわけでw
>>934 ポインタの保持はグローバル変数と並ぶ大罪
引数で渡すのが王道
その辺のコードはスクリプトで記述するもんじゃないの? いまだにc++でゴリゴリ書いてんの?
ポインタ保持できなかったらうっかりメモリも確保できねえ。
すべてスタックに確保か
>>943 複数保持だろ?
昔のC言語の本には結構書いてあったな
ゲーム作ってるとDirectXのデバイスのロストで大抵痛い目見るんだ
どっかで保持してあるインスタンスがあって そのインスタンスのポインタをどっかのクラスがもっちゃ駄目だよね そのインスタンスを破棄した情報をどっかのクラスは知らないわけだし どうしたってバグる そういう構造にそもそもしちゃ駄目 引数使え引数
スマートポインタ使おうぜ。
引数にすると処理ごとに別のインスタンスが渡されることを考慮しないといけないから、 そう簡単に置き換えられないこともあるでしょう。
インスタンスのエイリアスが複数あると最適化が阻害されるじゃん 基本的に、最適化しづらいコードってよくないと思うんだ。
951 :
デフォルトの名無しさん :2008/12/27(土) 00:11:53
とか言って、最適化しやすく書くと処理系依存だのって叩かれるんだよな
>>949 それって結局別の処理かかなきゃいけないわけだしいいんじゃないの?
駄目なの?
必要もないのに必要のない値が一括で流れてる構造っていいの?駄目なの?
引数できっちり渡すことこそきちんとしたプログラムじゃない?
それとも実装の手間惜しんでバグ増やすほど作業時間切迫してるの?
class T { public: void foo(C& c); void bar(C& c); // foo() と bar() には必ず同じインスタンスを渡してください!! }; こんなコメント書くぐらいなら T の中に C& c を持ったほうがいいこともあるでしょ。
>>953 ないって
よしんばあったら設計がまずい
どんな状況だそれは
そもそも使う側からみて if(pC)chinko.setC(pC); chinko.foo(); unkounko();←実はこのときにpCシボンヌ chinko.bar();←そうとは知らないchinkoがpC使おうと必死の形相で実行 なんて見た目問題おきないようなコードでやられたら一生バグがみつからん っていうかチェックが甘すぎる このコードはせめてこうなってなきゃ駄目だろ 素人じゃないんだから if(pC)chinko.setC(pC); if(pC)chinko.foo(pC); if(pC)unkounko(pC); if(pC)chinko.bar(pC); なら使用してる側からもpCにアクセスしてるってわかるだろ常考(エラー処理もほしいが) ↓これじゃ意味不明じゃん if(pC)chinko.setC(pC); chinko.foo(); unkounko(); chinko.bar();
>924 AとBは一対一対応? 何で多重継承じゃダメなの? 動的に切り替わったりするの? >956 昔からある所有権の問題だな。 素直にスマートポインタ使うのがベター。
>>957 そうかぁ?
スマートポインタって落ちないだけじゃね?
俺は引数を使ってうまく組むべきだと思うけどね
>>953 自分ならせめてこうする。
class T
{
public:
void foo_bar(C& c) {
foo(c);
bar(c);
}
private:
void foo(C& c);
void bar(C& c);
}
>>959 ポインタの保持の問題をいってるのにおかしなこという
961 :
957 :2008/12/27(土) 01:16:25
>958 依存関係を減らすのは重要だけど、本質的に依存するものを切り離すのは本末転倒だからね。 結局のところ、クラス同士がどういう関係で、何を処理するか次第だと思うよ。
>>961 いや、そんなことねぇよ
やっぱり、こういうポインタを保持しちまうなんてのは
PGの怠慢なんだよ
怠慢するならするでさ
なにかフォローが必要なんだと思うぜ
もちろん他の人間もわからないしさ
人に対してもソースに対してもそういう配慮が必要になるのを忘れちゃいけない
資料作ったりコメント残したりね
そういうのが嫌だったら引数で渡すようにしたほうがいいぜ
引数だって構造体でまとめて変更あってもソース変わらないですよね?
なんて意地悪しないでちゃんと一つ一つチェックして渡すべき
963 :
957 :2008/12/27(土) 01:25:32
ついでに言うと ・引数で渡す オブジェクトが生きていることを保証する責任は関数を呼び出す側(のプログラマ)が持つ ・スマートポインタのメンバとして保持 オブジェクトが生きていることを保証するのはスマートポインタ。 ただし、循環参照など別の問題が発生するかどうかを管理する責任はスマートポインタを 扱う部分全体(のプログラマ)が持つ といった感じかね。
> 基本的に、最適化しづらいコードってよくないと思うんだ。 最適化されますようにって気を使って技巧的に書いたソースからできたバイナリよりも 深く考えず自然な形で書いたソースからできたバイナリのほうが最適化されていることがある罠。
965 :
957 :2008/12/27(土) 01:30:24
>962 だから内容次第だってば。 例えばイテレータとかはポインタをメンバとして持たないと何にもできないぜ?
>>965 ごめん
C++のそういう機能全般使ったことないわ
俺、C+クラスぐらいの機能でもう10年ぐれーそれで通ってきてる
これまで言語は規制をかけることで発展してきたけど
C++のテンプレート類はなんか便利な機能群な感じがして
これまでの言語の進歩とは違うっていうか勘違い系が入ってる気がするんだよね
毎回、何がいいの?その程度の機能って感じがする
967 :
957 :2008/12/27(土) 01:43:49
さすがにC++をC++として使うのなら、STLとか使わないのは勿体無いよ。 ベターCとして使うんだったら別に構わないけど。 もちろん、純粋関数だけを使用して宣言的にプログラムすることもある程度可能だけど、 全部それでやろうとすると大変な部分が出て来るからね。
>>967 あんまり便利にならなくね?
むしろ、問題ばっかりおきる
あれだけ汚いコードかかせてやってくれること可変配列だけっていらないだろ
配列 new ダイレクトに使ってんのか? ちょっと例外起きただけでメモリリークするようなプログラム組んでんじゃねーだろうな。
newはオーバーライドしてあるからいいチェック入ってるな でもmallocラップした関数のがいい機能あるんだよね・・・orz
いい機能w
shared_ptrとか使わずにnewやmallocをラップしただけで対策してる気になってる? だったら間違いなく例外脆弱なコードになってるな 「俺は例外なんか使わないから関係ないぜ!」とか言わないように 関係なくないから
>>972 引数通すから必要ないよ
お前が想定してる自体のほとんどの可能性からいって潰れてるから
必要ないんだろうな
ライブラリが勝手に例外投げる事もあるからな。
>>973 騙るならまず日本語を勉強してからにしてくれ。
ポインタの保持もしない 引数で渡してるならほとんど問題おきないな 引数で渡すって怠慢をするから他の多くのものが必要になってる感はたしかにある
X引数で渡す ○引数で渡さないでポインタを保持する
newしたポインタを誰も管理せずに関数の引数で持ち回ってるの? それだから例外安全だって言ってるの? ダメだこいつ早く何とかしないと
void foo(X *px){ ... bar(px); ... } int main(){ foo((X*)malloc_wrapper(sizeof(X))); delete X; } 引数で渡すってこういうこと?
>>978 どういう場合を考慮して駄目って言ってるの?
>>979 インスタンス1つに付き変数1つみたいな感じだ
なんではじめのmallocで確保したときは変数もってもいいぜ
でもそれ以外は駄目
引数で渡すってのはそれであってる
fooやbarが例外投げたらとか下らないことは言うなよ 絶対投げない関数しか使わないから
エラーメッセージだして終了だろ常考
例外を送出しない保障の関数しか使わないのかー。 そんな最強クラスに強い例外安全性だけでコード書くとか俺には無理すぎる。
>>983 例外使えないとなんか駄目なんだw
そんなにあの機能役に立つとは思えないけどなー
コードスタイルひっくり返すほど重要なんだw
あんまり応用効かない技術に頼ってんのな
なんかの位置間違えたんだろうなきっと
>>984 だって便利とかの以前にC++の他の人が書いたライブラリはほぼ全滅。
標準ライブラリもboostも諦めるしかない。
newもnothrowとかplacement newとかしか使えないじゃん。
ついでにoperator hoge(=,+,etc)系は、
本質的に例外使えないとエラーを表現できないから使えない
同じくコンストラクタもエラーの通知方法は例外だから使えない
operator =とコンストラクタが使えないって事は結局ただのPODと殆ど同じ。
エラーの発生しない事が保障できるなら上の構文も使えるけど、
そんなのはPODに毛が生えたようなしょぼいデータ構造だけだろうし役には立たなさそう。
POD相当のクラスしか使えないC++って何に使えるの?
本当にCよりはマシってぐらいしか使い道なさそう。
個人的にはC++では例外は空気のように存在してて、それが無い世界が割と想像できん。
Google 社では例外禁止だけどな。
>>986 だから全部使ってねぇって
C+クラスしか使ってねぇっていってんじゃん
つまり、C99で拡張された機能も使えずC++の便利な機能も一切使えず、 未だに20年近く前の技術にしがみつくということなのですね、判ります。
>>990 仮に使うと何がどうよくなんの?
って機能ばっかりだけどな
クラスにしてもあんまりご利益ないんだよね
老害
いやだから、頭が20年前のレベルから進化してないのだろ? 大人しくCを使っておけばいいと思うよ。 COBOL専業のソフトハウスだってあるご時世だ、C専業もあるだろさ。 つーか、>992に同意。
>>960 ならそもそも、954も言っているが、953のような有り得ない状況を元に話をするなよ。
>>993 みんなそうだけど
全然説明できないよね
テンプレートまわりの利点ってさ
作り手のオナニー以上の効果は絶対にない
こういうのをマクロではなく関数として記述できるとか、 #define swap(type, x, y) do {type t = (x); (x) = (y); (y) = t;} while (0); CのqsortよりC++のsort関数テンプレートのほうが見た目が自然でしかも速いとか。
言ってみろって言われて初っ端そんなことしかでてこないところとか もうホントなんもねぇだろw
↓最後に当を射たレス
1000ならC言語に戻す
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。