1 :
v(^・^)v :
2006/03/15(水) 20:53:15
STLつかうと一気に実行ファイルサイズが10倍に?!
>10 環境によるだろ。 俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力 ランタイムを使用するようにして使っているが、例えばstd::vectorを 使っても使わない時と比べ10Kほどしか増えない。
>>11 すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。
C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。 とかいうエラーが出るんだけどこれってどうすればいいの? #include <stdafx.h> 後氏ね。 言葉が悪いな。それで教えているつもりか。 まぁヒントぐらいにはなったな。 うむごくろう。
プロジェクトのプロパティで、"プリコンパイル済みヘッダーを作成する"にする というかVSすれに行ってくらはい。
>>12 ,
>>15 新参者を発見しますた。(・∀・)ニヤニヤ
そういやもう春休みの時期かぁ。
なんで変なところまでテンプレになるの? 某厨房板の地鎮祭みたいなものか?
新参者を見つけてニヨニヨするスレはここですか?
なんでただでさえ長いテンプレに変なもんつけるんだか。
あっちこっちから参照されるサブ関数はC++の場合どうするのが いいんでしょうか? サブ関数をまとめたクラスを作って使用もとでフレンド宣言とかでしょうか? アドバイスよろしく
>>20 サブ関数とやらは全部適当なnamespaceに放り込んどけ。
>>20 なんでフレンド?
てけとーなクラス作って、
public static な関数にしてしまえばいいんじゃない?
まぁ
>>21 みたく namespace でもいいけどさ。
namespace mylib { namespace math { // 数学関係の関数 } namespace graphics { // 画像関係の関数 namespace io { // 画像関係の入出力 } } namespace utility { } .... } のようにしてる。適当なnamespaceの中に、用途別のnamespaceがある感じ
24 :
20 :2006/03/16(木) 17:09:21
ありがとぅん 家に帰たら挑戦してみます。
26 :
デフォルトの名無しさん :2006/03/17(金) 21:33:22
なんでケツが関係あるの?さっぱりわかんね。 亜ふぉで素か?
28 :
デフォルトの名無しさん :2006/03/17(金) 22:06:54
おろっ? K じゃなかったか・・・ これは失礼 # はー、つまんね
俺は?
俺も?
32 :
デフォルトの名無しさん :2006/03/18(土) 06:50:08
あれかい? デリートしたオブジェクトポインタは直後にNULLにしといた方が初心者には何かと安心かい?
うん
二重 delete が起きるコードなんてたいていバグってんだから、 バグ発覚の可能性を除去するなんて勿体無いとおもう。
35 :
デフォルトの名無しさん :2006/03/18(土) 07:34:06
もしコピーコンストラクタが代入に対処できていたら、大変な事になってましたね。 左辺が、意図したデータを持ってる時の代入か、はたまた初期化の時の単なるゴミデータか判別できませんもんね。 ゴミの時にメソッドなんか呼ぼうもんなら終了ですもんね。 以上、今日の日記。
初めてconstの有用性を知ったとき、関数の引数をconst参照で渡す効能を知ったとき、 あるいは前置++, --演算子の後置に対する効率上の違いを知ったとき等、 人は十字軍になるものなんだろう。Effective C++にも書いてあるけれど。 何事も行き過ぎはよくないという一例だな。
37 :
デフォルトの名無しさん :2006/03/18(土) 16:18:16
>>34 >たいていバグ
じゃなくて、明らかなバグ
でも、delete 後 NUL代入する「信仰」は後を絶たない
何故だろう??
即落した方が、遥かに有用だと思うのだが
すぐエラーで落ちるとは限らない
>>37 delete 自体は問題なくてもデストラクタが複数回呼ばれちゃいかんだろ?
で、デストラクタがあるオブジェクトかどうかでNULLは代入したりしなかったりするのはナンセンスだろ?
>>37 たとえば、T型へのポインタの配列へのポインタT** ptrをメンバに持ち、要素をクリアするメソッドを定義すると
void clear() {
if (ptr) {
for (int i = 0; i < size(); ++i) delete ptr[i];
delete[] ptr;
ptr = 0;
}
}
このclear()は、もしptrに0を代入していなければ、二度呼び出された時点で不正になる。
要素が存在する場合に限ってclear()を呼び出せるような仕様にするより、
いかなる場合でもclear()は要素をクリアするような仕様の方が、見通しがいいと思う。
if (!my_container.empty()) my_container.clear(); // 要素が空かのチェックつき。こう書くより
my_container.clear(); // こう書けば、要素のあるなしに限らずクリアしてくれる方が、私は嬉しい
ただし、最初のdeleteループでは、各要素に0を代入したりはしない。
すぐ次のdeleteで、各要素にアクセスできなくなるからね。
>>40 void clear() {
if (empty()) return;
42 :
デフォルトの名無しさん :2006/03/18(土) 17:59:42
オブジェクトの初期化を ob = 1 ってできないようにすれば 代入時にはコピーコンストラクタが呼び出せないのは 簡単にわかるのにっておもいました。 以上C++学習中の今日の日記
43 :
http://www.vector.co.jp/soft/win95/util/se072729.html :2006/03/18(土) 18:16:58
名ソフト TextSS の64bit化ってできない?
仕様的にdeleteのNULLチェックは入らないって話をどこかで見た覚えがある。 if(!foo) delete foo; は delete foo; で良いって話。 つまり重複開放も問題ない気がする。
ちがうー。deleteにヌルを渡しても無視してくれるだけだ。 恐ろしい勘違いをしているぞ。
>>37 MS のせいだな。
>>45 とか SAFE_〜() とか。
みんな auto_ptr() 使えばこんな議論も要らないのに。
スコープから外れる直前のポインタを delete したときはヌル埋めは不要。
スコープに残ってるポインタを delete したときはヌル埋めは有効。
auto_ptr() がうまく働いてくれる。
パフォーマンスを気にしたいところでは auto_ptr 使いたくなかったりするんだお
そういや昔同じはなしになったときに、生ポインタと比べてどれだけ遅いのか計ってた香具師がいたな 結果はきれいさっぱり忘れてしまったが
>>49-50 全部インラインで実装できるからパフォーマンスに影響は無いはずなんだけど。
実測して言ってるの? >49
インライン化はされるとは限らないんだお
インライン化はされないとは限らないんだお
>>53 だから遅くなるかもしれないことは避けるんだお
55 :
デフォルトの名無しさん :2006/03/18(土) 19:24:07
>>51 インラインで実装「できる」ことと
インラインで実装「しなければならない」ことは
ちゃんと区別しないと、どこへ行っても文盲扱いされるぞ
>>54 そんなこと言ってたら標準のテンプレートも boost もほぼ全滅だな。正気か?
「パフォーマンスを気にしたいところで」と言ってるんだお そういうところでは boost なんてもってのほかだお
58 :
51 :2006/03/18(土) 19:45:50
>>55 あぁ「インラインで実装」じゃ意味がわからないな。
「全部インライン展開できるはずだから〜」に言い換えておこう。
>>57 速度は実測が基本。
原因が明らかになる前にコードを劣化させるなんてもってのほか。
まあ、deleteの話に戻るが、例外処理で判定すんのが面倒だからNULL代入してるだけ。 一律 delete 並べれば良いだけだから。
>>60 それも auto_ptr のほうがいいだろ。
やっぱり実測しろって展開になったw 誰かやれよ
>>39 > delete 自体は問題なくてもデストラクタが複数回呼ばれちゃいかんだろ?
一つのインスタンスに対してデストラクタが
複数回呼ばれるロジック自体がおかしい、直すべきだと思う
>>40 >>41 の通り、あんまし理由になっていない希ガス
>>60 > まあ、deleteの話に戻るが、例外処理で判定すんのが面倒だからNULL代入してるだけ。
ごめん、意味判らない
自分でdelete呼んだら もうそのコードは間違っているという認識だけどな Boostでdeleteを検索すると ptr_containerさえ一個もなかったりする
65 :
デフォルトの名無しさん :2006/03/18(土) 21:06:40
直接 I/O したら もうそのコードは間違っているという のと同じ論法だな
>>65 むしろそっちのほうがまだ納得できる理屈なんだが
67 :
デフォルトの名無しさん :2006/03/18(土) 21:41:21
>>66 せいぜい、間違ったコードでレスしてくれたまえ
コンストラクタ・デストラクタにくくって話をしてる奴と、話をしてない奴がいる。
TextSS のWindowsXP(Professional)64bit対応化おながいします もしくは64bitにネイティブ対応したテキスト置換ソフトありますか? そういや64bitにネイティブ対応している2chブラウザてありましたっけ?
auto_ptrのパフォーマンスを気にするのなら、そもそもc++を選択しているのが 間違っているような気が…… まあ、パフォーマンス気になる部分をクラスに切り出して、その中でチューニング するのが程良い妥協案じゃない?
boost::scoped_ptrは? それすら嫌なら自分で作れば?
質問です。 数値を取るようなテンプレートを用いたクラスを作成し、継承して利用します。 たまたま2箇所で同じ数値を渡して特殊化した場合、staticメンバが 共有されるのはしょうがないことですか? 文章だけだとわかりにくいので例で。 サイズをTで渡すと、継承したクラスのインスタンス数をカウントし、 そのメモリ容量を返す以下のクラスを考えます。 template <int T> class Count{ public: static int num; Count(){num++;} ~Count(){num--;} static int getmem(){ return num * T;} }; template <int T> int Count<T>::num = 0;
ここで、以下のようにクラスA,B,Cを作ります。 A,Bはサイズが同じ。 class A : public Count<8>{ int i,j; }; class B : public Count<8>{ long long l; }; class C : public Count<16>{ long long l,m; }; int main(int argc,char** argv){ A a1,a2,a3; B b1,b2; C c1,c2,c3,c4; printf("A = %d\n",A::getmem()); //8*3=24を期待 printf("B = %d\n",B::getmem()); //8*2=16を期待 printf("C = %d\n",C::getmem()); }
Aは3つ、Bは2つインスタンスがあるので、printfした時は24,16が 表示されて欲しいのに、ともに40が表示されてしまいます。 このような現象を防ぐ方法はありませんか? (Countが<int T>をとるのではなく、<class T>として<A>や<B>、<C>で特殊化し、 getmemではnum*sizeof(T)なら対応できるのはわかるのですが、 今回はこのCountに相当する部分がライブラリで変更できない)
void foo1(){ ... ++bar; ... } void foo2(int hoge){ ... bar*=hoge; ... } 上記のように、一部分だけ違う関数が必要なんです。 引数が変わり、また非常に多く呼び出される関数なのですが、 重複したコードを書かないようにする、コストの低い良い方法ってないでしょうか?
>>72-74 Count が変更できないなら無理。
そのライブラリの設計ミスか、そのライブラリが
想定していない使い方をしてるんだろう。
>>75 void foo_first(int& bar);
void foo_last(int& bar);
void foo1() { int bar; foo_first(bar); ++bar; foo_last(bar); }
void foo2() { int bar; foo_first(bar); bar*=hoge; foo_last(bar); }
first をコンストラクタ、 last を
78 :
77 :2006/03/19(日) 00:08:05
ごめんしくじった。 first をコンストラクタ、 last をデストラクタとし、 int bar をメンバとするクラスを作るといいかも。
その、一部分だけ違うところを、関数オブジェクトをとるようにするとか。
>>77 ネストの深い所にあって、前後を分割できないんです・・・
>>79 引数の数や型が違う場合に上手く出来たでしょうか?
ちょっとやってみます。
>>80 boost::bindなんかを使って引数の数などを揃える。
>>70 > auto_ptrのパフォーマンスを気にするのなら、そもそもc++を選択しているのが
> 間違っているような気が……
その理論だと、すべて「アセンブラでかけ」という結論になっちゃうよ。
極論房はこれだからダメなんだよ。
ソフト開発に極論はありませんがな。
auto_ptr のパフォーマンスを疑うようなやつはコンパイラ実装者を馬鹿にしすぎ。
>>82 auto_ptrのパフォーマンスを論じてんのが極論なんだろ。
>>81 ライブラリが必要なんですね。
とりあえずコピペで行きます。。
だから適当なコード書いて実測しろと 話はそれからだ
実測値とか依存になりえるもの全てに依存した数値だから困る てかパフォーマンス以外にもautoptr使いたく無い場面ってあるある
日本語が酷い事になってるが突っ込みは無しで
使えない(vectorの要素とか)場合なら分かるけど 使いたくないって・・どんなんやねん?
>>87 そんな微妙な最適化などすべきじゃないだろう。
ソースコードを最適化して、
アセンブラレベルで見たら、加算命令がひとつ消えていました。
最適化は成功したようです。
これは違うだろ?
91 :
70 :2006/03/19(日) 02:10:38
>82 直後の2行は無視ですか。そうですか。 auto_ptrて、標準C++ライブラリでもかなりオーバーヘッドの少ないクラスだよね? そのオーバーヘッドが気になるなんて、どういうデータ構造にしているんだろう? プログラムの大半がポインタアクセスになるようなプログラムでもないかぎり、 そんなにひどいことにはならんと思うけど…… #流体シミュレーションとか有限要素解析とか、そっち系かな?
>>89 まぁ確かにautoptrの挙動で困る場面ならautoptr使えないようになってるけどな。
使わなくて済むんなら使わなくていいんじゃないか? C++にはいろいろな選択肢がある、というだけだし
>>91 標準C++ライブラリと比較してオーバーヘッドを語られてもなぁ。
そんな話は意味ないだろ。
>#流体シミュレーションとか有限要素解析とか、そっち系かな? そっち系なら、生ポインタ推奨なのかな 特殊用途だとは思うけど
スマートポインタのパフォーマンス気にしないなら、JavaいけJava
いやDやろうぜ 業務には使えないが
もういいから好きなの使いなよ
100 :
70 :2006/03/19(日) 02:46:09
>95 auto_ptrのオーバーヘッドがどの程度か示さずに語られてもなぁ。 そんな話は意味ないだろ。 >96 でしょうね。普通、データ数が物凄いことになるから、データにアクセスするときの オーバーヘッドがバカにならない…… チューニングの最後の方には変わりないけど、そこまで踏み込まなきゃいけない ことが多々あるようですね。
>>100 auto_ptrなんて、生のポインタを使うのとまったく同じなわけだが。
まさか今日び、テンプレートをサポートしていながら、
インライン展開をサポートしていないコンパイラも珍しい。
インライン展開されると不具合が出るコードktkr
104 :
70 :2006/03/19(日) 12:36:24
ああ、そりゃそうか。 ポインタ自体のオーバーヘッド(ポインタごしのアクセス / 直接アクセスの違い)と ごっちゃにしていたよ。 auto_ptrとしてのオーバーヘッドはポインタのコピー(移動)ぐらいか。
テンプレートを使うデメリットは、コードサイズの増加?
コードサイズの増加は、手書きでも同じようにコーディングしたらあんまり 変わんないんじゃない? どっちかというと、テンプレートの欠点は ・コンパイル時間の増加 ・(externを実装したものが少ないので)ヘッダーに実装詳細まで 含まれるのでゴチャゴチャする のような気がする
確かにヘッダに実装書くのきもちわるい
>>100 鸚鵡返しは、低能の証だと何度言ったらわかるんだ?
109 :
70 :2006/03/19(日) 13:50:15
いや、コメント考えるのタルかったんで。何度も言われた記憶ないし。 で、auto_ptrのオーバーヘッドってなに?
>>110 禿同。あれをsmart_ptrと名付けなかった連中を誉めたい。
112 :
70 :2006/03/19(日) 14:11:56
内容の無いコメントするのも無能の証だとおもうけど? auto_ptrはauto_ptrでsmartだと思うけどね。 あれのおかげでRAIIとか所有権の明確化/移動がやりやすい。 確かに気を付けないと大怪我するけど、それは「C++だから」ということで。
数字コテ化するのは煽りあいが泥沼化してる証だぜ
STLのは、auto_ptrでいいと思うけどね。 smartっていうなら、boostのshared_ptr見たいなやつだろう。 こっちは、確かにオーバーヘッドがあるけど、目的が違うしね。
もう、70は感情にまかせて書いてるだけか。
116 :
デフォルトの名無しさん :2006/03/19(日) 19:57:53
俺が令状だ
話をぶった切ってすみません、質問させてください。 template <template <int> class apply, int n> struct applier { enum { value = apply<n>::value }; }; template <int n> struct add { template <int m> struct result { enum { value = n + m }; }; }; template <int n, int m> struct applier_add { enum { value = applier<add<n>::result, m >::value }; }; int main() { std::cout << applier_add<2,3>::value << std::endl; } これが VS.net のコンパイルできて g++ 3.4.4 でコンパイルできないのは何ででしょうか? また、これを g++ でコンパイルできるようにするにはどうしたらよいでしょうか? g++で出るコンパイルエラーは↓です main.cpp:11: error: type/value mismatch at argument 1 in template parameter list for `template<template<int <anonymous> > class apply, int n> struct applier' main.cpp:11: error: expected a class template, got ` add<n>::result'
>>117 add<n>::template result
>これが VS.net のコンパイルできて g++ 3.4.4 でコンパイルできないのは何ででしょうか? add<n>::resultがテンプレートであることは実体化させてみるまで分からない。 だから、「型でもテンプレートでもないもの」と推定される。 型やテンプレートを期待している場合は、それぞれtypenameとtemplateキーワードが必要。
120 :
119 :2006/03/19(日) 20:21:21
VS.netでコンパイルできるのは、単にコンパイラが甘いだけ。
ACDK (Artefaktur Component Development Kit)っていうライブラリ使ったことある人いませんか? このACDKのコアライブラリがJavaっぽいクラスライブラリで、(acdk::lang::StringBufferとか) なかなか使えるんじゃないかとおもってるんですが。
久しぶりに質問者の意図が全くわからん質問だな
C++使いにはJavaっぽいと言われて良さそうだと思う人は少ないのではないかと思う。
「Javaっぽい」という言葉が好意的に受けいれられるのはJava使いの間だけ!
>>123-125 >C++使いにはJavaっぽいと言われて良さそうだと思う人は少ないのではないかと思う。
それもそうだ。了解です。
まだ、C++初心者なんですが 参照で,アンパサンド 「 & 」 で宣言して かつ、初期化が必要と知ったのですが この参照という行為自体 何か、特別な意味合いがあるんでしょうか 学習していくうちに、必要性が出てくるのなら覚えておきたいですが あまり必要性が無いなら、軽い知識として覚える程度で良いのでしょうか あと、C言語なら、ポインタなら%pを使ってアドレスがみれて %xなら16進数等、それぞれの変数に対する表現方法 があるのは自明の理だとおもいますが、C++では、また別の 構文が有るのでしょうか、初心者なので、屁みたいな質問かもしれませんが できれば教えて頂きたいです
参照を使うべきか、ポインタを使うべきかは、適材適所。両方同程度に使えるようにしておいた方がいい。 ポインタと参照で、おそらく一番違う点は、参照は「常にオブジェクトを指している」ことだ。 この制限があるので、より安全に使えることが期待できる。 int i = 1; // 整数型 int* ptr = &i; // 整数型へのポインタの初期化 int& ref = i; // 整数型への参照の初期化 *ptr = 2; // ポインタを介したアクセス ref = 3; // 参照を介したアクセス int* qtr; // qtrの指す先は不定 qtr = 0; // qtrはオブジェクトを指さない(ぬるぽ) int& ref2; // エラー。参照先が指定されていない int& ref3 = 0; // エラー。何も指さない参照は許されない int& ref4 = *qtr; // 酷い例 上記例のように、参照の場合、初期化やアクセスの際に*や&などの記号がつかない。 参照元の完全な別名として扱うことができ、コードがすっきりする。 また、C++では関数は値渡しがデフォルトだが、効率の観点で関数呼び出し時にコピーを作りたくないことがある。 この場合、定数参照渡しが「非常に良く」登場する。 void func(const int& ref) { return ref*2; } 後半の構文云々はprintfの書式指定子のことかな? 出力ストリームへの書式指定は、C++ではマニピュレータを使う。 cout << setw(3) << hex << 25 << endl;
C++なんかいらない、Cだけで十分 そう思っていた時期が俺にもありました
ボクシングには蹴り技がある そう思っていた時期が俺にもありました
131 :
デフォルトの名無しさん :2006/03/21(火) 07:31:11
禿は自分の基本方針として「新機能をやたら増やしてユーザを喜ばす、ようなことは避けたい」と言っている にもかかわらず、参照が TCPL の初版からあったのは "強い理由" があったからに他ならない
newで確保してファイルから特定の文字列を可変長読み込むみたいなのを作ろうと思うんだけど C++には動的配列拡張するCのreallocに対応する関数ってある?
>>132 new で確保した領域を拡張する操作は無い。
かわりに std::vector を使うのが正解。
struct C { int x; struct Y { int y1, y2; } y; int z; }; こういう構造体があるとき、C *p; に対して printf("%d\n", p->x); printf("%d\n", p->y.y1); printf("%d\n", p->y.y2); printf("%d\n", p->z); を for 文で書けないでしょうか?
>>134 いちおう書けるよ。余計なものがいっぱい付いてくるけど。
余計なものって何さ
137 :
135 :2006/03/21(火) 09:05:37
つまり、止めとけってことね。元のソースで何が不満なのさ?
>>136 size_t const offset_to_int[4] とか、
boost::function<int& (C&)> int_by_index[4] とか。
offsetof(C, y.y1) って有効だっけ?直接のメンバしかだめ?
>>137 実際はメンバがもっと多くて処理も複数行に渡ってる、つまり
DoSomething1(p->Member1);
DoSomething2(p->Member1);
DoSomething1(p->Member2.SubMember1);
DoSomething2(p->Member2.SubMember1);
DoSomething1(p->Member2.SubMember2);
DoSomething2(p->Member2.SubMember2);
DoSomething1(p->Member3);
DoSomething2(p->Member3);
// ... まだまだ続く
みたいになっていて、一見しただけでは処理したいもの全部に
対して本当に処理しているのが分からないからです。これが例えば
int table[] = {C::Member1,C::Member2::SubMember1,C::Member2::SubMember2,...};
for (int i = 0; i < n; ++i) {
DoSometiong1(p.table[i]);
DoSometiong2(p.table[i]);
}
みたいに書ければ見通しがよくなるのですが。
>>139 よしわかった。
じゃぁまずは offsetof 使ったやつを。
C が POD 限定になるうえに offsetof(C, y.y1) が怪しいが、
とりあえず
>>134 の C についてコンパイルと実行はできた。
void print(C* p)
{
static size_t const offset_to_int[4] = {
offsetof(C, x),
offsetof(C, y.y1),
offsetof(C, y.y2),
offsetof(C, z),
};
for(int i = 0; i < 4; ++i)
{
printf("%d\n", *reinterpret_cast<int*>(reinterpret_cast<char*>(p) + offset_to_int[i]));
}
}
offsetof(C, y.y1) は offsetof(C, y) + offsetof(C::Y, y1) とすれば問題ない。
無駄にBoost.Lambdaを使ってみる。 #include <iostream> #include <boost/function.hpp> #include <boost/lambda/lambda.hpp> #include <boost/lambda/bind.hpp> #include <boost/lambda/casts.hpp> struct C { int x; struct Y { int y1, y2; } y; int z; }; int main() { C c = { 1, {2, 3}, 4 }; using boost::lambda::bind; using boost::lambda::_1; boost::function<int (const C&)> arr[] = { bind(&C::x, _1), bind(&C::Y::y1, bind(&C::y, _1)), bind(&C::Y::y2, bind(&C::y, _1)), bind(&C::z, _1), }; for (int i = 0; i < 4; ++i) std::cout << arr[i](c) << std::endl; return 0; }
CがPODなら共用体を使うという手も使えるだろう。 union Hoge { C Foo; int Bar[4] };
>>143 これを
>>140 に最適化してくれるコンパイラがあれば神なんだが。
と思ってとりあえず iostream を cstdio に置き換えてから
gcc にアセンブリ吐かせてみたが、悶絶した。駄目だ。
>>144 Hoge x に対して &x.Bar[1] == &x.Foo.y.y1 が成り立つと証明できる?
構造体のほうにはパディングが入る可能性があるからダメだと思うんだけど。
アライメントを調整すればいいだけだろ
そんなキモイコードは書きたくない。
doxygenに食わせたら、構造体のメンバ一覧がperlで出るから、 それ使ってコード生成したら?
巡回用のイテレータを作れば? そうすりゃalgorithmも適用できるから2重にお得 #include<iostream> struct C { int x;struct Y {int y1, y2;} y;int z; struct iterator{ C*c;int&(**pos)(C*); explicit iterator(C*c,int&(**pos)(C*)):c(c),pos(pos){} int&operator*(){return (*pos)(c);}iterator&operator++(){++pos;return*this;} friend bool operator!=(iterator a,iterator b){return a.c!=b.c||a.pos!=b.pos;} }; iterator begin(); iterator end(); }; namespace{int&Cx(C*c){return c->x;}int&Cy1(C*c){return c->y.y1;} int&Cy2(C*c){return c->y.y2;}int&Cz(C*c){return c->z;} int&(*table[])(C*)={Cx,Cy1,Cy2,Cz};} C::iterator C::begin(){return C::iterator(this,table);} C::iterator C::end(){return C::iterator(this,table+sizeof(table)/sizeof(table[0]));} int main() { C c = {1,{2, 3},4 }; C::iterator it = c.begin(),end=c.end(); //for_each + ostream_iteratorでも可 for (;it != end;++it) std::cout << *it << std::endl; return 0; }
最近constのメリットがあんま見出せない気がするんだが・・ すでにビット的定数性のないクラスなんていくつも出てきたし、 スレッドセーフとか言うわけでもないし、なんのためにがんば ってconstつけてんだかわかんねー。 唯一、 void f(const string& s) とかで operator動かせて、f("hoge")って呼べるくらいしか 思いつかない。
>>152 うっかり書き換えてしまうのを防ぐことができるじゃないか。
いつの間にか const スレが落ちてるのに気づいた。
>>152 void f(const string &s);
だと、
f(s);
としたときに、sの値が変わらないことが保証される。
「値が変わらない」の正確な意味は型によるけど、
たとえ内部表現が変わっても観測可能な振舞は変わらないように
const性が定義されてることを期待できる。
これで十分じゃないか?
いやあ、まあそれはそうなんだがさ、それだけのためにちょっと 手間がかかりすぎる気がするなあと。 stlもconst_iteratorとかさ・・。もう疲れたよ。 全てつけるのやめるとすると、上の以外なんか問題ってあるん だったっけ?
>>155 静的な定数テーブルがプロセス間で共有できない。
または ROM に配置できない。
>>153 constスレとカンマスレを偲ぶ人多いね。
良スレだったってことですね。
>154 ほら、保障っつってもさ、const_cast程度で外されちゃうし、 大した保障じゃないなら、もう void f(string &s); でいいんじゃないのかなーとか思うんだよね。そうするとさ、 void getHoge() const{} これは意味的定数性だからconstにして、メンバはmutableつけて 対策してと・・とか色々考えるのから開放されるしさ。 そもそもきっとconst導入した人は、ビット的定数性なんて問題を 想定してなかったような気がするし、そうするともう役目を終えてる というか、なんかほとんど効力がない機能のような気がするんだよなあ。
んじゃconstは気が向いた時に付ければいいってことで
ま、愚痴ってもしょうがないか
>>152 値セマンティクスのクラスにはconstをしっかり考えてやるべきだけど、
参照セマンティクスのクラスはあまりconstを考える必要はない。
というのをどこかで読んだ覚えがある。
>>149 >>151 C は自分で作ったクラスではないので、いじらずに済ませたいのです。
Interface Pattern はアリですが、もっとシンプルなのが無いかと思いまして。
>>150 C++ の範囲内でやる方法は無いですかねえ。
>158 >const_cast程度 程度じゃねえよ、const_castは実装のための最後の手段の1つで、 そうホイホイ使うような物じゃないだろ。 constは単純なread onlyインターフェイスを生成する手段の一つだと思ってる。 read onlyインターフェイスが要らないクラスなら、無くてもいいんじゃね。
const_cast とタイプすると罪悪感に苛まれるな
俺のやっていたことはすべて間違っていたのか? と、途方にくれるな
今のところ、幸いにもこういう風にしかconst_castは使ったことが無い。 class Hoge { public: const_reference operator [](std::size_t i) const {/* 〜 */} refernece operator [](std::size_t i) {return const_cast<reference>(static_cast<const Hoge&>(*this)[i]);} };
>>168 こっちのがよくね?
reference operator [](std::size_t i);
const_reference operator [](std::size_t i) const {return const_cast<Hoge&>(*this)[i];}
int a[MAX] などと配列のメンバーを持つクラスにおいて、 コンストラクタで、メンバーイニシャライザで初期化するには どうすればよいでしょうか?
ということは、コンストラクタの実装で、for で回す等して初期化するしかない んですね。ありがとうございました。
>158 ちょっと、言い方がおかしかったかも。 constの価値がないと言ってるんじゃなくて、概念的定数性の存在価値は あるのかってことを言いたかった。 Java的に言うとimmutableパターンによるスレッドセーフなオブジェクトと シャローコピー時のデータ汚染の回避みたいなメリットが、概念的定数性 だとmutableによって、当然どっちも失われるわけだから、苦労する意味は いったいあるのか?みたいなことを言いたかった。
174 :
デフォルトの名無しさん :2006/03/22(水) 01:14:34
int foo() { bar(); { static int si = 123; return si; } } みたいなC++の関数があるとして、si用のメモリが123に初期化されるのは どのタイミングでしょうか? 1 プログラムが実行開始した瞬間 2 main関数到達前 3 foo関数初回呼び出し直後 4 変数siの存在するブロックに初回に入ろうとする時 くらいの候補があると思うのですが。手持ちのコンパイラでは1でしたが、 標準で保障されているのがどこまでかが知りたいです。
>>173 その言い方だと mutable さえ使わなければ挙げてるメリットが得られるんだろ?
十分だと思うなぁ。
なんで mutable の使用が前提になってんの?
標準仕様じゃ決まってないだろ。 大抵はデータセグメントに配置されて、プログラムロード時に初期値が設定されるんじゃねーの?
178 :
174 :2006/03/22(水) 01:32:41
>176,177 ども。クロスプラットフォームなコードを書いている関係で、「PODなロー カルstaticオブジェクトの定数式による初期化」がスレッドセーフに行わ れるかどうかを気にしているのですが、スレッドが絡むと標準仕様では何 ともいえないですかね・・・。
>>178 大丈夫、どのスレッドかは兎も角、どれかのスレッドで最初に実行されるまでには
初期化されている。
まぁ、volatileつけないとどの道まともに扱えないわけだが。
>>179 いや、何の前提も加えずに大丈夫とは言えないだろう。
現行の規格ではスレッドについて何の言及も無いわけで、
規格に準拠したコンパイラがスレッドを考慮したコード生成を行うとは限らない。
>179 そうだっけ? 確か大抵の実装は関数に入る際にフラグをチェックして 初回ならば、コンストラタを呼び・・みたいに展開されるので マルチスレッドの場合はコンストラクタが2度呼び出されるので 危険だったような・・ だとすればPODの場合もアウトなので、その関数はまずシングル スレッドで一度呼び出されていないとまずくなると想定していて、 俺は怖いのでそうしてる。
183 :
182 :2006/03/22(水) 02:20:06
いや、ごめん、実装依存か?
http://gcc.gnu.org/gcc-4.0/changes.html The compiler now uses the library interface specified by the
C++ ABI for thread-safe initialization of function-scope static
variables. Most users should leave this alone, but embedded
programmers may want to disable this by specifying -fno-threadsafe-
statics for a small savings in code size.
gcc4.0はfunction-scope staticはthread-safeを保障しているみたい
VCはどうかな
184 :
182 :2006/03/22(水) 02:36:28
>175 概念的定数性ってメンバにキャッシュ処理的なことしてる場合に GetHoge()とかがメンバを変えるけど、意味的にはconstって ことだろ? class A{public: void GetHoge() const{a_ *= 2; return a_;} mutable int a_; }; でも、constにしたいからメンバをmutableにするって理解 だったが・・、なんか違うかな? んで、結局GetHogeはスレッドセーフじゃないし、immutable オブジェクトにもならないからメリットはなんだ?という ことを考えたが。
>>184 mutable を使えばそうなる。あたりまえ。
それは const の機能について「ほとんど効力がない」という理由にはならないだろ。
結局は、キャッシュや遅延評価を装備したオブジェクトから値を取り出す
メンバ関数に const 付けて mutable 使うか、非 const メンバ関数にしてしまうか
という2択で迷ってるだけじゃないの?
>185 >それは const の機能について「ほとんど効力がない」という理由には >ならないだろ。 いや、だからそれは173で訂正してると思う・・ > 結局は、キャッシュや遅延評価を装備したオブジェクトから値を取り出す > メンバ関数に const 付けて mutable 使うか、非 const メンバ関数にしてしまうか > という2択で迷ってるだけじゃないの? Yes。けど、"ただ"と言えるほど簡単な話ではないと思う。(EffectiveC++ で筆者は両者の方法は哲学的問題と言ってるが)。そして、今のところ自他 ともスマートな解決方法は聞いたことがない。 185はどっちの立場でやってる?
"ただ"→"だけ"
constスレとカンマスレってどこにあるの?
>>179 >まぁ、volatileつけないとどの道まともに扱えないわけだが。
kwsk
191 :
174 :2006/03/22(水) 07:45:15
どもです。最近のg++なら(PODでなくても)スレッドセーフに初期化される ので問題ないですね。しかし、MS/Sun/HP/Intel/..のコンパイラだとどうな の?というのが気になっている&コンパイラ買えないという感じです。 local staticは諦めて、 static int si = 123; int foo() { bar(); return si; } にすればOKでしょうか。
193 :
174 :2006/03/22(水) 08:02:43
194 :
デフォルトの名無しさん :2006/03/22(水) 09:18:28
195 :
174 :2006/03/22(水) 09:26:19
>194 すみません、もうちょい具体的に・・・
197 :
デフォルトの名無しさん :2006/03/22(水) 09:56:18
しつもんです、簡潔に
template <typename A,typename B>inline char *binary_pack(const std::map<A,B> &src,char *from)
{
*((int*)from)=(int)src.size();
from+=4;
for(std::map<A,B>::const_iterator i=src.begin();i!=src.end();i++)
from=binary_pack(*i,from);
return from;
}
という関数を作ったのですがg++(gcc3.4.4/FC4)で通らなくて困ってます。
エラー内容はiteratorのiが定義されてないということらしいのですが、
VC++7やgcc3.2.4あたりでは通ったり(警告でる)します。
同じ関数名でいくつか似たような機能のものを複数多重定義してますが、
mapでないvectorのiterator作ろうとしてもエラーでてしまいます。
-fno-implicit-templatesのようなオプションも無駄でした
(
http://www.sra.co.jp/wingnut/gcc/gcc-j.html#Invoking%20GCCより 。
たぶんiteratorの定義方法が正確ではないのかなと思ってるんですが
エラーの対処方法詳しくわかる方居たらご教授願えないでしょうか?
typename std::map<A,B>::const_iterator かな
200 :
198 :2006/03/22(水) 10:10:32
ありがとうございます! typenameつけたらwarningもでなくなり通るようになりました。
201 :
デフォルトの名無しさん :2006/03/22(水) 10:10:41
>>198 本当にコンパイル通ったのか?
再帰の実引数 *i は map の const_iterator が指し示す先で
再帰の仮引数 src は map そのものへの参照やんけ
そうじゃなくて、関数オブジェクトとスレッドセーフティの関係が知りたいってことだろ
>>197
STLportの便乗話だけど、VC7.1のビルドは特に何もしないで出来たが、 VC8のビルドは、configure.batを走らせてからでないとビルド出来ない。 多分もう誰でも知ってると思うけど、一応初心者用に書いておきます。
誤爆シマスタ
206 :
185 :2006/03/22(水) 12:36:58
>>186 > いや、だからそれは173で訂正してると思う・・
ごめん。見落としてた。
よく考えると、概念的 const のせいで苦労が増すというのがおかしいと思う。
スレッドセーフが必要なら、どのみち値の算出(〜設定)に同期が要る。
クラスが内部でやらなければ利用者に責任が押し付けられることになる。
シャローコピーしたところで概念的に const でさえあればデータ汚染にはならない。
>>184 の例がまずいのは、繰り返し GetHoge() を呼び出すだけで値が変わっていくから。
一般的なキャッシュ、遅延評価の実装では他の非 const 操作が行われるまで
外部に返される値は変わらない。この場合、他に非 const 操作がなければ
Immutable オブジェクトとしての性質を満たし得るだろう。
先にインターフェースを考えて、実装段階でキャッシュが必要になることを考えると、
immutable を使った概念的 const も妥当だと思う。
そろそろ標準でスレッドをサポートしてほしいな。
208 :
デフォルトの名無しさん :2006/03/22(水) 15:20:22
重くなるからいらない 今の定義で十分に対応可能だし
スレッドは一生無理でしょ 禿もそういってるし
210 :
デフォルトの名無しさん :2006/03/22(水) 15:31:52
C++自体が多重仮想記憶を「サポートする」機能を持たないのと同じ
マルチスレッドに対する挙動を仕様で決めてくれれば十分
sizeofに詳しいサイト求む
BCC5.6.4でこれをコンパイルすると、cが未定義だと怒られてしまいました。 共用体なので問題ないと思っていたのですが、何が問題なのでしょうか。 #include <iostream> using namespace std; union bits{ bits(double n); void show_bits(); double d; unsigned char c[sizeof(double)]; }; bits::bits(double n){ d = n; } void show_bits(){ int i, j; for(j = sizeof(double) - 1; j >= 0; j--){ cout << "ビットパターン/Byte" << j << ": "; for(i = 128; i; i >>= 1) cout << i & c[j] ? "1" : "0"; cout << endl; } } int main(){ bits ob(1991.829); ob.show_bits(); return 0; }
>>213 なんでshowのほうにbits::ねえんだよ
あとi&c[j]は括弧でくくれ、優先順位が違う
>>214 すごい単純ミスですいません。
ありがとうございました。
>207 boostじゃだめなの?
217 :
デフォルトの名無しさん :2006/03/23(木) 02:30:02
volatile つけるとどういう効果があるんでしょうか?
>>217 変数への読み書きが「副作用」とみなされ、最適化で削除されなくなる。
また、 const と同様にオーバーロードに使われる。
>>217 ちなみに所謂cv修飾のvなのでconstがつけれるとこならどこにでもつけれる。
# c は const
最適化で削除されたくない→volatileつける と考えると、実際どういう場合につけるべきなのか 難しいですね。一時変数は別に不要だとわかりますが クラスのメンバー変数は全部つけないといけなくなるのかな
>>220 コードから見ていつ変わるかわからん変数やオブジェクトにつけるべし。
具体例をあげると複数のスレッドから変更される変数やオブジェクトとか
メモリマップドI/Oなんかに対してつける。こういった変数やオブジェクトに
アクセスする時に最適化が効いてるととんでもないことになる。
大変なことになる一例をあげると下のコードで hoge をどっかスレッドがfalseにしても
最適化が効いちゃってると無限ループになっちまう。これを避ける為には hoge を volatileで修飾すべし!
bool hoge = true;
void hige() {
while(hoge);
}
>>220 削除されるのは変数じゃなくて、変数への読み書きだぞ。
メンバー関数に全部つけるとか、ただの糞コードに他ならない。
たとえばWin32のAPIとかconstのはずなのに宣言が f(void* p); ってふうになってるケースがあるからこれらを呼び出す時にconstキャストは多々つかいますわ。
ここでエスパー登場。 C 用に設計されたコールバックなどの汎用引数には ほとんど void* が引数として使われるので、そこに const T* を渡そうと思ったら const_cast が必要になる。 ってことだと思われ。
226 :
デフォルトの名無しさん :2006/03/23(木) 10:07:45
>>220 >最適化で削除されたくない
^^^^
必ずしも削除じゃないよ
普通に文脈解釈したときの意味が変わるような削除まで無限に許しているわけじゃない
本当に厳密なタイミングが必要な箇所だとか、a -= 0; みたいに意味なさそうに見える箇所だとか、
本来ならアセンブラで書くような性格を含んでいるところに、取扱注意と書いておくだけ
>>222 メンバ関数全部に throw() をつけるたり
非静的メンバ関数全部に virtual をつけたり
基底指定子全部に public をつけたり
C++ ってデフォが糞なの結構あるね
>>226 ではデフォルトで全ての変数をvolatile扱いしてほしいということですか。
228 :
デフォルトの名無しさん :2006/03/23(木) 10:26:08
>>227 必要な箇所に必要なキーワードを置くことにいやも好きもない
俺はドライに割り切ってるが、糞という表現がでてきたんで言い出したらキリねえぞってだけ
日本語でも勉強するか
230 :
デフォルトの名無しさん :2006/03/23(木) 11:10:32
えんざんしおーばーろーど
符号付き整数全てにsignedつけたり自動変数全部にautoつけたり
今c++を独習しているのですが、 #include <iostream> using namespace std; template <class T> class coord { T x,y; public: coord(T i, T j) { x=i; y=j; } friend ostream &operator<<(ostream &stream, coord ob); friend ostream &operator>>(istream &stream, coord &ob); }; template <class T> ostream &operator<<(ostream &stream, coord<T> ob) { stream << ob.x << ' ' << ob.y << endl; return stream; } template <class T> istream &operator>>(istream &stream, coord<T> &ob) { stream >> ob.x >> ob.y; return stream; } int main() { coord<int> i_ob(1,2); cout << i_ob << endl; return 0; } こういうコードコンパイルしたら「外部シンボルoperator<< ... が未解決」と怒られました。 どこを訂正すべきでしょうか?
>>232 #include <iostream>
using namespace std;
template <class T> class coord;
template <class T> ostream &operator<<(ostream &, coord<T>);
template <class T> istream &operator>>(istream &, coord<T> &);
template <class T>
class coord {
T x,y;
public:
coord(T i, T j) { x=i; y=j; }
friend ostream &operator<< <T>(ostream &stream, coord ob);
friend istream &operator>> <T>(istream &stream, coord &ob);
};
>>232 T x,y;
public:
coord(T i, T j) { x=i; y=j; }
- friend ostream &operator<<(ostream &stream, coord ob);
- friend ostream &operator>>(istream &stream, coord &ob);
+ template <typename U> friend ostream &operator<< (ostream &stream, coord <U> ob);
+ template <typename U> friend ostream &operator>> (istream &stream, coord <U> &ob);
};
-template <class T>
-ostream &operator<<(ostream &stream, coord<T> ob)
+template <typename U>
+ostream &operator<<(ostream &stream, coord<U> ob)
{
stream << ob.x << ' ' << ob.y << endl;
return stream;
}
-template <class T>
-istream &operator>>(istream &stream, coord<T> &ob)
+template <typename U>
+istream &operator>>(istream &stream, coord<U> &ob)
{
stream >> ob.x >> ob.y;
return stream;
>>234 メンバテンプレート使うと、BCC5.8.1では「このコンテキストでは<<が
曖昧です」とか言われる。BCCのバグらしい。
gcc3.4.2(MinGW)、VC8ではちゃんと通る。
236 :
デフォルトの名無しさん :2006/03/23(木) 19:58:46
どっちも一長一短だな // --- fig1 --------------------------- template <typename T> struct X { template <typename U> friend void f(X<U>&) { X<int> a; a.y = 0; } private: int y; }; main() { X<void> x; f(x); } この場合、 ・Borland 5.5.1 は private のみを問題視 ・g++ 4.1.0 は X<void> で宣言された f と X<int> で宣言された f が曖昧と言ってくる 俺は g++ に賛成
237 :
デフォルトの名無しさん :2006/03/23(木) 19:59:06
(
>>236 の続き)
// --- fig2 ---------------------------
template <typename T> struct X {
friend void g(X<T>&)
{
X<int> a;
a.y = 0;
}
};
main()
{
X<void> x;
g(x);
}
この場合、
・Borland 5.5.1 は X<void> で宣言した friend 権限は、X<int> には及ばないと言ってくる
・g++ は何も言ってこない
俺は Borland に賛成
238 :
デフォルトの名無しさん :2006/03/23(木) 20:11:32
あ、y の宣言忘れてる・・・ でも、わかるよな?w
>どっちも一長一短だな fig 2の方は何がしたいか分からんのだが。
240 :
デフォルトの名無しさん :2006/03/24(金) 00:22:11
>221 DQN発見..というのは言い過ぎかもしれないが..痛い。 別のスレッドがその変数に触るなら、mutexなりcritical sectionなり で排他制御するのが正しい。もしそれを省略してlock-freeなアルゴ リズムを採用したいのなら、volatileではなくメモリバリアを使え。
メモリバリアとvolatileは用途が違うと思うんだが。 片方はコンパイラ向けで、片方はCPU向けでそ?
242 :
240 :2006/03/24(金) 00:32:28
メモリバリアは両用だよ。gccの__asm__の最後の引数に"memory"を 渡した場合について調べてみれ。
============== ここまで読んだ ===================
gccの、しかも、__asm__みたいな超特定言語固有な話をされても・・・
>>240 volatile が必要になるようなケースで、volatile を書かずにメモリバリアを入れても駄目でそ。
っていうかメモリバリアってSMPじゃないと意味ないし。volatileはスレッドや割り込み処理でも
有効に使える・・というか正しく使わなくてはならない。
そもそも最適化で消えちゃうのってコンパイラとして問題な希ガス
>>240 DQN発見..というのは言い過ぎかもしれないが..痛い。
mutexなりcritical sectionなりを使ってもvolatileを使わなければ
コンパイラの最適化で無限ループになっても文句は言えない。
248 :
デフォルトの名無しさん :2006/03/24(金) 02:13:16
>>247 >mutexなりcritical sectionなりを使ってもvolatileを使わなければ
>コンパイラの最適化で無限ループになっても文句は言えない。
え??
>>247 さすがにグローバル変数の場合には volatile なしでも関数呼び出しの前には
値をストアするだろうし、後で参照すれば値をロードしなおすコードが出る出祖。
auuto 変数の場合にはコンパイルオプションによってはロードしなおさないコードが
でることもあるかもしれない。この場合には明示的な volatile が必要か。
またvolatile厨か…
vectorのような使い勝手で元から確保していた配列のサイズを オーバーしてしまった時に自動でリサイズしてくれるような クラスを作りたいのですが、 x[i] = x[i-1] + vx[i] * dt; と言うような感じのコードを実行したときに、 「x[i]」でリサイズが必要になった場合、 「x[i-1]」の参照が無効になってしまうと言う状態になってしまいました。 なにかこう言った状態を解決する方法はないのでしょうか? よろしくお願いします。
>>251 operator [] の戻り値を参照型じゃなくて値型にしていれば
そういった状態にはならない。
配列クラスへのポインタとインデックスの組み合わせを持った
プロキシオブジェクトを返すことでも解決できるかもしれない。
253 :
251 :2006/03/24(金) 13:57:18
>>252 値の代入は何かほかの方法を用意しておくしかないということでしょうか?
プロキシオブジェクトについてはしらなかったので調べてみます。
ありがとうございました。
>>249 bool hoge = true;
void hige() {
while(hoge);
}
大域スコープにあってもループ中にhogeを変更する明示的なコードが無いから
>>221 を
↓のように置き換えるコンパイラがあってもおかしくない。つかstrength reduceとかあたりまえ。
void hige() {
if (hoge)
for (;;)
;
}
autoだと変数がレジスタにしか割り当てられない可能性高いけどそれはまた別の話。
はいはいワロスワロス
どうやっても効率悪そうだな。 事前にresizeするか、↓じゃだめなの? prev = x[i-1]; x[i] = prev + vx[i] * dt;
>>255 それだったら、STLのvector使っても、あまり変わらないだろう。
257 :
251 :2006/03/24(金) 14:28:56
>>255 自分で使うだけなら事前にresizeするだけでもよかったんですが、
C言語もほとんどしらないような友人も使うので
できる限り単純にしておいておきたかったんですよね。
かといってデータの量もかなりあるので余り無駄なメモリも負担も増やせなくて…
258 :
251 :2006/03/24(金) 15:02:28
度々申し訳ないです。 一度も値が代入されていない変数の値を使う事は普通は無いと思うので、 リサイズする可能性があるのは代入演算子の左側の「x[i]」だけだと考えて、 x[i] = x[i-1] + vx[i] * dt; と言うような命令があったときに「x[i]」でリサイズして 配列をdeleteするのを、次に「operator[]」が呼ばれた時にする というのはありなのでしょうか? なにか問題が起きそうな気もしなくもないですが
副作用完了点をもう一度熟読した方がいいな。
260 :
251 :2006/03/24(金) 15:13:58
>>259 確かによくわかっていなかったです。
一度詳しく調べてみます。
移植性がなくなってもよいのなら、
>>251 の言うような事はできるかも
しれんが、少なくとも式の評価順序について曖昧な部分は、その
処理系の説明書にも書いてないだろう。
規格はそこまで縛ってないのだから。自分で調べるというのならそれでも
いいのだが。
262 :
デフォルトの名無しさん :2006/03/24(金) 15:50:24
STLでツリーって、どーつくるんですか?
263 :
嘘 :2006/03/24(金) 15:55:15
Boost Graph Library を使う。
「STL」でって言ってるだろうが、このカス
>>261 operator=のPOD型に関する評価順序は右から左と決まっているので、
右辺を評価した後で左辺を評価した時に配列やvectorの参照アドレス
が変わるのがまずいって話でしょう。
あとoperator+とかは左から右なので、例えばx[i} + x[i + 1]という式が
あったとして、x[i + 1]がxの参照を変更してしまうような操作であった場合、
x[i]が参照で返されているとアクセスエラーが出る可能性があります。
だから
>>252 さんのおっしゃられる通り、値返しにすれば、アドレスが変化
しても問題がないように思います。
266 :
デフォルトの名無しさん :2006/03/24(金) 16:01:17
配列でつくって、インデックスの差で構築するのが無難ですかー?
>>265 いやいや、今の話はPOD型ではなくて、自前のクラスの話では。
まあクラスにしても同じなんだが。
>>251 いっそstd::map使え。キーにstd::size_tを指定してしまえ。
>>262 漏れは、各ノードに「親ノードへのポインタ」と「子ノードへのポインタのリスト」を持つようにした。
struct tree {
tree* parent;
std::list<tree*> children;
T value;
};
実際にはstructではなくclassで、各メンバはprivateにした上でアクセサを定義。
イテレータとして
1. 子ノードイテレータ
typedef std::list<tree*> children_type;
typedef typename children_type::iterator children_iterator;
2. preorder_iterator(begin()、end()で先頭・末尾の次を取得でき、全ノードを前置順走査する)
3. postorder_iterator(rbegin()、rend()で先頭・末尾の次を取得でき、全ノードを後置順走査する)
を用意。tree::iteratorにpreorder_iteratorをtypedefしておく。
子ノードの追加はoperator+, +=、削除はoperator-, -=
これにストリーム入出力つけて300行くらい。でもコード見たらboost::iterator_facade使ってた。
「STL」でって言ってるだろうが、このカス
なんか変なのが混じってるようだが、マジレスすれば、 STLにツリーは用意されてません。 もしSTLっぽいツリーを実装したいなら、「tree.hh」でググるべし。
272 :
デフォルトの名無しさん :2006/03/24(金) 17:03:16
>>269 始めはこの形を検討しました。
ただ怖いのは、ポインタが無効になることなんですよね。。
やっぱり配列かなぁ。。
Cらしくない。。
273 :
デフォルトの名無しさん :2006/03/24(金) 17:05:53
>>271 おぉ。
面白そうなので、ソースを見てみます。
>>273 ここが C++相談室 ならお前の言うことは正しい。
しかし、ここは 【初心者歓迎】C/C++室 Ver.25【環境依存OK】 なのであった。
275 :
デフォルトの名無しさん :2006/03/24(金) 17:11:18
今後このスレは【初心者歓迎】C/C++室 Ver.25【環境依存OK】 となりますた
うおっ すまん。素でまちがえた。
>>272 ポインタが無効になる、というのはどういうこと?
見落としてるのかな。
279 :
デフォルトの名無しさん :2006/03/24(金) 17:21:02
>>278 コピーした場合とかですね。
イテレータに詳しい方ならわかるはず。
>>279 ううん…?
要素追加時にnew、要素削除時に子要素もろともdelete。
treeのデストラクタで全要素delete。
コピーコンストラクタでは構造通り全要素追加。
std::list<>で持っているのはノードへのポインタだから、deleteされるまで無効にはならないはず。
各イテレータは、直下の子要素追加・削除時に無効になるけれど、それはSTLでも同じことじゃないかい?
それとも見当はずれのことを言ってるのかな('A`)
要素を管理しきれないなら木なんか作るな
>>254 >関数呼び出しの前には値をストアするだろうし、後で参照すれば値をロードしなおす
^^^^^^^^^^^^^^^^^
目の不自由な人乙
それとも理解力ないのか?
283 :
デフォルトの名無しさん :2006/03/24(金) 17:58:51
>>280 気にしていたのは、
tree<...> x, y;
xつりーを構築;
y = x; //yは有効なつりー?
とかです。
よく考えてみたら、yの木を根から再構築すればいいだけの話ですね。。
284 :
デフォルトの名無しさん :2006/03/24(金) 18:00:56
>>283 日本語おかしいですね。
"y" -> "x"
もしくは、
"yの木を"->"yの木は"
285 :
デフォルトの名無しさん :2006/03/24(金) 18:03:55
>>283 日本語おかしいですね。
"y" -> "x"
もしくは、
"yの木を"->"yの木は"
>>286 ひえーBCCだとコンパイルできない。
BCCぜってー変だよこれ。
VC7.1だと通るね。
BCC なんて時代遅れだ。
289 :
デフォルトの名無しさん :2006/03/24(金) 23:48:27
C++が読めないので教えください。 宣言の初期化みたいなんですけど、 コメントの 1、2、3 と return文 4 の ところです。 #include <stdio.h> class test { public: test() {}; ~test() {}; static test* ins(); static test ins1; static test* ins2; static test* ins3; }; test test::ins1; // 1 test* test::ins2 = test::ins(); // 2 test* test::ins3 = (test*)NULL; // 3 test* test::ins() { return new test(); // 4 }
>>289 1から3は静的変数の定義。
クラスの静的変数は、クラス内の宣言とは別にどこかcppファイルで定義が必要。
普通のグローバル変数がヘッダで宣言し、どこかで定義するのと同じこと。
2と3は初期化子を指定している。
4は動的にオブジェクトを作っている。誤解を恐れず言えばmallocのC++版と言ったところ。
これくらい自分で何とかしろよ。
291 :
デフォルトの名無しさん :2006/03/24(金) 23:56:43
>> 290 ありがとうございます。感謝です。 C++は暗号みたいで難しいです。
ついでに言うと、こんなコード参考にしちゃいかんよ。 このコードだとメモリリークする危険がありますな。
289ではないけど freeがないからリークの可能性って事 C言語はまだ良く分からないけど
294 :
由美子 :2006/03/25(土) 00:32:26
コマンドプロンプト-bcc32 kon.c NTVDM CPUは不正命令を検出しました。 CS:270c IP:0103 OP:63 3a 5C 42 6f アプリケーションを終了するには[閉じる]を選んでください。 と表示され.odjファイルしか作れません。三つファイルが出来るのですよね? かれこれ2時間格闘しています。 誰か、何が悪いのかわかる方いらっしゃいますか? よろしくお願いします。かなりの初心者で申し訳ありません
295 :
デフォルトの名無しさん :2006/03/25(土) 00:57:53
core吐いてないか? それを見てなんとか汁
296 :
デフォルトの名無しさん :2006/03/25(土) 01:21:03
本物のプログラマはコアダンプを読める。
本物のプログラマはechoとリダイレクトでプログラムする。
298 :
由美子 :2006/03/25(土) 02:44:13
core?ですか?わかりません。初心者で申し訳ないです。どーやって調べれば見つかりますか? ホントお願いします。泣
>>265 '=' も '+' も評価順序は決まってないよ。
300 :
デフォルトの名無しさん :2006/03/25(土) 02:54:45
NTVDM つってるのに core かよ・・・ 何ともご立派なセンセイだな
あるクラスのインスタンスが、状態遷移を持っていて、 その状態によって、使えるメソッドが決まる、という設計は やっぱ糞かなw
>>301 糞かどうかはわからないが、バグの元になることは確かだ。
asshole->*
304 :
デフォルトの名無しさん :2006/03/25(土) 09:40:59
屁みたいな質問内容だと思うけど出来れば教えてください 以下のソースで動かしました #include <iostream> using namespace std; class Test{ public: char *ary;void print(char *ary);Test(char *ary);~Test();}; Test::Test(char *ary){cout << "コンストラクタ\n";cout << ary << '\n';} Test::~Test(){cout << "デスクトラクタ\n";cout << ary << '\n';} void print(Test *obj){obj->ary = "print()\n";} int main(){Test obj("Hello");print(&obj);return 0;} で、デスクトラクタは、オブジェクト破棄の後に出る関数と捉えているんですが 結果、print()という関数の前にデスクトラクタが出てきました objが破棄されたにもかかわらず、objの参照渡しがなされてるようで 不思議です。まだまだクズの初心者なんで、学習量が少ないんですが 出来れば教えてください
>>304 >結果、print()という関数の前にデスクトラクタが出てきました
どうやってこれを確認した?
>>304 コンストラクタ
Hello
デスクトラクタ
print()
と出力されて何も問題ないようだが。
ちなみにprint関数の中では代入しているだけで画面への出力はぜんぜん行っていないからな。
>>288 何を言う!BCCと言っても、現時点では最新バージョンの5.8.1だぞ!
(タイムスタンプ 05-12-01 10:01)
・・・・・と言ってもむなしいだけだよな。氏ねよBCC・・・・
早見優!
>>304 挙動については
>>306 だと思うが、気になったので老婆心から一言言わせてくれ。
クラスTestのメンバにvoid print(char* ary)があり、かつ、クラス外にもvoid print(char* ary)がある。
こういうケースでは、クラスメンバの方だけを使う方がいいと思う。
あと、メンバ変数char* aryと、コンストラクタの引数char* aryが同名だけど、ちゃんと混乱せず使えてる?
挙動がわからない状況では、まぎらわしい記述は避けた方がいいよ。
>>309 の「クラスメンバの方だけを使う方がいい」というのは無視してくれ。
すまんこ
311 :
304 :2006/03/25(土) 20:34:31
まだ、勉強中なので、混乱した状態での把握をしておこう と思っています。さすがに、長いプログラム書くときに こんな同名の変数やら、メンバやらは区別しようと 思ってます。
312 :
デフォルトの名無しさん :2006/03/25(土) 21:03:46
>>304 これやってみな
main()
{
cout << "--------------" << endl;
Test obj("Hello");
cout << "--------------" << endl;
print(&obj);
cout << "--------------" << endl;
}
313 :
デフォルトの名無しさん :2006/03/25(土) 21:05:57
>>311 > こんな同名の変数やら、メンバやらは区別しようと
これは、ちょっと違う
変数名は別に同じでも構わない
初心者は別だが
あるクラス定義ヘッダ中で、 int getHoge(int a) const; とかかれていた所があったのですが、このconst はどういう意味なのでしょうか?
クラスのメンバ変数を書き換えません。
俺も数日前同じ質問したな おまいらありがと
static int getHoge(int a); とどう違うの?
比較するなんて考えたくないほど全く違う
>>318 端的に言えばthisポインタの有無。
だめな説明だな、これじゃ。
>>318 だとgetHoge()の中でメンバー変数に一切アクセスできない。
>>315 だとgetHoge()の中でメンバー変数を読むことだけはできる。
322 :
デフォルトの名無しさん :2006/03/26(日) 00:40:35
ヘッダファイルにインクルードしたくないから ポインタでかまわない場合は、 class CFoo; class CAAA { protected: CFoo *pFoo; }; こんなふうによくやりますけど、 このCFooってクラスがnamespace付きの場合って、 無理なんでしょうか。 class hoge::CFoo; class CAAA { protected: hoge::CFoo *pFoo; }; こういうのは怒られてしまうんですけど、 ヘッダにインクルードする以外手はないんでしょうか
namespace hoge { class CFoo; } じゃだめか?
素朴な疑問だが、コンストラクタが複数ある場合に初期化リストって めんどくね? 俺はパフォーマンス多少悪くなるけど、共通関数作って呼んじゃってる けど、みんなどうしてる?
そうしてる。
がんばって初期化リスト使う 極まれにマクロつかったりする
>>324 メンバ多すぎるんじゃね?
private にネストしたクラス作るとうまくいったりする。
>>324 クラスをインターフェイスと実装に分離し、非公開継承する
pimpl
330 :
デフォルトの名無しさん :2006/03/26(日) 10:41:17
>>324 どんなにきつくても悪魔のささやきには負けない
俺はデータブロックとみなすかインターフェースとみなすかで 早めにPODとクラスに分けちゃってクラスの書き方は速度をあんまり考えてない。
>>331 お前さん、 POD の意味わかってる?
plain old dataだろ?ハゲを舐めるなよ
そうなると
>>331 の意味がわからんわけだが。
別にフサフサはムリして理解しようとしなくていいぞっと
いや、ハゲが言葉の意味を誤解してるんだろ。 struct S { std::string s; }; この S はデータブロックだが POD じゃないぞ。
338 :
デフォルトの名無しさん :2006/03/26(日) 14:23:56
>>323 おお、なるほど!!
ありが`
じゃあついでにもう1こ。
クラス内クラスを別ヘッダから宣言だけしたい場合はどうすればよいんでしょ。
class CFile
{
class CHandle
{
int a;
};
};
こういうクラスがあったとして、CHandleを別のヘッダで
class CFile::CHandle;
ってやると怒られてしまいますが、
これって、
class CFile
{
class CHandle;
};
こんなことやってもダメですよね?
>>338 その問題は避けられないので、ネストされたクラスは
インターフェースに使わないほうがいい。
逆に言うと、インターフェースに使うクラスは
ネストされたクラスにしないほうがいい。
includeのヘッダファイルなどの書き方について よくわからないところがあったので質問させてもらいました。 「*.h」というようなファイルには極端な話し 外部のファイルからアクセスする必要があって、 実体の無い物のみ書き込むと言うような考え方で良いのでしょうか? またサブフォルダなどを使ってはいけないと言う話しをどこかで聞きました。 #include "./test/test.h" #include "../test.h" などとすると問題が起きることがあるのでしょうか? ヘッダファイルの中では極力インクルードを使わないようにした方が良い なんて言う話しも聞いたことがあります。 なにかこう言ったようなやってはいけない的な事があれば 教えてもらえませんでしょうか? 基本的な質問で申し訳ないですが、よろしくお願いします。
Cの時代なら、基本的にはヘッダファイルにはプロトタイプ宣言を、 *.c ファイルには関数の定義を書くんだよ、って言えたんだけどなぁ。 クラスの定義はヘッダファイルに書くし、テンプレートの定義も ヘッダファイルに書くし、ヘッダファイルって大活躍だよね。 ごめん、ぜんぜん質問の答えになってなかった。寝るわ。
>>341 確かに言われてみればクラスやテンプレートを勉強し始めてから
よくわからなくなってきたような気がします。
ありがとうございました、お疲れさまです。
>>340 ヘッダの変更は利用側の再コンパイルを必要とするので、
内容は必要最小限にしておいたほうがいい。
ヘッダファイルの検索方法は標準で定義されていないので
コンパイラ間で移植を行うときに問題になることがある。
個人的には、 . や .. などソースファイルの位置に依存する書き方は
問題になりやすいのでお勧めしない。
ただ、コンパイルオプションの設定でどうにかなることがほとんど。
ヘッダファイルの中でのインクルードは依存関係を累積的に増やす事になる。
これも必要最小限にするべきだろう。
public: typedef enum A { a, b, c, : (20個ぐらい続く) } TypeA; ↑ こういうクラスの中にtypedefされたenum定義とかって、別のヘッダファイルにしておいて public: include A.h; みたいにかけないですかね?
>>344 普通に書けるよ。
class something {
public:
#include "A.h"
};
#include <a.h>で出来るだろ。
348 :
344 :2006/03/27(月) 00:04:54
orz
class A, B, C というのがあり、BもCもAを継承するのですが、Aの一部の メソッドは、Bの方には継承したくありません。こういう場合、一般的にはどうするのが うまい設計でしょうか? 単純にAの一部のメソッドを別クラス(A’)にしてCの方は、AとA’ を多重継承させるのが簡単かと思いますが、この場合A’は引数にAの メンバ変数を取る単なる関数の集合体になります。まぁこれでもいいの ですが、何かもうちょっとオブジェクト指向的な?よい方法はありますか?
>>349 > この場合A’は引数にAのメンバ変数を取る単なる関数の集合体になります
ここの意味がわからん。
不満が無いならそれでいいだろう。
何が不満なのかわかるように書いてくれれば、
回避方法もあるかもしれんが。
>>349 Aの一部のメソッドを外したものをBaseAとして定義してその一部のメソッドだけの集合をOptAにつっこんでCはOptAを継承してBはBaseAを継承じゃだめなのか?
というかAが基底になりきってないだけじゃないの?
ライブラリ提供のAだってならどうしようもないけどな。
>>349 「オブジェクト指向的」に言うと、Aの持つインターフェースを全て持たないなら
BはAをpublic継承すべきではない。
C++の観点から言うと、usingを使って継承されたメンバのpublic/privateを自由に変更できる。
BでAから継承したくない関数と同名で引数を変えたメンバ関数を プライベートに宣言しとくとか
>>352 >C++の観点から言うと、usingを使って継承されたメンバのpublic/privateを自由に変更できる。
できなくね?
>>354 #include <iostream>
struct a
{
void f(){std::cout << "f\n";}
void g(){std::cout << "g\n";}
};
struct b : public a
{
private:
using a::f;
};
int main()
{
b x;
x.f(); /* エラー: b::fはprivate */
((a &)x).f(); /* ok */
}
357 :
354 :2006/03/27(月) 00:59:04
>>355 g++ 3.3.5では通るのであった
355の方が自然だとは思うけど,さて規格ではどっち?
358 :
349 :2006/03/27(月) 01:01:09
みなさんアドバイスありがとうございます。
その中で、
>>352 >「オブジェクト指向的」に言うと、Aの持つインターフェースを全て持たないなら
BはAをpublic継承すべきではない。
まさにここをお聞きしたかったのですが、全てもたないけど一部は持つ(その一部
は実装が共通のメソッド)
という場合はどのようにすべきなのでしょう? 個人的にはこれってmix-inの問題
なのかなと思ったりするのですが。う〜ん
359 :
349 :2006/03/27(月) 01:02:17
あ、public継承にしなければいいのかな
>>357 g++3.5.4
test.cpp: In function `int main()':
test.cpp:5: error: `void a::f()' is inaccessible
test.cpp:18: error: within this context
362 :
360 :2006/03/27(月) 01:04:08
3.4.5ね。
>>358 どうするべきかって言ったら、きっちりインターフェースを切るべきに決まってるだろ。
何が不満なのかわかんないままだし。
>>343 なるほど・・・ありがとうございます。
参考になりました。
なんだっけ。 「ペンギンは鳥。鳥は空を飛べる。従ってペンギンは空を飛べる。あれれ?」問題だっけ。 鳥クラスにfly()メソッドがあり、鳥クラスを継承したペンギンはfly()が呼び出せる。 fly()をprivateにしたり例外投げたりすることで、ペンギンは空を飛べなくなる。 しかし、これは、ペンギンは空を飛べるが、空を飛ぼうとしたら必ず失敗する、ということにすぎない。 それが嫌なら、flyable_birdクラスとnon_flyable_birdクラスあたりに分離する。 というのをどこかで昔読んだ。
366 :
デフォルトの名無しさん :2006/03/27(月) 10:58:14
>空を飛ぼうとしたら必ず失敗する、ということにすぎない。 実際、そうだけどね バージョン化したプログラムに退化器官はつきものだし 退化ではなくもともと翼のない鳥なんておかしなものを後付で作るほうがどうかしてるよ
367 :
デフォルトの名無しさん :2006/03/27(月) 11:19:42
>>365 なんかすごい納得。いいなその説明。
メモっとこ。
368 :
デフォルトの名無しさん :2006/03/27(月) 11:28:56
飛ぶ概念クラスを作ってその鳥クラスに継承させるか否か決めればいんじゃね?
そこで、テンプレートですよ。 struct typelist_tag{}; template< typename Signature > struct inherits; template< typename T1 > struct inherits< typelist_tag ( T1 ) > : public T1 {}; ... /* 鳥テンプレート */ template< class Polices > class bird : public inherits< Polices > { ... }; struct flyable { virtual void fly()=0; }; struct swimable { virtual void swim()=0; }; // カラス class crow : public bird< typelist_tag( flyable ) > { /* fly を実装するとか */ ... }; // ペンギン class penguin : public bird< typelist_tag( swimable ) > { /* swim を実装するとか */ ... };
それって多重継承で良くね? // 鳥 class bird { ... }; struct flyable { virtual void fly()=0; }; struct swimable { virtual void swim()=0; }; // カラス class crow : public bird,public flyable { /* fly を実装するとか */ ... }; // ペンギン class penguin : public bird,public swimable { /* swim を実装するとか */ ... };
>>368 の言うとおり、「鳥は空を飛べる」の時点で間違ってるんだけどな
あの鳥はまだうまく飛べないけど〜 いつかは風を切って知る〜
空を〜 飛べるはず〜
>>365 EffectiveC++の
「publicに継承するときはis-a関係にあるか確認しよう」
に出てた。これが最初かしらんけど。
bird
/ |
flying non flying
|
penguin
こんな感じででてたね。
私自身、この設計が間違ってるとは思わないけど、
本の中で、例を出すにはいい解説だったと思うよ
class hoge{ hoge(); } hoge::hoge(){ class piyo{ piyo(); int piyovalue; } } piyo::piyo(){ piyovalue=0; } 見たいな事できる? 変なところがあったらダメだし求む。
無いが何か?
なら回線切って首吊って氏ね
お前が氏ね
みんなはさーん
>>379 相談のマナーがなってなけりゃスルーでええやん。
>>376 どうでもいいけど、classの宣言・定義は、ブロック {} のあとに ; が必要だ。
piyoのコンストラクタはprivateなので、
hogeと明示的にfriend関係にするか、piyoをpublic継承しないと
このままではpiyoのインスタンスを生成できない。
コンストラクタで例外が投げられないよう気を付けておく。
newした配列をdeleatするときに、deleat [] arrey;といった様に、これからdeleatするオブジェクトを明示的に指定しなければならない理由とは何でしょうか。 もしくは、どんなオブジェクトでも無差別に開放するスマートな方法はありますか?
C++でオブジェクトの配列は忌み子だから、おとなしく std::vectorでもつかっときなさい
え?じゃあ文字列はどうすればいいんですか? これも有効な方法があるんですか?
文字列にはstd::stringがあるだろう。
388 :
デフォルトの名無しさん :2006/03/27(月) 18:33:10
>>384 通常は auto を使えば構築と破壊の対をコンパイラに作ってもらえる
それをわざわざ違う方法で扱うからには構築と破壊の対を特殊な形にする動機が必ずあるはず
よって、この質問はシュールと言わざるを得ない
>もしくは、どんなオブジェクトでも無差別に開放するスマートな方法はありますか?
>>388 無差別にオブジェクトを削除したければ、ステートメントブロックを作ってその中に記述すれば良いんですか?
390 :
デフォルトの名無しさん :2006/03/27(月) 18:46:54
>>389 詩的な表現をされている部分の真意を測りかねるが
ブロックからの逸脱を削除と解釈してはならないオブジェクトを指定する方法が new や static だ
autoだと(ブロックの中で)無差別に殺す事が出来る でもスマートじゃない。
392 :
デフォルトの名無しさん :2006/03/27(月) 19:22:02
>でもスマートじゃない。 え???
393 :
デフォルトの名無しさん :2006/03/27(月) 19:37:21
しゃべり過ぎは禁物 このへんでやめとこう
まとめると、オブジェクトはステートメントブロック内でしか生きられないから、deleatとかを使って コツコツオブジェクトを殺すんじゃなくて、ステートメントブロックを活用して一気にオブジェクトを殺せば良いと。 でもそれだと複雑なコードが組めないし、トリッキーになるから素直にdeleatするか、この話はこのへんで止めておこうと。
deleteも綴れない無能は何言っても無駄
deleatと打ちたくなる気もわからなくはない
そこは敢えてスルーしてたのに…
くだらんつっこみで、流れを壊してる奴、空気読め。
このへんでやめておこう という気持ちもわかるが、最後の締めがdeleatじゃねぇ・・・
女にもてない奴は、空気が読めない。
逆も成り立つ。 空気が読めない奴は、女にもてない。
う ほ や ら な い か と言われた俺は?
同類憐れみの令
.exe
>>384 配列arrayの先頭アドレスは、しばしばポインタで表される。
あるポインタ変数が与えられたとき、それはオブジェクトへのポインタを指すのか?
T* X = new T;
それとも、配列の先頭アドレスなのか?
int array[N];
int* Y = &array[0];
両者を区別することは難しい。
そこで、オブジェクト用のdeleteと、配列用のdeleteを用意して、
判断をプログラマにまかせているのだと思われ。
delete X;
delete[] Y;
408 :
デフォルトの名無しさん :2006/03/28(火) 05:22:42
delete p == delete[1] p は結果的にボツったけど案は出てたね
C++で エラー処理を一箇所でまとめたいとき try ~ catchって使っていいの? gotoや、do{ break }while(0);とか使うべき? エラーと例外は別物とか聞いたし
ケースバイケース
>>409 まさにそのために例外がある。
ただし、例外を使うのは例外的な状況に限ったほうがいい。
>>412 ほんとだ、参考になる。じっくり読んでみるよ。
あれ? また例外処理のスレが立ったのか。
415 :
Defaultの名無しさん :2006/03/28(火) 21:45:51
ちょっと変わったfunctorが作りたいです。 普通はresult operator(arg1,arg2, ...)といった感じで実行ですが、 すべての関数は,void Execute()で実行します。 このとき引数の値を事前にfunctorに保持させるようにします。 戻り値もExecute()実行後にfunctorに保持し、適宜,rerult GetResult()みたいな感じで取り出すとします。 ここで問題となるのが、引数argN型や戻り値result型の保持の問題です。 argやresultが参照の場合はやっかいです。メタプログラムして値型にすれば容易に解決できると思いますが、 Execute()実行まえに参照先が変化している場合(マルチスレッドが理由とかで)もあるので、 やっぱり参照で保持したい・・・ポリモルフィズムしてほしい・・・ なにか良い知恵をご教示願います。
ポインタで持てよ
417 :
Defaultの名無しさん :2006/03/28(火) 22:10:27
どうもありがとうございます。 でも、 保持している関数ポインタ(func_ptr)の引数がarg&だった場合はarg*で保持するとします。 このとき、Execute()実行時はfunc_ptr(*arg)が起動するわけですが、 argが抽象クラスの場合はコンパイルされません・・・
コンパイルされません、って何だよ。 cc1:error:sorry unmplemented.か?
#include <stdio.h> struct IHoge{ virtual void hoge()= 0;}; struct CHoge : IHoge{ void hoge(){printf("h\n");} }; int f(IHoge &i){ i.hoge(); return 0;} struct ce { IHoge *arg; int ret; int (*func)( IHoge & ); void Execute(){ ret = func( *arg ); } }; int main(){ CHoge ch; ce e; e.arg =&ch; e.func = f; e.Execute(); printf("%d\n", e.ret ); } こういうことだろ。
普通にコマンドパターンだよね
421 :
デフォルトの名無しさん :2006/03/29(水) 00:58:59
メソッドと関数の違いってなんですか? ほとんど同じとは聞くけど正確な違いとか定義とかあるんでしょうか?
422 :
Defaultの名無しさん :2006/03/29(水) 01:00:01
415です。みなさんありがとう! 自宅に帰ってきました。 とりあえず、こんな感じで使えればなあと思ってます・・・ class FunctorBase{ public: virtual void Execute(const long& arg)=0; ...}; template<typename Result,template Argument> class Functor { public: typedef typename FuncPtrCreate<Result,Argument>::FuncPtr FuncPtr;//関数ポインタの型 typedef typename FuncPtrCreate<Result,Argument>::ResultType ResultType; typedef typename FuncPtrCreate<Result,Argument>::Argtype Argtype; private: typedef typename FuncPtrCreate<Result,Argument>::ResultHolder ResultHolder; typedef typename FuncPtrCreate<Result,Argument>::ArgHolder ArgHolder; public: explicit Functor(FuncPtr func) : FuncPtr_(func) { } virtual void Execute() { ResultHolder_.Set( FuncPtr(ArgHolder_.Get()) ); } void SetArg(Argtype arg) { ArgHolder_.Set(arg); } ResultType GetResult() { return ResultHolder_.Get() } private: FuncPtr FuncPtr_; ResultHolder ResultHolder_; ArgHolder ArgHolder_; ... }; つづく
423 :
Defaultの名無しさん :2006/03/29(水) 01:01:29
つづき 使い方は・・・ Strung Func(long& arg); int main() { Functor<String,long& arg> functor(&Func); functor.SetArg(10); functor.Execute(); Functor<String,int&>::ResultType rerult=temp1.GetResult(); } とりあえず寝ます。
425 :
Defaultの名無しさん :2006/03/29(水) 01:04:05
あっまちがい 最下段temp1.GetResult(); はfunctor.GetResult(); めんご
>>422-423 せめてコンパイルできるかどうかぐらいチェックしてから貼れよ。
使われてない FunctorBase とか宣言されてない FuncPtrCreate とかボロボロだぞ。
427 :
デフォルトの名無しさん :2006/03/29(水) 05:44:28
__DATE__ および __TIME__ の文字列のフォーマットって、 処理系依存ですか?それとも規格で厳密に決まっていますか?
16.8 Predefined macro names The following macro names shall be defined by the implementation: ... _ _DATE_ _ The date of translation of the source file (a character string literal of the form "Mmm dd yyyy", where the names of the months are the same as those generated by the asctime function, and the first character of dd is a space character if the value is less than 10). If the date of translation is not available, an implementationdefined valid date is supplied. _ _TIME_ _ The time of translation of the source file (a character string literal of the form "hh:mm:ss" as in the time generated by the asctime function). If the time of translation is not available, an implementationdefined valid time is supplied.
6.10.8 あらかじめ定義されたマクロ名 次に掲げる七つのマクロ名は, 処理系によって定義されていなければならない。 _DATE__ 前処理翻訳単位の翻訳の日付("Mmm dd yyyy"の形式をもつ単純文 字列リテラルで, 月の名前はasctime関数で生成されるものと同じ とする。dの値が10より小さいときは, その最初の文字は空白とす る。)。翻訳の日付が得られない場合, 処理系定義の正しい日付を提供 しなければならない。 (略)
>>421 メソッドはJava/C#などの言葉。
C++ではメンバ関数。
_DATE__ とか使ってログを取ろうと思ってログ関数作ったけど その関数の中で呼んでも意味無いんだね。当たり前だけど。 使えないと思った。 bindとか使ったら使いやすくなるだろか。
433 :
デフォルトの名無しさん :2006/03/29(水) 12:41:45
VC++6では、もしかしてstdのalgorithmって使えないんですかね?
>>433 使えるよ。 STLport 使うとだいぶマシになるよ。
435 :
デフォルトの名無しさん :2006/03/29(水) 12:50:39
.netでは普通に動くんですが、 vc6だとmaxは定義されていないとでるんですが #include<algorithm> #include<iostream> using namespace std; void main(){ int a,b,c; a = 0; b = 1; c = max(a,b); cout << c << endl; cout << a << b << endl; }
437 :
デフォルトの名無しさん :2006/03/29(水) 13:53:47
.netでは普通に動くんですが、 vc6だとmaxは定義されていないとでるんですが #include<algorithm> #include<iostream> using namespace std; void main(){ int a,b,c; a = 0; b = 1; c = max(a,b); cout << c << endl; cout << a << b << endl; } error C2065: 'max' : 定義されていない識別子です。
過去ログ読んだか? 同じ質問があった気がする
過去ログ多すぎて読めませんwww
b馬鹿だな、ここで質問してググりながらここを見て放置しとくんだよ
441 :
デフォルトの名無しさん :2006/03/29(水) 15:10:22
そうしてますね。 ていうか、 「過去ログ呼んだか?」の一行をぜひ、 「できないよ」「できるよ」の答えの一行にしてほしい質問者です
>>437 は質問の体をなしていないから答えようがないんだが。
std::maxが使えるか、という質問ならたぶん「使えない」でいい。
algorithmの各関数が使えるか、という質問なら、「使えるものもある」で。
443 :
デフォルトの名無しさん :2006/03/29(水) 16:00:17
「使えるものもある」ですか。 ありがとうございます。
w
過去ログ読んだか?1〜47まであるぞ、気合い入れて読め。
過去ログにgrepかければ一瞬です。
犬糞環境なんて整えられません><
>>430 >C++ではメンバ関数。
非公開メンバ関数をメソッドとは呼ばないと思う。
過去ログが落ちてしまって残ってない場合はどうやれば…
>>449 ●を買う。鯖代への貢献にもなって一石二鳥。
それでも拾いきれないものについては、保存している人を探して、拝み倒して
どこかにうpしてもらう。その後、君がまとめサイトを作れば完璧だ。
にく
C++初心者の者ですが、
http://www.asahi-net.or.jp/~yf8k-kbys/newcpp17.html を見ながら勉強していたら、最後のwhile文からを
while(1){
int ans;
cout << "1 鳴かす 2 年収を表示 3 昇給 4 やめる"<<endl;
cin >> ans;
if(ans == 1)
dora.naku();
else if(ans == 2)
cout<<dora.get_nensyu();
else break;
}
}
こう書くと年収の表示がおかしくなります。
自分で色々書き方を変えても原因がどうにも分かりません。
どなたか何処がダメなのか教えてください。
>>453 endl が抜けてるせいで改行が入らない上にでバッファリングされてるんじゃね?
そうじゃないなら、「おかしくなる」って言われてもわかんねーよ。
ちゃんと症状書け。
C++はじめたばっかりの初心者なんですが //hello3.cpp #include <iostream> #include <string> using namespace std; int main() { string name; int tosi; cout << "こんにちは。私はコンピュータです。" << endl; cout << "あなたの名前を入力してください。" << endl; cin >> name; cout << name "さん。よろしく。" << endl; cout << "ところで、" << name << "さん。失礼ですがお年はいくつですか?" <<endl; cout << "(入力は必ず、半角の数字でお願いします。)" << endl; cin >> tosi; cout << "なるほど。" << tosi << "歳ですか。" << endl; cout << "私はもうすぐ2歳のマシンです。"<<endl; } この例文を実行すると エラー E2379 hello3.cpp 15: ステートメントにセミコロン(;)がない(関数 main() ) とか出ます・・・ セミコロンちゃんとつけてるんですが・・・・どこが悪いのかわかりません、教えてください。
>>455 × cout << name "さん。よろしく。" << endl;
○ cout << name << "さん。よろしく。" << endl;
つか、エラーが出たら、その箇所を見て間違いを探す練習をした方がいいと思うぞ。
コンパイラのエラーメッセージはエラーを起こした行番号の参考程度にし、 エラーメッセージの内容は無視して、まず該当行から自力で間違いを探す方がいいな
うっひょう!できました!
>>456-457 ありがとうございました!いままで○○Pとかにいたんでここの優しさがしみる・・・・
>>457 いや、内容を無視するのはまずい。先に内容を考えた後で、
原因と直結しないメッセージである可能性も考慮するのが正解だろう。
慣れてくればそういうメッセージは見分けられるようになる。
460 :
453 :2006/03/30(木) 10:43:00
>>454 おかしくなるというのは、関数から返ってくる年収の値が100のはずなのに
実行すると1401とか表示されるということです。
>endl が抜けてるせいで改行が入らない上にでバッファリングされてるんじゃね?
これってどういうことでしょうか?
確かにdora.get_nensyu()<<endl;と直すとちゃんとした値が表示されるのですが
改行がないと何がまずいのでしょうか。
>>460 endl ぐらい Google でも使って自分で調べろ。
あと標準出力のバッファリングもな。
で、 endl 入れると「ちゃんとした値」ってことで 100 と表示されるのか?
「1401とか」って何だよ?実行するごとに変わるのか?
改行が無いのがまずいと思わないならそれはお前の勝手だ。気にするな。
書き込む前によく読みなおして、自分以外の人が読んでも
理解できるかどうか確認してください。
>>460 改行を入れるまで、文字列を出力しないでバッファにためこむ環境があるってことさ。
つまり、std::endl(もしくは'\n')を入れないと文字列が出力されないことがあるので、必ず入れましょう、ということ。
>>462 '\n' をいれてもバッファのフラッシュはかからない。
「必ず入れましょう」ということで汎用のコードに endl ばら撒かれてもフラッシュしまくりで困る。
きちんと使い分けましょう。
フラッシュしたかったらstd::flushマニピュレータ突っ込めばOK
465 :
453 :2006/03/30(木) 11:20:21
>>461-462 ありがとうございます。おかげでやっと意味が分かりました。
この手のエラーは初めてで何が原因だったか全く分からなかったため
言葉足らずな質問になってしまいすいませんでした。
>>455 × cout << name "さん。よろしく。" << endl;
○ cout << name << "さん。よろしく。" << endl;
>>448 非公開だろうと何だろうと、メンバ関数をメソッドと呼ぶのは誤り。
メンバ関数という用語も標準規格で定義されているのですか?
470 :
466 :2006/03/30(木) 12:06:11
だれかが言う前に俺が言ってやる 春
>>469 つ[JIS X3014]
つ[google]
つ[自助努力]
>>469 Functions declared in the definition of a class, excluding those declared with a friend specifier,
are called member functions of that class.
476 :
デフォルトの名無しさん :2006/03/30(木) 19:27:08
感情クラスから怒りクラスを派生させて、怒りクラスから憎しみクラスを派生させて… ってやっていったら人工知能つくれませんか?
478 :
476 :2006/03/30(木) 23:00:16
僕は馬鹿にされて軽くあしらわれたのですか?
479 :
デフォルトの名無しさん :2006/03/30(木) 23:37:56
MFCてなによ? C++の書き方覚えても あまり意味ないわけ? 裏切られた気分・・・・
>>479 MFCはWindows アプリケーションを作るためのフレームワーク。
Winアプリを作るのが少しは楽になるかもしれない。ただ最近は下火。
C++の高度なことはあまり要求されないので、
MFCを使いたいがためにC++を学んだのであれば、
たしかに裏切られた気分になるかもしれない。
481 :
デフォルトの名無しさん :2006/03/31(金) 09:56:08
お前ら、Windows で開発するとき、 各種ライブラリってどこに置いてますか? C:\ に置いてます?たとえば C:\boost\lib\ みたいに。 その辺、Windows ってコンセンサスって無いですよね? ルートに全部置くのもなんか汚い(?)気がするし、 かといって C:\Document and Settings\以下略 みたいな長ったらしい、かつ、空白を含むパスに置くのも嫌だしなぁ。 Vista では長ったらしいパスをやめた、って話だけど。
482 :
デフォルトの名無しさん :2006/03/31(金) 10:02:25
>>481 普通は、libpathにパス指定して好きなとこに置くだろ。
パス指定されると、コンパイルが遅いとか言っていた時代と違うんだから。
長ったらしくて空白を含むパスにLib置いて挙動がおかしくなるコンパイラは Win32対応って言わないと思うんだけどなぁ。
スレ違いだが、 make のリスト区切りがスペースなのが困る。
486 :
デフォルトの名無しさん :2006/03/31(金) 12:45:08
>>481 /usr/lib の下にまとめてラクになっちゃえばOK。
Document and Setting も Vista では /user/ だし。
>>483 やっぱそんなものなのか
おいらは普段はLinuxでやってるんだけど
ときどき頼まれてWinで開発するときに
どこに置いたらいいものか悩む
488 :
487 :2006/03/31(金) 12:50:35
ちなみにUNIXの場合も決め打ちされてる訳ではない
>>485 GNU makeだと\でエスケープできるよ
eclipse/cdt 以外でリファクタイングできるツールないのかな? javaぽい書き方してjavaのリファクタイングツールを流用するしかない?
>>487 適当にどっかにライブラリ用のフォルダ作ってまとめとくのが普通でしょ
こんなの、落としてきたインストーラ無しのソフトを
どこに解凍して置いておこうかな、っていうレベルの問題だと思う
linuxでもそういうことあるし同じでしょ・・・
全体的なフォルダ構成が違うけど
最近話題のstatic_castってなんだよ エロイのか?
エロくはないけど、大流行だよ! ナウなヤングにバカウケ
バカウケの部分をもっと ナウでヤングに出来ないかな?
>>491 適当に置くこともできるけどUNIXではコンセンサスみなたいなものはあるよ
手元に環境あれば
$ man hier
してみれば解説されている
498 :
デフォルトの名無しさん :2006/04/02(日) 00:02:47
static_castと普通の(char*)みたいなキャストって何が変わるの?
>>498 static_cast のほうができることが少ない。そのぶん安全。
また、検索しやすいという効果もある。
従来のキャストはできることが多すぎたから, static_cast と const_cast と reinterpret_cast に分割した, と思っておけば大体おk. static_cast: 暗黙にできる型変換を明示的にやるために使う. const_cast: const/volatile をつけたりはずしたりするために使う. reinterpret_cast: 実装に依存するような型変更のために使う.
>>500 誤解してるやつが多いんだが、 const, volatile をつけるときは const_cast 使わなくていい。
危険なキャストを洗い出すときに const_cast 検索するから、つけるときは static_cast で。
>>501 すまん、意味がわからん。
C style のキャストも const_cast も使用せずに
どうやって const, volatile を付けるん?
暗黙の変換のこと?
>>502 「つけるときは static_cast で」
void*からint*等へのキャストはstatic?reinterpret? いつもはreinterpretを使ってたんだけど あちこちでstaticの方でやってるのを見かけて自信がなくなってきてる
>>504 void* からオブジェクトポインタへの変換は static_cast 。
reinterpret_cast は間違い。
reinterpret使うくらいならCスタイルかなぁとか思ったりする。 検索はしづらくなるけど
508 :
デフォルトの名無しさん :2006/04/02(日) 01:32:55
reinterpret_castはbit表現のレベルで、無理やり変換する場合だけって考えていいのかな
>>508 ビット表現が保持されると決まっているわけじゃない。
510 :
504 :2006/04/02(日) 01:41:22
>>506 thanks
staticは安全なの、reinterpretは危険なのを強引に、
dynamicはvtable付きクラスをダウンキャスト、constはconst,volatile外し
ってイメージで使ってた。
無チェックなダウンキャストとか、継承関係に無いポインタ間のキャストは
危険そうだったからreinterpretのイメージだったけど
危険さ具合がイメージとちょっとずれてたみたい。
511 :
デフォルトの名無しさん :2006/04/02(日) 01:41:34
>>509 む、そうなのか・・・
ちょっと適当に自分でいろいろ試すことにする
>>510 無チェックなダウンキャストは static_cast 。
継承関係が無ければエラーになる。
reinterpret_cast だとエラーにならない。
コンパイラの実装依存のがreinterpretで 特殊用途のdynamic,constの他は全部staticすか
プリミティブ型のポインタ変換はstatic_castでよかったのか。 どうもいまいちreinterpret_castの使いどころがわからないんだよな。
int i をストリームにバイナリ出力するとき、 out.write(reinterpret_cast<char*>(&i), sizeof(i)); してるんだけど、これって実装依存になるのかな? 規格中に ・ int* から void* に変換したとき、変数の記憶域の先頭を指す。 ・ void* と char* は同じ内部表現を持っている。 っていうのは見つけた。 だから static_cast<char*>(static_cast<void*>(&i)) なら大丈夫そうなんだけど、 これは激しくウザイ。
構造体をfstreamのread,writeで書き込むときって、char*にキャストするよね。 この場合はreinterpret_castでいいのかな。
>>516 普通、絶対そんなことしないと思うが、 alignとか考えたことある?
518 :
デフォルトの名無しさん :2006/04/02(日) 02:44:20
結論 皆キャストも満足に扱えてない。
struct Data { int i; char c; } d; write(fp, &d, sizeof(Data));
>>517 read, write の引数は char* なわけだが、「普通」はどうするのかね?
>>521 POSIX の read, write は void* だな。
でも今話してるのは iostream の read, write で、こっちは char* になってる。
523 :
デフォルトの名無しさん :2006/04/02(日) 03:06:02
あるクラスのインスタンスへのポインタをlistに入れた場合、 そのlistをdeleteすればそのクラスの実態まで消えるのでしょうか?
525 :
デフォルトの名無しさん :2006/04/02(日) 03:14:56
>>525 Effective STLとかにそのへんのこと詳しく載ってる
527 :
デフォルトの名無しさん :2006/04/02(日) 03:24:49
>>525 即レス乙です。ちょっと憂鬱読んで気になったもので……
528 :
デフォルトの名無しさん :2006/04/02(日) 03:26:40
static_castでコンパイラに怒られたらそれっぽいcastに書き換えてるようじゃダメなのか…
>>529 なんのためにキャストしようとしているか理解していればそんなことはおき得ない
531 :
デフォルトの名無しさん :2006/04/02(日) 08:08:38
>>525 その他に、ポインタが指す先がすべて new で確保したもので、2カ所以上からポイントされていないという保証も必要
ポインタの列を list で扱うというパターン自体が、そもそも自動 delete を望まないか、list で作っているのが部分集合で
全体集合を作っているコンテナに破壊の仕掛けがあるような場合に使うもの
532 :
デフォルトの名無しさん :2006/04/02(日) 08:11:23
素直にポインタでなくオブジェクトそのものを突っ込めばよくね?
>>531 そんなときこそ delete して 0 代入イディオムですよ
っ[boost::shared_ptr]
>>517 alignは#pragmaでごにょごにょしました。
やっぱり変数ごとに一個ずつ読んだり書いたりしないとだめなんかな。
ファイルヘッダとかは一気に構造体で扱っちゃったほうが分かりやすいと思ったんだけど……。
基本型しか使ってない構造体ならwrite(&struct)でいいとおもうけど。 互換性をいいだせば整数とかも文字列に変換せんといかんのじゃないか。
えーっと、例えば、#pragmaかなんかでalignを1バイト境界に揃えた構造体、 struct A{ unsigned int data; } a; を ifstream.read((char*)&a, sizeof(a)); したときの互換性?で致命的な問題って何があるでしょうか。 エンディアンぐらいしか思い浮かばない自分は半年ROMるべきでしょうか。
intのサイズとか。
>>537 思いつくのは揚げ足取り:
・alignmentを1バイト境界にできないコンパイラが存在したときに困る
・メンバにポインタや参照を含むときに望ましい結果にならない(そもそもやろうとしてないだろうけど)
・バイナリでの入出力は、どうも、C++では熟考されてない雰囲気
・アドバイス「構造体よりクラスを使え」
漏れも、たとえばWindowsBMP(DIB)のBITMAPINFOHEADERのような場合、
#pragma等でごにょってread(&struct)してるよ。ついでにoperator>>()も定義して
BITMAPFILEHEADER bf;
cin >> bf;
540 :
539 :2006/04/02(日) 14:40:13
> C++では熟考されてない雰囲気
これの意味は、バイナリ入出力では「型のビット表現」そのままを入出力するしかできないので、
型の大きさ(char単位の大きさ)、エンディアン、浮動小数点なら各ビットの意味など
判別・読み書き時にC++ライブラリの支援がない(支援ができない)。
そもそも、読み書きすべきバイナリデータが、C++だけで使われるとは限らない。
アマゴサ星系のエル・オーリアン人が、彼らの特殊言語で読み書きするかもしれない。
バイナリで扱うなら、ファイルの先頭あたりにUTFのBOMのようなものを入れるしかない。
「安全」さを求めるならテキスト入出力を使うべきなんだろう。
非現実的だが。
>>538 その問題は、read((char*)&a, sizeof(a))の問題ではなく、バイナリ入出力自体の問題じゃないかな。
541 :
デフォルトの名無しさん :2006/04/02(日) 14:49:56
gimpのbmpヘッダ書き込みのところのソースとか見てみたら 構造体のメンバを一つずつファイルに書き込んでたから アラインメントとか考えるとこういう風になっちゃうのかなー と思って、おれもそうしてた まあ、C言語だけど
>>538-539 ・実際はtypedefしたdwordなので、intのサイズが違ったらtypedefを書き換えればいいかなぁとか。
・1バイト境界に出来ないコンパイラは考えてませんでした。反省。
・ポインタを含むようなら当然このような手段は取らないです。
・C++ではストリーム使うべきかなと思ったんですが……やめたほうがいいですかね。
・単にデータをバインドするだけの使い方をしたかったので、純粋な構造体を使いました。
構造体はこういう使い方をするべきではないでしょうか。
実際はファイルを扱うクラスのreadメンバ関数の中で処理してます。
virtualメンバ関数があるとsizeofがずれてしまうので構造体なんですけども。
>BITMAPINFOHEADER
はい、まさにそんな感じです。
ifstream.readを変数分全部書くと、構造体メンバの変更があったときコードにも影響が出ますよね。
もっといい書き方あるんでしょうか。
ファイルフォーマットとかプロトコルっていうものをちゃんと 考えれば、ほぼ必然的に int とか struct をそのまま write したりは出来なくなるよね。 定義されてる(or 定義した) とおりのデータを、定義どおりの順に 定義どおりのサイズで読み書きする。たまたまパディングを調整 できるコンパイラで、バイトオーダーもあっていれば struct とかも使える。 そんだけのこと。
544 :
542 :2006/04/02(日) 15:08:52
長々と書いてたらその間にレスが……
>>540 可搬性を求めると問題は尽きないんですね……。
>>541 やっぱりそうなっちゃいますか〜。
>>543 なるほど……良くわかりました。
変数を全部読み込む手間 <-> 一度に読み込むリスク
でトレードオフってことですね。
プラットフォーム固定なら align してベタ書きでいいと思うけどね。 GUI ならどうせ他の色んな所でプラットフォーム固定のコードを書かざるを得ないだろうし、 ファイルの読み書きのところだけ可搬性を重視してもナンセンスかと。
546 :
542 :2006/04/02(日) 15:34:45
GUI部分は別にして、コアだけ作っていたので、 ある程度汎用性があったほうがよいかと思って色々と考えていました。 でも確かにここだけ可搬性を求めても仕方ないですね。 align指定と構造体で置いておくことにします。 色々とどうもありがとうございました。
C++ なら、読み書きを構造体のメンバ関数として提供しておけば、 プラットフォームを変更したところで、 その構造体のところの定義をいじっただけで済むと思われ。
個人的にはメンバ関数を持った構造体にalignmentを指定したくないんですけど、杞憂でしょうか。 何か気持悪いんですが……。
>>548 個人的には彼女を持ったからオナニーをしたくないんですけど、杞憂でしょうか。
何か気持悪いんですが……。
と言われてる気分だ。お前の勝手にしろ。
ちょっと前からバイナリ出入力と関連してアライメントの話が出てくるが、関係がわからん。 普通に sizeof 使ってたらアライメントも問題にならないと思うんだけど。
>>550 別環境では、ずれる可能性があるって話では?
>>551 別環境だったらサイズやビット表現も違う可能性もあるだろ。
アライメントだけ指定する意味が無い。
>>553 仮想関数があってもなくても関係ない。「好きにしろ」で終わり。
お好きなまでに…
>>555 仮想関数テーブルへのアドレスが読み書きされちゃうじゃん。
>>557 それとアライメント指定の是非に何の関係が?
>>559 漏れ個人的にはグローバルなコンパイルオプションなんかで
(ファイル書き出しなどに使う)構造体のレイアウトが変わったら
イヤだから、#pragma pack とかでアライメントは指定してる。
関連プログラム全部同じオプションでコンパイルするしー、とか
未来永劫アライメントなんか変えないしー、
っていう人なら確かにいらんかもしれないな。
VCとx86系を使ってますが、 コンパイラが勝手にintとかshortをワード、ダブルワード境界に揃えてしまいました。 それでは構造体で一気に読み込むとパディングのせいで実際のファイル構造とずれてしまうので、 #pragmaでアライメントをバイト境界に指定するわけですが、 #pragmaの機能は当然処理系依存機能なので余り広範囲に使いたくありません。 (コンパイラを変更したら#pragmaを恐らく変更しなければならない) エンディアンはこの際おいておいても、同一の性質を持つ記述を散在させるのは気持ちが悪いので、 PODのみを持つ構造体にアライメントを指定しておいて、それを扱うクラスにはアライメントを干渉させないように したのです。
>>560 なんか感覚おかしくね?
将来的なことを心配するならアライメント依存しない方法を選ぶだろ。
「構造体を一気に読む」自体が処理系依存なわけで。
メモリダンプ・ロードなんてどう考えたってハックじゃん。 そんなの使う場所で環境依存云々言ったって五十歩百歩。
>>勝手にしろ、好きにしろ
皆さんのお考えを聞いてみたかったのです……。
>>558 仮想関数を持ったクラスはsizeofの値が増加します(VCでは増えました、処理系によるかもしれません)。
この場合alignmentではなくこの増加分がどこに収められるかが心配なのです。
sizeofでサイズをとっての読み書きを想定しているので、
sizeofがずれるとread(&struct, sizeofA)では問題があるのです。
>>562 プログラムがalignmentに依存しないとしても、ファイルフォーマットは固定されてます。
構造体で一気に読むとしたらalignmentは少なからず関与してくると思います。
>>563 処理系依存なのはalignとエンディアンとパディングの大きさだけかと思っていました。
構造体一気読み自体が処理系依存とはどういうことでしょうか。
fstreamの仕様に関わることでしょうか。
>>564 ハックになってしまいますか。
メモリダンプというよりバイナリファイルダンプに近いんですけど。
なんだか収まりがつかなくなってきてしまったので、最後に皆様に率直にお聞きします。
私の構造体一気読みのコードを保守する羽目になったら私を殺そうと思いますか?
>>519 がまともに使えると思ってるやつばっかり、ってことだろ?
構造体のメンバのメモリ上での順番はC++では規定されてたっけ? あとchar以外の変数のサイズは処理系依存だけど。
alignとエンディアンとパディングが処理系依存なわけだから、 それを前提にしている構造体一気読みも当然処理系依存だろ。 >565 Win32上の処理系だと、COMの関係で、vtblはクラスの先頭に もってきてる可能性が高い。
厳しい現実を言うと char のビット数すらも固定ではなかったり
だが、unsigned char の最大値が255以上 sizeof(char)==1 であることは規定されている
571 :
542 :2006/04/03(月) 00:28:49
>>567 共用体ではないクラスの非静的データメンバがアクセス指定子が間に入らずに宣言された場合、
後で宣言されたデータメンバのほうがクラスオブジェクト内でより高位のアドレスになるように割り当てられる。
(X3014:2003より引用)
らしいです。
型のサイズについては
>>542 の最初の項のとおりです。
>>568 そうですね……。
3つの条件をクリアしたらいいのだろうか、と思いましたが、
よく考えるとつまりそれが処理系依存でした。
処理系依存でOKなら一気でもOK
ダメなら一個ずつ読み書きしなさい、ということですね。
>>565 結局「勝手にしろ、好きにしろ」としかいえないのが現実なんじゃないの?
構造体一気読みはコードを書くのが簡単だし、パフォーマンス上好ましいことも
あるだろう(fstreamを使っている時点でアレかもしれんが)。
他プラットフォームへの移植性が求められるなら、一バイトずつ読み書きするのが
比較的良い方法になるだろう。それでもC++の規格はすべての環境で同じファイル
フォーマットが使えることを保証してはくれないだろうけど。
その気があれば、移植するすべてのプラットフォームごとにマクロで実装を
切り替えたっていい。
プラットフォームごとの違いを吸収してくれるバイナリ入出力ライブラリ
みたいなものを作ってもいい。
好きにしろ。
573 :
542 :2006/04/03(月) 00:51:29
>>572 読み込むにしても、もっとよい策が無いかなぁと思ったものですから、
経験豊富そうな方がいそうなここへ書き込んだしだいです。
少なくとも私の考えた策は処理系依存を気にしないなら使えることが分かりましたし、
可搬性や移植性を考えるならすべきでは無いことも分かりましたので、
後は好きにさせていただきます。
色々と為になる書き込みを戴きました。
どうもありがとうございました。
boost::serializationてどうなんだっけ?
Boostのテンプレートライブラリ
どうせ標準ライブラリの範囲だけでプログラムつくらないから互換性なんか無視っす。
もう終わった話題だからアレだけど、 例えばWin32 APIなんかだと構造体の最初のメンバが自分自身のsizeofを保持するケースがけっこうある。 先の例のBITMAPINFOHEADERでも、 unsigned long biSize; // 構造体のサイズ(バイト) なんてメンバがある。 バイナリ入出力以前に、alignmentをバイト境界にしておかないと、こういうケースでハマると思うんだけど。 (構造体のサイズをハードコーディングするか、#pragmaごにょごにょ) で、まぁ、なにがいいたいかというと… alignment、endian、padding、メモリ上のビット表現を考慮し、 各環境で最適なコードで(一気読みできるならそうして、1バイトずつ変換が必要ならそうする)、 ストリームとバイナリ入出力してくれるような 可搬性のあるバイナリ入出力ライブラリ誰か作って…!
>>578 バイト境界でなくても整合性さえ取れていれば問題ないと MSDN に書かれてます。
>>572 以前実測したが、fstreamとFILE*は、readで一気読みする分には処理速度変わんないよ。
IOがでかすぎるせいで、差が消えちゃう。
っていうか fstream や FILE はバッファ有るからまとめてI/Oしてるよね。 Unix の read() や Windows の ReadFile で細かい単位で読み書きしたり すると、あるべき速度の10倍くらい遅いプログラムも簡単に作ることができる。
582 :
デフォルトの名無しさん :2006/04/04(火) 16:41:00
sort用に、Fooクラスの2つの引数を持つ比較関数オブジェクトを作ろうと思ったのですが、 考えてみれば関数オブジェクトから、Fooクラスのprivateメンバにはアクセスできないっす。 これは一々getter用意するなり、friendにせざるを得ないんすかね。 と、言いますか、operator=や、operator<なんかが、他オブジェクトのprivateメンバにアクセスできるのは、 どの辺に規定されてるんすかね。ドラフト見てもいまいち分からないっす…。
>>582 Fooクラスにoperator<を持たせりゃいいじゃん。
それと、operatorなんとかのスコープは関数と同じ。どういう宣言を
されてるかだけによる。
584 :
582 :2006/04/04(火) 16:53:28
>>583 レスサンクスです。後者は勘違いしてました。
自分と同じクラスのprivateメンバなら、他オブジェクトでもアクセス出来ちゃうってことすか…。
何か納得いかないすが、理解できました。
何通りかでsortしたいんすが、「Fooクラスにoperator<を〜」では、一つしか賄えなくて困ってるっす。
でもgetterなりしか無いようでしたら、諦めるっす。
>>584 関数オブジェクトのコンストラクタに引数をとるという方法は?
引数によって、どういう比較をするか、決めればいいのでは?
内部構造を知らないとかけないコンパレータは内部に書くのが普通。 外部から与えるコンパレータが内部構造に依存するのは道理としておかしい #include <iostream> #include <vector> #include <algorithm> using namespace std; class Foo { int a, b; public: Foo(int a, int b) : a(a), b(b) { } bool operator < (const Foo& o) const { return cmp_ab(*this, o); } static bool cmp_ab(const Foo &lhs, const Foo &rhs) { return lhs.a != rhs.a ? lhs.a < rhs.a : lhs.b < rhs.b; } static bool cmp_ba(const Foo &lhs, const Foo &rhs) { return lhs.b != rhs.b ? lhs.b < rhs.b : lhs.a < rhs.a; } }; int main() { vector<Foo> v; v.push_back(Foo(0,2));v.push_back(Foo(1,1));v.push_back(Foo(2,0)); sort(v.begin(), v.end(), Foo::cmp_ab); sort(v.begin(), v.end(), Foo::cmp_ba); }
>>586 関数オブジェクトの形にしないでもsortって使えるんですね。
見た目もすっきり。ありがとうございました。585さんもサンクス。
皆さんの知恵をお借りしたい。 クラスのメンバ内に次のような宣言があるとします。 public: int num0; int& operator=(int num1); int& operator=(int num1); が呼ばれないようにひっそりと num0に NULL を入れるにはどうやればいいですか?
>>588 代入演算子はコピーには適用されなかったと思うからそうすりゃいいんじゃね?
590 :
デフォルトの名無しさん :2006/04/05(水) 18:48:07
class A { public: int num0; int& operator=(int num1); }; main() { A a; a.num0 = 0; }
591 :
デフォルトの名無しさん :2006/04/05(水) 18:54:37
>>589 コピーには適用されないってどういうこと?
コピーコンストラクタを作れってこと?
int& operator=(int num1); がnum0に代入するときに呼ばれると思ってるのか?
一瞬コピーコンストラクタと代入演算子の区別の話だと思ったが よく読むと全く意図の分からない電波質問だな
・int型にNULL ・メンバ変数がpublic ・operator=で何をさせたいのかが不明
595 :
ガウショ :2006/04/05(水) 22:18:01
さて、ここで低レベルな質問です。 char *型の引数で結果を受け取る関数ありますよね? あれをstd::stringで受け取れるようにしたいです。 理想(無理だけど)↓ string s; sprintf(s.data(),"aaa"); とか string s; GetDlgItemText(hWnd,ID,s.data(),256); 何かいい方法があったら教えて下さい。
よくわからんけど、コンストラクタで初期化すればいいんじゃね
&s[0]
599 :
デフォルトの名無しさん :2006/04/05(水) 22:24:42
#pragma once #ifdef __cplusplus BOOL GetDlgItemText(HWND, std::string&); #endif
>>597 std::stringってvectorの様に連続性が保証されてなかったんじゃなかったっけ?
601 :
596 :2006/04/05(水) 22:25:09
>>601 コンストラクタで初期化せんでも、単に代入すればいいじゃん。
publicなんだし、num0への代入にoperator=は何も関与しないし。
>>603 ひっそりと、っていうからクラスを利用する側に意識させたくないのかと思ったけど
それもそうか
605 :
ガウショ :2006/04/05(水) 22:35:03
>>お答え頂いた皆さん
ありがとうございます!
>>598 やってみます。
606 :
ガウショ :2006/04/05(水) 23:00:39
解決できましたー
srand((unsigned)time(NULL)); ransu=rand()%100; とやっても生成された乱数が同じ数字が三連発されたり等でかなり「つかえねー」のですが もっとゲームなどに適した乱数関数ってありますか?
boost::random
>>595 sprintfの代替にはboost::formatがある。
後者は自分でstd::string(というよりもおそらくstd::basic_string<TCHAR>)を受け取る関数を作るしかない。
ただし
>>600 に注意。
スレ違いな回答をするが、
ATL::CWindow::GetWindowTextならATL::CStringで受け取れる。
またATL::CStringにはFormatというsprintfの代替がある。
MFCのCWndとCStringでも可。
611 :
ガウショ :2006/04/05(水) 23:18:44
コンポジションだっけ? stringをメンバにして自作クラスつくりまふ。 んでreserveして文字列受け取るメソッド作る。 cString s; sprintf(s.GetCStr(),"aaa"); みたいな
age過ぎましたorz
>>611 なんかそんなのboostにあったような無かったような…
614 :
607 :2006/04/05(水) 23:43:54
>>608 サンクス。
早速使ってみますた。
あまりの格の差に笑いすらこみ上げますた。
…rand()なんて薦める本は全部焼却処分したい気持ちだw
それにしてもここまでstd::ostringstreamが全く出てこないとは……。
薦めてる本なんて無いだろ。 boostは標準じゃないんだから、書きたくても書けない。 あと、標準のrandも、実装によってはMTが使われる場合もある。
>>607 で同じ数値が三連発、というのは
どこかrandの使い方を間違えてるように見えるんだけど
もしかしてrandを使うたびにsrandしてない?
618 :
デフォルトの名無しさん :2006/04/06(木) 01:16:44
はじめまして。 お世話になります。 開発環境:WindowsXP VC++6.0 MFC使用 ダイアログベースで画面を作成(A.exe CDialogベース)し、その画面でボタンを押下し 子画面(A_Child)を表示させます。表示方法はDoModal()で。 そのA_ChildはCDialogベースです。 A_Childダイアログが表示されている間(最前面)は、デスクトップ上の操作を 何も出来ない様にしたいのですが、方法はありますでしょうか? (例:スタート→ログオフでダイアログが表示しますよね。 その時ってそのダイアログ以外は触れないですよね。) せめて、自分たちが作成したアプリだけでも操作不可能にしたいのです。 SetWindowPos()、ModifyStyle()、色々試しましたが上手くいきません。 DoModalで表示させるのがそもそもまちがいののでしょうか? 何か方法が有りましたらよろしくお願いします。 説明が下手ですみません。 PS システムモーダルのチェックONで常に最前面に表示されているのですが 後ろの画面等が操作できてしまうんです・・・・。
619 :
デフォルトの名無しさん :2006/04/06(木) 01:33:30
MFCのモーダルって本当はモードレスで見かけ上モーダルのふりをしてるんだっけ? スレ違いすまそ
>>617 そうだな。ありがちなのはtime()が一秒ぐらい同じ値を返すから、srandに3回ぐらい同じ値を
渡してるとか。
それとは別に、rand()%100とやるのも良くない。 (int) (100.0 * rand() / (RAND_MAX + 1.0)) のように上位ビットを用いなくては均等な乱数にならない。
>>622 最近ではそれを考慮して実装されてるとどこかで聞いた。
ちょいと実験してみる。
>>623 operator%を定義してるのかなー、とか考えてしまったではないか・・・w
キニシナイでおくれ
625 :
デフォルトの名無しさん :2006/04/06(木) 04:09:09
operator(・ ・) みたいなのって定義出来ないの?オッパイ
>>616 rand()をMersenne-Twister使って実装してるような処理系あるか?
typedef struct { double X; //X座標 double Y; //Y座標 } SCoord ; //座標構造体 vector<SCoord*> CoordsList; //座標構造体へのポインタ列を格納するベクタ srand((unsigned)time( NULL )); //乱数の初期化 for (unsigned int i=0; i<10; i++){ SCoord* pTempCoord; pTempCoord = new SCoord; SCoord->X = (double)rand(); //乱数で座標を生成、代入 SCoord->Y = (double)rand(); CoordsList.push_back(pTempCoord); } //座標構造体のインスタンスを10個作ってポインタを格納 念のためファイルに ofstreamfout("出力先ファイル.txt"); for (unsigned int i = 0; i < CoordsList.size(); i++){ SCoord* pTempCoord; pTempCoord = (BeadsList[i]); fout << "X座標 " << pTempCoord->X << ", Y座標 " << pTempCoord->Y << endl; } で出力したところ、正しい値のように見えます。 ここで、pTempCoordはスコープの外ですが、そのポインタはCoordsListに保存 されています。また、newでインスタンスを確保しているので、deleteで開放 するまでメモリが開放されるわけではないと思うのですが、問題あるでしょうか?
>>627 問題ない。
>SCoord->X = (double)rand();
pTempCoord->Xの間違いか?
次の質問です。 typedef struct { double X; //X座標 double Y; //Y座標 } SCoord ; //座標構造体 vector<SCoord*> CoordsList; //座標構造体へのポインタ列を格納するベクタ srand((unsigned)time( NULL )); //乱数の初期化 for (unsigned int i=0; i<10; i++){ SCoord* pTempCoord; pTempCoord = new SCoord; pTempCoord->X = (double)rand(); //乱数で座標を生成、代入 pTempCoord->Y = (double)rand(); CoordsList.push_back(pTempCoord); } //座標構造体のインスタンスを10個作ってポインタを格納 使用済み座標構造体のインスタンスをメモリから削除するつもり for (unsigned int i = 0; i < CoordsList.size(); i++){ delete CoordsList[i]; } CoordsList.clear(); //オートポインタなので不要とは思うが、念のためベクタをクリア ベクタに格納したポインタは特に放置してもプログラム終了とともに自動消滅するでしょうけど、 構造体のインスタンスはプログラム終了後もメモリに残ると思います。それで構造体のインス タンスを個別に開放しようとしているのですが、プログラムが異常終了してしまいます。 どこに問題があるのでしょうか?
>>630 問題ないようだけど?
> プログラムが異常終了してしまいます
をもっと具体的に。
>>630 for (unsigned int i = 0; i < CoordsList.size(); i++){
634 :
632 :2006/04/06(木) 14:03:11
すまんボケてた
>>630 >構造体のインスタンスはプログラム終了後もメモリに残ると思います。
OS のないシステムなんですか?
>//オートポインタなので
何が?
で、どこでコケてるんですか?
使っている処理系はBorland Developpers Studio 2006のC++Builder10 なの
ですが、デバッガでステップ実行したら、
>>630 で書いたコードまで終了した
ところで、ソースファイルControls.pasが見つかりません。というダイアログ
が開き、パスを入力するようになりました。
Controls.pasって多分C++BuilderのGUI関連のライブラリのソースで、普通に
インストールすれば、ユーザーが知らなくても処理に必要なら処理系は知ってる
はずと思うのですが...
for (unsigned int i = 0; i < CoordsList.size(); i++){
delete CoordsList[i];
}
の部分をコメントアウトするとメモリリークしてるかもしれませんが正常終了します。
for (unsigned int i = 0; i < CoordsList.size(); i++){
SCoord* pTempCoord;
pTempCoord = CoordsList[i];
delete pTempCoord;
}
や
for (unsigned int i = 0; i < CoordsList.size(); i++){
delete (SCoord*)CoordsList[i];
}
に、変更しても同じなので、ポインタのデータサイズがわからなくなると
いった問題ではなさそうです。
637 :
デフォルトの名無しさん :2006/04/06(木) 15:07:43
実行ファイルを開いた瞬間他のプログラムを開くという処理はどうすればいいのか教えてくれ。
system
std::systemをmainの先頭からでも呼んだらどうだ?
>>636 標準C++の範囲では、見たところソースコードに問題ない。
あくまでも趣味の違いだが、SCoord生成時はnew代入じゃなく初期化時new、削除はイテレータを使うくらいか?:
Sccord* pTempCoord = new SCoord;
for (vector<SCoord*>::iterator it = CoordsList.begin(); it != CoordsList.end(); ++it) delete *it;
Controls.pasは、処理系依存の問題なので、スレ違い。
C++Builder相談室 Part16
http://pc8.2ch.net/test/read.cgi/tech/1138766165/l50
いや、
>>637 は、自分の実行ファイルと入っていない。
何か実行ファイルを開いたとき、他のプログラムを開きたいのだろう。
そして、環境もいわないという傲慢さだ。
そうだなぁ……。
大抵のOSでは、実行するシステムコールもしくはAPIなどがあるから、それをフックして……。
642 :
637 :2006/04/06(木) 15:33:49
WinXP VC++6 組みたいプログラムは実行ファイルを開くと他の実行ファイルをオープンさせるという仕組みのプログラムです。 つまり実行ファイルを開いたらブラウザやテキストエディタを起動するようなプログラムを作りたいってこと。
だからstd::systemで対象のexe叩けばいいだろ
>>636 C++Builderなんていう腐りきった処理系は窓から投げ捨てろ
>>640 ありがとうございました。どうも処理系依存の問題のようですから
C++Builder相談室 Part16に行ってみます。
>>643 windows用のC++用開発ツールで、お勧めの腐りきってない処理系って
何ですか?...VC6からC++Builderに逃げ出したのですが...
>>642 WinだったらShellExecuteだけど、スレ違いだから他行ってね。
647 :
デフォルトの名無しさん :2006/04/06(木) 15:55:46
>>645 VC++ じゃなんでだめなの?
2005 Express Edition じゃだめ?
>>645 別にC++Builderでもいいと思うぞ。
少なくとも、VCLは優れたライブラリだと思う。いささか古い設計ではあるけどね。
今後の発展(標準C++やC++0xへの準拠)はもう望めないけれど、
Win専用GUIつきユーティリティ開発なら悪い選択肢ではない。
漏れはgcc/icc+wxWidgets でもこれは他人におすすめできない。
>>647 2005 Express Edition ってVCの新バージョンですか?
乗り換えた頃はVC6で、正確には覚えていないけど、
std::でコンパイルできないことがいくつかあったことと
BCB6にはposix互換関数が揃っていて、UNIXやLinuxへの
移植性があるプログラムが書けると思いました。
IDEのエディタがVCより更にひどかったけど、秀丸を
併用して、セーブしてIDEに戻ると、ソースが変更されました、
読み直しますか?と聞いてくるので、Yes、再コンパイルで
エディタの悪さはカバーできたし...VCLのソースが
パスカルって言うのは気になったけど、ブラックボックスだと
思えばWinMain関数まで隠してしまうMFCよりはましに思えたし...
...で、2005 Express Edition ってBCB10と比べてどういいの?
VC++2005は、、、 やたらと重かったりインテリセンスが鈍くて困る VC++2003から乗り換える理由が見つからん BCBよりはマシじゃね
VC++2005ExpressEdition使ってるけど別に不便なことはない リソースエディタ付いてないけどそういうの使わないし てか発売されてるのは高杉 落とせばいいけど開発者としてなんだか悪い希ガス
>>651 >落とせばいいけど開発者としてなんだか悪い希ガス
なんで?これMSが無償配布してるんだよね
環境依存ネタは他スレでよろ
>>652 それとは別の発売されてる方だろ
雑談終了
VC6の頃、MSDNプロフェッショナルは、年間7万円弱で、 OSとVSが使い放題だった時期があったけど、今は高すぎ。 OS供給だけのMSDNに入ってる。
ここってソースupしたら赤ペン先生してくれますか?
たまにしてくれる人もいるよ 暗号化されたソース読むのも勉強になるし
boost::format というsprintf 相当のモノはあっても、 sscanf に該当するものがないのは寂しいな。
あーすまんistringstream忘れてた
>>661 いや、stringstream があるのに、boost::format が出来たのは、
マニュピレータの指定が面倒だからでしょ。
たとえば、"0123456789ABCDEF" という入力があったとして、
これを、4桁ずつの16進数と解釈して4つの整数変数に設定したい
みたいな要望があったとき、
sscanf( in, "%4X%4X%4X%4X", out1, out2, out3, out5 );
みたいに型安全に書けたら便利かなってこと。
型安全というからには、フォーマット文字列と型が不一致のときは例外でも投げて欲しかった。
664 :
デフォルトの名無しさん :2006/04/06(木) 18:17:29
ありゃ、例外発生しないんだ・・・ これから使ってみようかなと思ってたのに。
引数の数が足りないときは例外が投げられるし、投げられないようにも出来る。 >663が言う件では、投げられないとしても問題が無い部分だ。 let's boostの人がそう言ってるから請け売りしてるだけ。
666 :
663 :2006/04/06(木) 18:31:29
>>665 let's boost の人がそう言っている、というのは知らなかったな。
まあそれはいいとして、俺は以下のコードはとても気持ちが悪いと
思ってるんだが、問題は無いと思うべきなのか?
try {
cout << format("%06d") % 1.23 << endl;
cout << format("%s") % 1.23 << endl;
} catch (...) {
cout << "catch" << endl; // ここにはこない
}
try〜catchの文はあまり頻繁に書きたくない
>>666 だったら、xpressive や、spirit の用に Expression Template で
フォーマット書くようなライブラリを使えばいいじゃん。
例外といわず、コンパイル時に警告してくれるぞ。
print( cout, _0d[6] % _endl, 1.23 ); // (int)1.23 でないと警告
print( cout, _s % _endl, 1.23 ); // コンパイルエラー
>>668 >>666 、は
動的にフォーマットを生成できて、
さらに実行時に型が間違っていれば、
例外を投げてくれるようなものを欲しているのではないか?
>>669 の書き込み見てふと気になったんだけど、
書式文字列を動的生成してるひとってどのくらいいるんだろ?
.NET だと自分自身、設定ファイルに書式書き込んでおいて、
読み込むとか(たまに)やるけど、C/C++ だとやった記憶がない。
>>670 ひと、じゃなくて場面の問題。俺は割合よくやる。
>>670 printf()なら"%*.*s"とかできるから余りやらないけど、scanf()だと融通が利かないからたまにやる。
あー、設定ファイルにフォーマット文字列を書くのはしばしばやるか。
例えば、日付で生成するファイル名を変える場合にFILE_NAME_FORMAT=result_%04d%02d%02d.txtとか。
複雑なプリプロセッサマクロを一時的に全て展開して内容を確かめる方法は無いですか? vc++2005です
コンパイラのオプションにあるよ。 プリプロセッサだけ動かすの。
675 :
デフォルトの名無しさん :2006/04/07(金) 05:14:57
>>662 sscanfはおそろしく速いよ。
parserの型を保存した場合だと、spiritもほぼ同じ速さ。
istringstreamは糞。
spiritはコンパイルが遅いw
677 :
デフォルトの名無しさん :2006/04/07(金) 06:41:20
>>674 IDE 上で簡単に角にできればいいのにね。
679 :
デフォルトの名無しさん :2006/04/07(金) 09:22:05
あ〜「確認できれば」のまちがい。 プリプロセッサでの展開後の姿を覗けたらって感じ。 「お前の本性覗いてやるぞ!」
680 :
デフォルトの名無しさん :2006/04/07(金) 09:39:12
マクロ呼び出ししているところをシングルクリックして [F12] で定義をたどることならできるな
>>680 きっとBoost Preprocessorみたいな複雑なマクロを書いているのだろう。
可変長引数マクロ: #define F(X, Y, ...) X(Y, __VA_ARGS__) って、標準C++で対応してたっけ。 g++ 3.4.2は対応してるけれど、標準かどうかがわからず。
してない。
>>682 vc8でも対応しているから別にいいよそんなこと。
変数xの値によって、生成するクラステンプレートの型を変えたい場合にスマートな方法はないでしょうか。 template <typename T> class C { T value; // 実際にはもっと複雑なクラス }; enum gen_t { i, d, c }; void f(gen_t type) { switch(type) { case i: { C<int> c; g(c); // g()は関数テンプレート // ... } break; case d: { C<double> c; g(c); // ... このようにswitch-caseで分岐するしか思いつきません。
>>685 変数xって何。その例でいうところの f の引数の type のこと?
>>686 すんません、変数xではなくて、fの引数のtypeです。
>>687 gen_tは使わなければいけないの?
template <typename T>
void f()
{
C<T> c;
g(c); // g()は関数テンプレート
}
f <int> ();
の方が素直だと思うのだけど
>>685 コンパイル時に型が決まらないテンプレートを使いたいとき、
仮想関数と組み合わせるというテクニックがある。
struct f_base{ virtual void f() = 0; };
template <typename T> struct f : f_base {
void f() {
C<T> c;
g(c);
// ...
}
};
691 :
690 :2006/04/07(金) 19:54:35
ごめん。struct fのfは別の名前にしておいてくれ。f()はコンストラクタじゃない。
>>685 boost::variantでvisitorパターンとか
#include<boost/variant.hpp>
typedef boost::variant<C<int>,C<double>,C<char> > val;
template <typename T> val create(){return val(T());}
val(*table[])()={create<C<int> >,create<C<double> >,create<C<char> >};
struct call_g : boost::static_visitor<>{template<typename T>void operator()(T&t)const{g(t);}};
void f(gen_t type){
val v = table[(int)type]();
boost::apply_visitor(call_g(),v);
}
>>685 enum gen_t { i, d, c };
template <typename T> void h(){
C<T> t;
g(t);
}
void(*table[])()={h<int>,h<double>,h<char>};
void f(gen_t type){
table[(int)type]();
}
>>688-693 それで教えているつもりか。
まぁヒントぐらいにはなったな。
うむごくろう。
いや、冗談です。マジで参考になります。
>>690 氏の仮想関数だと、派生クラス(f_baseを継承したクラス)のインスタンス化は
やっぱりコンパイル時に行われませんか。
>>692-693 インスタンス化された関数ポインタをテーブルで持っておくアイディアは思いつきませんでした。
thxです!
697 :
デフォルトの名無しさん :2006/04/08(土) 07:39:42
つのだ☆ひろ
699 :
デフォルトの名無しさん :2006/04/08(土) 16:16:41
列挙型の列挙子にアクセスする際に↓ enum eHoge{TEST0,TEST1}; int i = eHoge::TEST0; こんな感じで出来ないんですね
struct eHoge { enum { TEST0, TEST1 }; };
enumは型だから無理だろ int Zeroに対してint::Zeroとかやってるのと同じ
703 :
デフォルトの名無しさん :2006/04/08(土) 16:29:58
>>699 それは非標準ながら VC++ 7.1 なら出来た気がする。
VC++ 8 だとどうかしらん。
>>703 VC++8ではC++/CLIなら699のようになった。
namespaceつかえよ!
707 :
デフォルトの名無しさん :2006/04/08(土) 17:57:48
確かに Enum名::アイテム名 って感じで 値を限定したい気もするよな。 まぁいまさら仕様を変えるのは無理なんだろうけど。
struct/namespace eHoge { enum type { TEST0, TEST1 }; }; とか、enum の方にも名前をつけてないと、 型を使いたい時に困るぞい。
いいえ、それはトムです
712 :
デフォルトの名無しさん :2006/04/08(土) 22:14:38
int a = 1; const long& b = a; って、キャストで一時オブジェクトができて、その一時オブジェクトを 参照するらしいけど、一時オブジェクトって、その式が終わった瞬間 に消滅するから、この記述は無意味?
constな参照型の変数の構築に使われた一時オブジェクトの寿命は、 その変数の寿命まで引き伸ばされるという規定が無かったっけ?
>>712 constの参照の場合、一時オブジェクトはスコープが続く限り
消滅しないだろ。
peekmessageループ中でscanf("%s",c)とやってもうまくいかない (cの値がscanf前後で変わっていないっぽい)のですが そもそもscanfは「いつ(ex 関数が呼び出されて以降)」から「いつ(ex Enterが呼ばれるまで)」までの 入力を受け取る関数なのですか? ちなみにこんな感じの使い方です peekmessage(){ ・ ・ ・ void pushA{//Aキーを押したときの処理 //jyotaiが0のときAを押したらキーボード入力受け取りモードに if (jyotai==0){ scanf("%s",c); } } ・ ・ ・ }
標準入力(stdin)でバッファリングされてたりするから いつからいつまでってないような気がするが。
cがcharのポインタであり、更にその参照する領域が確保済みであることを祈るよ。
>>716 scnaf()は、関数が呼ばれた時点までに確定している入力を受け取る関数です。
ではいつ入力が確定するかと言うと、標準入力が接続されているデバイスによって違います。
720 :
デフォルトの名無しさん :2006/04/09(日) 15:25:02
>>719 その説明だと入力待ちは生じないように聞こえるが?
>scnaf()は、関数が呼ばれた時点までに確定している入力を受け取る関数です。 おまえの環境ではscanfはブロックしないのか?
722 :
719 :2006/04/09(日) 15:29:47
すまん。訂正。 関数が呼ばれた時点までに確定している入力がフォーマットの要請に満たない場合、 エラーが発生しない限り待ちますw
723 :
716 :2006/04/09(日) 15:48:36
みなさんどうもです。
>>718 char c[81]とVC.netのヘルプのサンプルコードそのままに指定してます。
>>719 ということはpeekmessage中だとキーボードからの入力メッセージはいつまで経っても確定しない?
ってことですかね?
>>723 標準入力可能なコンソールプログラムじゃないような気がするが気のせい?
725 :
デフォルトの名無しさん :2006/04/09(日) 23:25:48
effective C++の68ページにmerePoolとmemPoolってあるんですけど。 記述ミスですかね?
class A { public: void a1(); void a2(); // <= a1()を内部で使ったメソッド }; class B : public A { public: void a1(); // <= a1 をオーバーライド }; この時、オーバーライドしたa1()を使った a2() を呼びたいのですが このままだと A::a2()が呼ばれます。良い方法はないでしょうか?
727 :
デフォルトの名無しさん :2006/04/09(日) 23:37:20
つvirtual
a1を仮想関数にしてオーバーロード
729 :
デフォルトの名無しさん :2006/04/09(日) 23:41:37
class A { public: virtual void a1(); // a1 を仮想関数にして void a2(); }; class B : public A { public: using A::a1; void a1(int); // a1 をオーバーロード };
オーバーライドだったっけ?ややこしいな
726です。 できました。ありがとうございました!
732 :
デフォルトの名無しさん :2006/04/10(月) 20:10:25
クラスTがあって、T(i)って表記は、どう考えれば良い? T* a = &T(i); とかOKなの?
OK。問題なし struct T{T*operator&(){return new T;}}; int main(){ T i; T*a=&T(i); }
T(i) <私まんこちゃん! ╋ /\
>>734 _, ,_ パーン
( ‘д‘)
⊂彡☆))============= T(i)
╋
/\
ふいた
&とTの結合度よりもTと()の結合度の方が高いから、 T(i)はTをiで初期化した一時オブジェクトという意味になるだろう。
739 :
デフォルトの名無しさん :2006/04/10(月) 23:07:19
寿命が問題
newした時に一時オブジェクトの内容がコピーされるんでいいんじゃない? deleteしないとメモリリークするが。
ついでに書くと、T(i)と折角書いても、結局operator &()でnew Tが 呼び出されるので、一時変数の内容は無視されている。
743 :
740 :2006/04/10(月) 23:37:01
あーしまった。 ×newした時に一時オブジェクトの内容がコピーされる ○newした後で折角作った一時オブジェクトがそのまま捨てられてしまう。 つまりT()でも良いし、T(j) [jはT型のインスタンス]でも全部同じ意味。
T a = T();
745 :
デフォルトの名無しさん :2006/04/11(火) 00:27:31
あるオブジェクトのインターフェースで、可変長文字列の可変長配列を処理結果として 返すような場合、一回に1配列分の文字列を返すようにする事が考えられますが、 イテレータとか使って一回で返してしまう方法ってあるんでしょうか?
ごめん、732てスタックに積まれたオブジェクトへのポインタを取っているような 気がするけど、間違い無いよね?
>746 あまり美しくはないが、auto_ptr<vector<string> >を返すのがパターンかなぁ。 vector<string>を直で返すのはさすがに気が引けるし。 あ、もちろんvectorでなくても適当なコンテナなら何でもいいけど。 他に何かもっと美しい方法あるかね?
>>748 std::stringについてのOutputIteratorを取るという方法もある。
面倒だし、異なるイテレータを渡すたびにコードが膨張するという欠点はあるが。
>>746 void f(vector<string>& result) じゃダメなの?
んー話は変わるけど、動作がわからない物については、デバッグでコンパイルして、 ソースと逆アセンブル混合で見る(VC8)とよくわかるね。 楽ばかりしてないで最終的には規格票を見なきゃならないんだが、あれ全部を 見るのは大変なので、ちょっとした事は上の方法で見ている。バイナリ嘘つかない。
>>751 > バイナリ嘘つかない
そうでもないよ。未定義動作になるソースに対しても何かしらコードは出るしね。
あと、人に説明するときに「VC8がこうコンパイルしたから〜」じゃ、さすがに
根拠にならない。おとなしく規格嫁。
>748 Sutterお勧めの方法じゃないの?
>>748 >vector<string>を直で返すのはさすがに気が引けるし。
TSC計ってみたけど,うち(A),(B)で殆ど差でないけどなぁ
typedef vector <string> Container;
void init_container (Container &p) {
static const size_t container_size (10), string_size (100);
p.reserve (container_size);
for (size_t i (0); i < container_size; ++ i) {
char c ('a'); string s;
for (size_t j (0); j < string_size; ++ j) s.push_back (c ++);
p.push_back (s);
}
}
Container get_container () {
Container result;
init_container (result);
return result;
}
auto_ptr <Container> get_container_ptr () {
auto_ptr <Container> result (new Container ());
init_container (*result);
return result;
}
Container c0 (get_container ()); // (A)
auto_ptr <Container> c1 (get_container_ptr ()); // (B)
以下のようにするとエラーがでてしまうのですが、何がいけないのでしょうか?(VC8Expr) std::vector<char> v; std::insert_iterator<std::vector<char> > out_itr(v,v.begin()); std::string str("test"); std::copy(str.begin(),str.end(),out_itr); out_itr = 'a';++out_itr;//ここ
*out_itr = 'a'; 後,状況によるけれどそのコードでやっていることをやりたいなら 'a' を最初に突っ込んで,次に [str.rbegin(), str.rend()) を back_inserter に突っ込むほうが効率は良い.
757 :
755 :2006/04/11(火) 09:27:24
>>756 ありがとう、ポインタに値代入しちゃだめですね...orz
背伸びする前に、何をやってるかきちんと理解するところからはじめないと。
伝統的に沸点低いよな、ここ。
764 :
デフォルトの名無しさん :2006/04/11(火) 22:57:03
ポインタなんて、なければいいのに
765 :
デフォルトの名無しさん :2006/04/11(火) 23:04:32
ポインタがわからない PG なんていなくていいのに
人の欠点は平気で責めたがるのに、自分の欠点は見ない奴が多いな。 俺もそうだけどな。
767 :
デフォルトの名無しさん :2006/04/11(火) 23:25:44
欠点だから責めてはならないという法はない 致命的な欠点は仕事への責任感に比例して放置できない 全盲の人が機長になれないのと同じ
>>767 別に責めてはならないとは言ってない。
ただ人を責める前に自分の欠点を直してからにしろと言いたい。
ある奴の欠点が他人から丸見えなのに、そいつに説教されると腹が立つだろう。
769 :
デフォルトの名無しさん :2006/04/11(火) 23:31:52
致命的な欠点と、仕事はできてる欠点を同列には語れない
>>769 わからん奴だな。俺は致命的な欠点については何も言ってない。
お前が勝手に言ってるだけだろう。
771 :
デフォルトの名無しさん :2006/04/11(火) 23:35:12
PG がポインタわかんねーのは、まごうことなき致命的な欠点 治して来てもらう以外に打つ手はない
>>771 それを先に言え馬鹿。
何の一般論かと思ったぜ。
流れ嫁。
全ての型に文字列変換するインターフェースを付けたくて struct IStringifiable{ virtual string toString() const = 0; virtual void Parse(const string& source) = 0; }; template < typename T > struct Stringifiable : public T, public IStringifiable{ virtual string toString() const { 云々かんぬん… } virtual void Parse(const string& source) { 云々かんぬん… } }; なんてことをしたら Stringifiable< int > みたいにしても プリミティブ型を継承できなくて('正しい基本クラスではない'と怒られる)困っています。 この場合StringifiableクラスのメンバーにT型のインスタンスを持つしかないんでしょうか?
何したいのかわからん。
>>774 string StringFrom(T source);
void ParseTo(T& target, string source);
int と Stringifiable についてオーバーロードするか、
template にして特殊化すればいいんじゃね?
778 :
774 :2006/04/12(水) 01:01:26
INIファイルやらコマンドラインやらからの入力に対応できる変数 みたいなモノを考えてました 例えば繰り返す回数をStringifiable< int > repeat_countみたいに定義しておいて IIniFile::Bind("ファイル名", "セクション名", "キー名", repeat_count); ICommandLine::Bind("コマンドライン名", repeat_count); といった感じに関連付けておけば IIniFile::Load("ファイル名"); ICommandLine::Eval(lpCmdLine); とやった時に変数の内容が更新されているような。 これをメンバー変数でやるようにしてしまうと repeat_count = 10; という式が書けなくなってしまうのでなんだかな〜と思ったわけです。 あ、operator const T() constとoperator=(const T& source)を オーバーロードすりゃいいのかな?
template<typename T> string ToString( const T& ); と宣言しといて、 template<> string ToString( const struct Hage& arg ){ //argを文字列に変換するコード } みたいなのを文字列に変換したい型の数だけ実装して、 strunt Hage a = {〜〜〜}; string hageStr = ToString(a); みたいに使えばよくね?
780 :
774 :2006/04/12(水) 01:48:21
>>779 いや、それだとバインドができないので…
とりあえず
>>778 の最後の解決法でやってみてるけど
ユーザー定義型についてStringifiableのメソッドを特殊化してもらうときに
メンバー変数名がわかってないと書けないのは気持ち悪いなぁ
int repeat_count;と定義して、 IIniFile::Bind("ファイル名", "セクション名", "キー名", &repeat_count); という風に使うインタフェースのほうがきれいじゃないだろうか。 Bindをいちいちテンプレートにするのが嫌なら、 IIniFile::Bind("ファイル名", "セクション名", "キー名", make_stringfier(&repeat_count)); とか。
782 :
774 :2006/04/12(水) 02:26:45
>>781 Bindの中でrepeat_countを参照で持つStringifiableのインスタンス作って
それを保持しとけば良いってことかな?
IIniFileとかの中ではいじくりたい変数の型を意識したくないので
なにかしらインターフェースを噛ませる必要があるのだけども
今後テキストエディットからの入力とか、外部から文字列で飛んでくる値を
全部透過的に扱うつもりなんだけど、受け取りたい対象毎に
(INIファイル用、コマンドライン用、エディタからの入力用…etc)
Stringifiableのインスタンスがどんどん増えてくのはどうなんだろう…
ちなみに後出しになって申し訳ないけどソースコード上である変数が
外部から書き換えられる可能性がありますよと明示したい意図もあったりして
説明のため直感的な名前にしたけどほんとはIStringifiableじゃなくて
IConfigurableってインターフェース名です
もう質問は無いな。がんばれよ。 はい次の人どうぞ。
>>779 それだったら、operator <<と>>を作ってboost::lexical_castでよくね?
>>778 どうよ?
// 文字列 => 変数への変換
template< typename T > struct parser {
void operator()( T & dest, string const & src ) const {
dest = ::boost::lexical_cast< T >( src );
}
};
// データバインドを行う
struct data_binder {
::boost::function< void ( string const & ) > update;
template< typename T > void bind( T & value ) {
update = ::boost::bind( parser<T>(), value, ::boost::bind::_1 );
}
};
// 派生クラス
class ini_file : data_bindable {
static map< path, data_binder > content;
public:
template< typename T >
static void bind( string const & fn, ...中略..., T & value )
{
path x( fn, section, key ); // パスを作成
content[x].bind( value ); // バインド完了
}
static void load( string const & filename ) {
/* 何かループ */ {
// TODO: データ読み込み
content[ /*パス*/ ].update( /*読み込んだデータ*/ );
}
}
};
786 :
785 :2006/04/12(水) 19:10:23
あ、ini_file のベースになってる data_bindable は何の意味もないな。 忘れてくれ。
スタックオーバーフローの例外が発生するのですが、こういうものなのでしょうか? struct SList { boost::shared_ptr<SList> next; }; int main(){ SList a; SList* p = &a; for(int i=0;i<100000;i++){ p->next = boost::shared_ptr<SList>(new SList); p = p->next.get(); } }
>>787 cygwin g++ 3.4.4 で試したけど、何事も無く終了したよ。
>>787 SList のデストラクタが全要素分再帰的に呼び出されることになるので、
デストラクタ呼び出しごとのスタック消費の 100000 倍のスタックが必要になる。
環境が書いてないことから想像すると Win32 で VC のデフォルト設定だろうから
スタックが 1M バイト割り当てられていたとして、1回のデストラクタ呼び出しによる
スタック消費が 10 バイト以内( 2 ワード以内)に収まっていればいい計算だが、微妙だな。
790 :
787 :2006/04/13(木) 09:39:03
>>788 VC8Expressなんですが、
コンパイラオプションから/clrをはずしたらうまくいきました。
バグなのかな...
>>790 CLR が挟まってるならスタック消費が 2 ワードじゃ済まなさそうだな。納得。
792 :
785 :2006/04/13(木) 10:05:38
>>785 の data_binder は↓のようにしないとダメだな。
_1 がいつの間にか無名NSに移動してたのは驚いた
// データバインドを行う
struct data_binder {
::boost::function< void ( string const & ) > update;
template< typename T > void bind( T & value ) {
update = boost::bind( parser<T>(), boost::ref(value), _1 );
}
};
ぶぅすとってオイシイ?
はい、オイシイです
あれあれ?怒らせていいんですか?使いますよ。イオナズン。
796 :
787 :2006/04/13(木) 10:21:13
>>789 >>791 デストラクタが深い再帰にならないようにしないといけないんですね。
(/clrだとi=4393までしかいけませんでした。)
小ブロック程度のnewで、メモリを確保できないって事あるんですかね? 一般的な環境(Win Mac Linux辺り)で なんか丁寧に例外取ってるの馬鹿らしくなってきまして
>>797 メモリが有限の資源である以上ある。
丁寧に例外を取るって何やってるか知らんが、多分間違った考え方してる。
>>798 もちろんnewする度にそこでtry-catchしている訳ではなく、メモリ確保できなかったら、
中間層辺りcacthし、データをバックアップする程度なんですが。
仮想メモリもあるし、それすら使い果たす頃には
例外取ってバックアップどころじゃない気もするんですよね
こんなかんじですKA?(><) hevy_weight * p = 0; try { p = new hevy_weight(); } catch( std::bad_alloc const & ) { throw std::runtime_error("メモリ不足です!"); }
スタックの話でなかったの?
ちがうやつじゃね? そしてheavyなスペル違うぞ
>>800 は heavy のスペル違うけど、ひょっとして
メモリ不足で bad_alloc 投げてるのに、ヒープに文字列保存する runtime_error 投げんのかよ!?
みたいな感じでは?
>>799 一般向けOSだとメモリはページ単位(4KBとか)で確保するものが多いから
それ以下のメモリ要求に対し失敗したらruntime_errorも投げれなそう。
漏れの個人的テストだと、小ブロックの確保時にbad_allocが投げられることはあるけど、
わざとそういう状況を作るか、プログラムのバグでHDDが異常にガリガリ言った後に投げられるか、
いずれにしても例外が投げられる前から予想できるときにしか投げられなかった。
そこで、bad_allocに対してtry〜catchをするのではなく、予期しない例外のひとつとしてcatch(...)。
むしろbad_allocより、制御装置固有のとか、特定用途の例外を知りたいわけで。
800さんは別の方です
>>804 勉強になります。貴重な情報感謝。
なるほど、確保失敗時は厳しいので、細かくやらず大きいくくりで捉えておこうという訳ですか。
ありがとうございました。
windowsの「メモリがありません」ダイアログに頼ってます。
807 :
デフォルトの名無しさん :2006/04/14(金) 14:48:58
最近boostを勉強しはじめたんですが、shared_ptrに入っているオブジェクトのポインタを ダウンキャストしたい時はどうすればいいんでしょうか? (例) class foo{}; class bar : public foo{}; typedef boost::shared_ptr<foo> pfoo; foo* b1 = new bar(); pfoo b2 = pfoo(new bar()); // b1なら、 if (dynamic_cast<bar>(*b1)) cout << "this is bar1" << endl; // b2だと? if (dynamic_cast<bar>(*b2)) ; // error!
>>807 訂正
if (dynamic_cast<bar*>(b1)) cout << "this is bar1" << endl;
809 :
デフォルトの名無しさん :2006/04/14(金) 14:56:34
諸君、活発に議論しているかね?
dynamic_cast<bar&>(*b2)
>>807 dynamic_cast<bar*>(b2.get())
fooのデストラクタがvirtualになってないよ。
>>811 b2.get()でいけました。 ありがとう
fooのデストラクタは、例では書かなかったけど作ってるプログラムはvirtualになってます。
>>812 もう遅いかもしれないが、shared_ptr 専用の
shared_static_cast
shared_dynamic_cast
shared_polymorphic_cast
shared_polymorphic_downcast
が定義されている。
上の例だと、
if( shared_polymorphic_downcast<bar>(b2) )
でもいい。
質問なんですが、Windows付属のペイントソフトでブラシの太さ(堅さ?)を3段階で選べますよね? あれをユーザが0から100の値で選べるようにするにはどういうコードを書いたらいいんでしょうか?
819 :
デフォルトの名無しさん :2006/04/14(金) 19:58:43
820 :
816 :2006/04/14(金) 20:11:17
821 :
デフォルトの名無しさん :2006/04/15(土) 11:46:33
boost::shared_ptrで質問です。 class hoge; // forward boost::shared_ptr<hoge> PHoge; class hoge { [※1] owner; vector<PHoge> hoges; }; こんなクラスがあるとき、 あるhogeオブジェクトAOwnerと、 AOwnerに所有されている、AOwnedがあるとき、 AOwnerのvector hogesに、AOwnedが入り、 AOwnedのownerにAOwnerを指すポインタを持ちたいとき AOwnedのownerはweak_ptrにする必要があるのでしょうか? boost::shared_ptrの循環参照の説明読んでたら頭が混乱してしまいました。
ゲ製から誘導されて あちこち探し回っても、的確な答えが見つからないので C++の話だが、 SaveDigit(FILE* stream, int nData); LoadDigit(FILE* stream, int* nData); 名前の通り、int型のファイル入出力を行う関数があるのだが、 COLORREFやDWORDやunsigned intをこの関数で保存したい場合、 当たり前だがキャストが必要になる。 このキャストの時、データは破壊されないのだろうか? それとも、各型毎の関数を作るかテンプレート関数を作るべき?
>>822 各型のサイズやビットパターンは環境依存
>823 サンクス、危うく環境依存のバグを埋め込むとこだった…orz
std::vector<Hoge> container; boost::ptr_vector<Hoge> ptr_container; containerからptr_containerに内容をコピーしたいのですが std::copy(container.begin(), container.end(), std::back_inserter(ptr_container)); ではptr_container.push_back()がHoge*を要求するのでできません。 newしてpush_backするback_insert_iteratorを作る以外で何か方法ありませんか? 標準 or Boostにあるものを使って書ければベストなのですが。
newする関数オブジェクトを書いてstd::transform
using namespace boost::lambda; std::transform(container.begin(), container.end(), std::back_inserter(ptr_container), new_ptr<Hoge>(_1));
828 :
825 :2006/04/15(土) 14:05:34
あ、transformですか。copyという事に執着してました。 push_backイテレータ作るよりはシンプルですね。 これで行きます。ありがとうございました。
質問があるんですが、VC++とC++は違うんでしょうか? いやですね、C++を学習するつもりで本を買ったのですがVC++を買ってました。 C++を学ぶならC++のやつを買いなおした方がいいでしょうか?
オラに10日でC++ヲミニツケルチカラヲクレ
831じゃないけどC++勉強したいけどどこから手をつけていいのか解らなくて 右往左往してる弱った....
まずは漏れの本を読め。 話はそれからだ。
Cを知ってるなら簡単だろ STLやクラスの高度な機能は後回し
836 :
833 :2006/04/16(日) 23:47:41
ループとか標準関数とかはわかったけど ここからどうすればいいの? 何かね課題みたいにプログラム作りたいんだけど なんかいい例ない?1万ステップぐらいのやつがいいんだけど
だれかヘルプミー。 g++ 3.4.4 (cygwin special)で以下のコードをコンパイルしたら、 #include <fstream> bool pattern::read(std::ifstream& ifs) { int w; ifs >> w; } こんなエラーがでました。 pattern.cpp: In member function `bool pattern::read(std::ifstream&)': pattern.cpp:39: error: no match for 'operator>>' in 'ifs >> w' intに対しては operator>> は(cinと同様に)定義されてると思うんだけど……。 なんか不味いことしてますか?
>>837 そのコードは pettern の宣言が無いというエラーになった。
エラーの出るソースはそれだけじゃないだろ。
問題が再現できるコードをちゃんと作れ。
839 :
837 :2006/04/17(月) 00:53:23
>>838 すみませんでした。正確には以下の通りです。
#include <iostream>
class pattern{
public:
bool read(std::ifstream&);
};
bool pattern::read(std::ifstream& ifs)
{
int w;
ifs >> w;
}
>>839 × iostream
○ fstream
再現コード作ってるときに気付くのが、よくあるパターンなんだがな。
>>840 うう、ifstreamは<fstream>ですね。
恐ろしく凡ミスに答えてくださってアリガトウございます。
全くお恥ずかしい限りで……。
843 :
デフォルトの名無しさん :2006/04/17(月) 04:58:33
new ch[10]; などとして確保したバッファ領域にデータを代入した後、そのデータはそのままに、 おしりに、さらに10バイト分のデータを追加したい場合、Cだと realloc()で、代入 データをそのままに、メモリー領域を拡大できますが、new した場合はそのような 事はできませんか? できない場合は、別途 20バイト分newして、そこにそれぞれをコピーして繋げる しかないでしょうか?
844 :
デフォルトの名無しさん :2006/04/17(月) 04:59:04
new ch[10] -> new char[10]の間違いでした。
>>843 その通り。realloc()を使わない方が良いのは、delete演算子で
デストラクタが働く事があるためです。
いや、むしろ ×realloc()を使わない方が良いのは ○realloc()を使ってはいけないのは
>>843 先ずはnew/deleteを使う戦略を見直す。
例えば、vectorなら何も悩む必要がなくなる。
一応デストラクタを自前で呼ぶ事もできるけど、 そこまでパフォーマンスを追求する(realloc を使う)必要性があるか、だな。
>>841 そこほとんどCじゃんw
たまに、悪ふざけしているような回答者がC++でコード書いてるけど
というか、まあ、どうやって身に付ければいいんだろうね
おれは適当に本読んで、プログラム書いたりしてるけど
細かいところの知識があちこち欠けている気がする
ADLとか
まともでそこそこなアプリ作ろうとしたら軽く1万いきそうだけど・・・
>>849 それを題材としてC++で組め、っていう話だろう・・・
Aというクラスがあったとして、 A* pa1 = new A(); A* pa2 = new A; この2つの命令に何か違いはあるのでしょうか。 同じ意味だとは思うんですが、確信が持てないです。 ちょっとした違いでもあれば教えて下さい。 delete pa1; delete pa2;
>>852 前者は0フィル。
後者はデフォルト・コンストラクタが呼ばれる。
あ。もちろん前者も0フィルの後デフォルト・コンストラクタが呼ばれる。
0で初期化なんてあったっけ?
856 :
852 :2006/04/17(月) 23:56:12
>>853 実際に試してみたんですが、どちらも初期化されてませんでした。
C++言語仕様ではそうなっていて、私の環境では仕様に沿ってない実装ってことになるのでしょうか。
それとも他の意味があるのかな。
C#と混同してるんだろ。
858 :
852 :2006/04/18(火) 00:01:36
確かに、C#はフィールドを初期化しますね。 なかなか素敵な言語仕様です。 結局、上で挙げた2つは全く同じだ、ということになるんですかね。
§5.3.4.15 15 A new-expression that creates an object of type T initializes that object as follows: . If the new-initializer is omitted: . If T is a (possibly cv-qualified) non-POD class type (or array thereof), the object is defaultinitialized (8.5). If T is a const-qualified type, the underlying class type shall have a user-declared default constructor. . Otherwise, the object created has indeterminate value. If T is a const-qualified type, or a (possibly cv-qualified) POD class type (or array thereof) containing (directly or indirectly) a member of const-qualified type, the program is ill-formed; という事で、非POD型はデフォルト・コンストラクタ、POD型は不定値。
追加 . If the new-initializer is of the form (), the item is value-initialized (8.5); . If the new-initializer is of the form (expression-list) and T is a class type, the appropriate constructor is called, using expression-list as the arguments (8.5); . If the new-initializer is of the form (expression-list) and T is an arithmetic, enumeration, pointer, or pointer-to-member type and expression-list comprises exactly one expression, then the object is initialized to the (possibly converted) value of the expression (8.5); . Otherwise the new-expression is ill-formed. で、§8.5を見てみると・・・・ 8 [Note: since () is not permitted by the syntax for initializer, X a(); is not the declaration of an object of class X, but the declaration of a function taking no argument and returning an X. The form () is permitted in certain other initialization contexts (5.3.4, 5.2.3, 12.6.2). ]
5 To zero-initialize an object of type T means: . if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T; . if T is a non-union class type, each nonstatic data member and each base-class subobject is zeroinitialized; . if T is a union type, the object’s first named data member89) is zero-initialized; . if T is an array type, each element is zero-initialized; . if T is a reference type, no initialization is performed. To default-initialize an object of type T means: . if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor); . if T is an array type, each element is default-initialized; . otherwise, the object is zero-initialized. To value-initialize an object of type T means: . if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor); . if T is a non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized; という事で、A()の形は非POD型はデフォルト・コンストラクタ、POD型はzeroで初期化される。 ここがAという形とは違う唯一の点か。
ごめん
>>860 は不要。
>>859 と
>>861 だけ見てね。
#include <iostream>
struct A {
int a;
};
int main()
{
int* pi1 = new int();
int* pi2 = new int;
A* pa = new A();
A* pb = new A;
std::cout << *pi1 << std::endl; // ここだけ必ず 0
std::cout << *pi2 << std::endl;
std::cout << pa->a << std::endl;
std::cout << pb->a << std::endl;
delete pb;
delete pa;
delete pi2;
delete pi1;
}
863 :
852 :2006/04/18(火) 00:21:46
なるほどなるほど。 これからは、new intに()をつけようって思いました。 ありがとうございました。
#include <iostream> struct A { int a; }; struct B { int b; void print() const { std::cout << b << std::endl; } private: virtual void f() {} // 非PODにする }; int main() { int* pi1 = new int(); int* pi2 = new int; A* pa = new A(); A* pb = new A; B* pa2 = new B(); B* pb2 = new B; std::cout << *pi1 << std::endl; // ここは必ず 0 std::cout << *pi2 << std::endl; std::cout << pa->a << std::endl; // ここも必ず 0 std::cout << pb->a << std::endl; pa2->print(); // もはや0である保証はない pb2->print();
delete pa2; delete pb2; delete pb; delete pa; delete pi2; delete pi1; }
俺も知らなんだ。 便乗して char p[] = "123456"; new(p) char[3](); // 先頭3つだけ0にセット これもあり?
>>863 そもそもintをnewすることがナンセンス。
>>866 おk
#include <iostream>
#include <algorithm>
void print(int i) {
std::cout << i << ' ';
}
int main()
{
char p[] = "123456";
new(p) char[3](); // 先頭3つだけ0にセット
std::for_each(p, p + sizeof(p), print);
}
配置newってdeleteしなくていいの?
>>869 配置newで配置したオブジェクトがデストラクタを持っている時だけ
呼び出す必要がある。
というか、char[3]ってデストラクタないでしょう。呼び出したくても
呼び出せない。
まさか delete p; したいとか? そんな事は思ってないよね?
872 :
833 :2006/04/18(火) 02:20:17
delete char[3] したいです。 new char[3]できるからしたいです
>>872 やっても構わないけど、undefinedだよ。鼻から悪魔が出てくるかも。
new char[3] と new(p) char[3] の違いをもう一度調べてみよう。
>>862 > std::cout << pa->a << std::endl;
↑ここも必ず 0 じゃね?
>>864 > pa2->print(); // もはや0である保証はない
↑ここも必ず 0 じゃね?
new B() は "value-initialized" で B は
"a class type with a user-declared constructor" じゃなくて
"a non-union class type without a user-declared constructor" だから
pa2->b は "value-initialized" → "zero-initialized" で 0 になるだろ。
型を返す非static関数は書けますか?
>>874 そう思うならやってみろや。
わざわざ仮想関数を入れてnon-PODにしている意味がわからないのか?
>>875 直接に型は返せないが、
ポリモーフィズムや列挙型を使って
それなりのことはできる。
そこでthisポインタをthrowですよ。
お前等エスパーだな。
881 :
デフォルトの名無しさん :2006/04/18(火) 09:18:04
オブジェクトへの参照を返しながら そのオブジェクトをこっそり delete するのって、 登り掛けてる人のハシゴはずすみたいで いたずらっぽくて楽しいよな。
>>879 型が分からなければcatchできないのでは?
>>879 パフォーマンスを度外視すれば確かに
型を返したと言えるね。
884 :
876 :2006/04/18(火) 09:39:17
自己解決しましたwww
885 :
デフォルトの名無しさん :2006/04/18(火) 10:02:54
>>877 とりあえず g++ でやってみたら全部 0 になったわけだが。
規格の話をしてるんだから、自分の持ってるコンパイラの
実験結果がわかっても意味無いだろ。
POD かどうかは "a class type with a user-declared constructor" にも
"a non-union class type without a user-declared constructor" にも関係ないから
意味がわからん。
>>885 あまりにも使わないので、存在を忘れかけていた。
型情報じゃなく、型そのものを返す関数やクラスは作成できないものか、という意味でした。 考えてたら夜があけてしまい、2chに質問書いて寝ていま起きましたスンマセン
889 :
886 :2006/04/18(火) 10:38:39
struct A { int a; // virtual ~A(); }; A* f() { return new A(); } こんなコードのアセンブリ吐かせてみた。 cygwin gcc 3.4.4 では non-POD にすると a は初期化されなかった。 とりあえず、 value-initialized に頼るのはまだまだ危険みたいだな。 だれか他のコンパイラの対応状況をレポートしてくれると助かる。
>>888 だから、意味がわかんねぇって。 C++ でおk
型は返せません、以上。
template でメタプログラミングしてることも考えると、そうとも言い切れない。 875 や 888 は、絶対違うだろうけど。
多分、こんな使い方を想定してるんだろう。 type foo() { return int; } type t = foo(); t n = 0; cout << n << endl; まあ、直接は無理だな。 近い事はできるかもしれんが。
実はファンクタを作りたいだけだったりして。
>>894 衝動的に MP に置き換えてみたが、面白くなかった。
struct foo {
typedef int type;
};
typedef foo::type t;
t n = 0;
cout << n << endl;
#include <iostream> #include <memory> class FooType { public: virtual void run() = 0; protected: template <typename type> static void body() { type n = 0; std::cout << n << std::endl; } }; template <typename type> class FooTypeRet : public FooType { public: virtual void run() { body<type>(); } }; std::auto_ptr<FooType> foo() { std::auto_ptr<FooType> type(new FooTypeRet<int>); return type; } int main() { std::auto_ptr<FooType> type = foo(); type->run(); } 近いと言えば近いのかもしれないコード。
898 :
デフォルトの名無しさん :2006/04/18(火) 12:30:45
VC++6でSHORT型の配列1000個を持っているクラスのインスタンスを1ギガ分くらい確保したいのですが、何故か動きません。 *P=NEW CLASS1[500000] 2*30000 600MBなら取れるのですがそれ以上になると落ちます。 助けてください
C++標準にSHORTやNEWなんてのはありません。 スレ違い。
900 :
デフォルトの名無しさん :2006/04/18(火) 12:57:15
shortとnewは標準C++規約じゃなかったんですね。
901 :
デフォルトの名無しさん :2006/04/18(火) 12:59:57
>>900 キーワードは case sensitive です。
902 :
デフォルトの名無しさん :2006/04/18(火) 13:10:23
自分で解決してみます。携帯なんでめんどい
903 :
デフォルトの名無しさん :2006/04/18(火) 13:36:30
アセンブラ部分に別変数を噛ませたら解決しました
最後までスレ違いには気付かないわけだな
PentiumDのマシンを買うことを検討しているのですが gccなどで、両方のコアに計算させたいと考えています。 コンパイラオプションなどで簡単に処理を分散させることはできるでしょうか? あるいは、それぞれのコアに分担を割り振る命令がC++のコードレベルで必須と なるでしょうか。 よろしくお願いします。
スレッド分ければ勝手にやってくれるんじゃね? ちなみにオレはデュアルコアが欲しくて仕方ないんだが、 あと半年なんとか我慢して待つつもり。
漏れは Vista SP1 待ち。 あと2年はあたらしいPC買えそうにもない
908 :
905 :2006/04/18(火) 16:43:42
>>905 >コンパイラオプションなどで簡単に処理を分散させることはできるでしょうか?
>あるいは、それぞれのコアに分担を割り振る命令がC++のコードレベルで必須と
>なるでしょうか。
後者
マルチスレッド
マルチプロセス
あたりがキーワード
910 :
905 :2006/04/18(火) 16:53:48
>>909 後者とのこと
ありがとうございます。
キーワード含め、もう少し調べてみます。
911 :
905 :2006/04/18(火) 17:15:23
無料かつOpenMPで並列化するのならWindows環境だとVC++2005Expressが一番楽だぞ。 LinuxならICCが無料で使える。gompは・・・まあ、ね。
913 :
905 :2006/04/18(火) 18:29:54
>>912 ありがとうございます。
ICCいいですね。
あと
GCCも4.2でOpenMP対応するとの説もあるようで、先が楽しみです。
みなさま、ありがとうございました。
914 :
デフォルトの名無しさん :2006/04/18(火) 20:43:03
>>898 VC6 やとデフォで nothrow ちゃうか?
915 :
デフォルトの名無しさん :2006/04/18(火) 20:44:38
>>905 CPU アフィニティは OS のシステムコールで制御するものなんで
このスレで話せることは少なそうだな
917 :
833 :2006/04/19(水) 01:07:16
6/7日発売だよ焜炉 自作板の情報だからまぁほぼ確定だと思うよ
template <class T> class Hoge : Hogehoge<T> { ... }; このようなクラスがあったとき、Hoge のコンストラクタのイニシャライザで @Hoge(int x) : Hogehoge(x) { ... } AHoge(int x) : Hogehoge<T>(x) { ... } とするのではどちらが正しいのですか? VC8では両方、g++3.4ではAがコンパイル通ったのですが
A
namespace LLNN = LongLongNamespaceName; 上の様な分って重なっても大丈夫なのでしょうか? 例えば、 a.h namespace LongLongNamespaceName {ほげ} namespace LLNN = LongLongNamespaceName; b.h #include "a.h" namespace LongLongNamespaceName {はげ} namespace LLNN = LongLongNamespaceName; 上の場合、b.hでnamespace LLNN = LongLongNamespaceName;の部分がa.hのそれと ダブってしまうと思うのですが
いいよ。 っていうか試してみたらすぐ分かると思うが
template <class T> class C { public: T& getT() { return t_; } private: T t_; }; template <class T> class D : public C<T> { public: T& f() { return getT(); } }; 上記のコードをg++3.2でコンパイルしたところ、 Main.cpp: In member function `T& D<T>::f()': Main.cpp:11: error: there are no arguments to `getT' that depend on a template parameter, so a declaration of `getT' must be available Main.cpp:11: error: (if you use `-fpermissive', G++ will accept your code, but allowing the use of an undeclared name is deprecated) とエラーが出ました。私にはどこも間違っているように見えないのですが、これはg++のバグでしょうか? それとも上記のコードにどこか間違いがあるのでしょうか?
>>922 Dの基底であるC<T>はテンプレート引数であるTに依存しているから
Dのコンパイル時点では型が確定していないのでgetTを持つかどうかが不明。よってエラー。
ってことらしい。
>>922 言い忘れた。
this->getT()やC<T>::getT()と明示的に呼ぶか
適当な所でusing C<T>::getT;を入れればOKっぽい。
>>924 ありがとうございます
教えていただいた方法で問題は解決出来たのですが、
>Dのコンパイル時点では型が確定していないのでgetTを持つかどうかが不明。
というのがよく理解できませんでした。
Tの如何に関わらず、C<T>はgetTを持つので、C<T>からpublicに派生する
Dも当然getTを持つと思うのですが・・
>>925 テンプレートの解釈は、二段階の名前解決をふむ。
最初は、Nondependentな名前のみが解決され、
インスタンス化されるときに、Dependetな名前が解決される。
Two-Phase Lookupという。
Dependentは、簡単に言うとテンプレートがかかわるもの。
たとえば、グローバルにgetT()という関数があったらどうなる?
当然、こっちのほうを呼び出すべき。
VCとかは、インスタンス化されるときに、すべての名前を解決するから、
>>922 のようなコードでも、問題なく通ってしまう。
928 :
デフォルトの名無しさん :2006/04/20(木) 09:27:44
Win32 APIでよくあるA/Wを吸収するマクロは型の場合、typedefでも代用できますか? #ifdef UNICODE typedef CHogeA CHoge; #else typedef CHogeW CHoge; #endif
>>928 可能、というよりWinAPIでもTCHAR型は
#ifdef _UNICODE
typedef wchar_t TCHAR;
#else
typedef char TCHAR;
#endif
となっているはず
>>929 どうも有り難うございます。
てっきり#defineだけかと思ってました。
A/Wの区別って、引数リストで区別できないの?
>>931 APIはC++だけのものじゃないので無理。
boost::ptr_vectorには何故resizeが無いのでしょうか?
>>931 GetWindowTextA/Wのように引数や戻り値まで全く同じものがある。
それでもC++ならテンプレートの特殊化でどうにかできるけれどさ。
C++のオーバーロードでは、GetCommandLineは区別できないな
ファイルの文字を一文字ずつ取得したくて while (!ifstr.eor()) { // ifstr = ifstream char ch; ifstr >> ch; cout << ch; } と書いたのですが、何故か改行が表示されなかったので、今度は while (!ifstr.eor() { std::cout << (char)ifstr.get(); } としたら今度は一番最後に変な文字(見たところ値は-1のようです)が表示されるようになりました。 どうすれば私のしたいことが出来るようになるのか教えてください
とりあえず、chはループの外で宣言な。
getして 初めて気づく 俺EOF
940 :
デフォルトの名無しさん :2006/04/20(木) 21:30:14
エオフ
独習C++という本の12章の理解度チェックの問題4 の解答をコンパイルしてみたらエラーで動きません。 警告も出ています。 警告の内容は以下のとおりです c:\一鉄\趣味\ゲーム作成\勉強\TeachYourselfC++\12-check-4.cpp(45) : warning C4541: 'typeid' が /GR- を使用したポリモーフィック型 'A' で使用されています; 動作結果は保証されません。 c:\一鉄\趣味\ゲーム作成\勉強\TeachYourselfC++\12-check-4.cpp(47) : (省略) c:\一鉄\趣味\ゲーム作成\勉強\TeachYourselfC++\12-check-4.cpp(49) : (省略) 警告だけで、エラーではないのでコンパイルは出来ます。 ですが実行時になってからエラーが表示されます それの内容は This Application has requested the Runtime to terminate it in an unsual way. Please contact the application's support tema for more information. です。 いろいろためしてみると myclassというクラスとそのクラス型のobjというオブジェクトがあったとすると typeid(obj)は機能するのですが typeid(myclass)は機能しません。 だれかどうすればいいか分かる方はいませんか? 長々とすいませんですた
>>941 コンパイラによっては、RTIIを使う際コンパイラオプションで
RTIIを使うことを指定しないといけないことがある。
一鉄w
一鉄打ち込んだソースみせてくれよ
>>942 細かいことなんだが、実行時型情報はRTTIじゃなかったか?
run time type informations
run time type identification?
information
string型に格納されている文字列の 一番最後の文字を取るにはどうすれば良いですか? vectorとかならback()で取れるんですが・・
*str.rbegin() str[str.size() - 1] *(str.begin() + str.size() - 1) *(--str.end())
そろそろ次スレ。 テンプレにある cuj のリンクどうする?
>>953 >OK, we all know std::basic_string is bloated and already has way too many members.
書き出しがこれかよwww
C++98→C++03の変更は細かい修正だけと聞いていますが、 その差分だけまとめた文書はないでしょうか? 双方もっているのですが、自分で調べるのは大変なので。
959 :
957 :2006/04/22(土) 09:01:55
ありがトン
あふぉぢゃねーの
fread(3)とかの3って引数の数?manの3? どっちが一般的?
manの3。ライブラリだぜということ。UNIX以外では意味ない。 引数の数で使うことはない。 それからスレ違い。
std::vectorやstd::map等のコンテナについてなんですが begin(), end()や、イテレータの代入・インクリメント・デクリメント等の操作で 例外がthrowされる可能性はあるんでしょうか?
begin() end() それぞれの operator についてソースを読めば?
いや、実装依存の話じゃなく規格で定められているのかなと。
それこそ規格書読めばという話になるが
>>963 禿本Special Editionの付録Eを読んで。
今手元にないからアレだけど。
強い保証と非送出保証が書かれてないものは規格的に未定義。
ifstreamでテキストファイルを読み込む場合なんですが、 一度目は問題なく読み込めるんですが、 同じ作業中にもう一度同じファイルを読み込もうとした場合、 ちゃんと読み込めないことがあるんですが、どうなってるんでしょう?
「ちゃんと読み込めない」を具体的に
foo970(char *filename) { ifstream file1(filename); : : //←なぜかクローズしてない ifstream file2(filename); readline(line); // ちゃんと読み込めない }
973 :
970 :2006/04/27(木) 15:10:56
ファイルのオープンはできてるんですが、 文字をどうも文字化けを起こした状態で読み込んでしまっているようです。 必ず起こるわけではなく、時折繰り返しているうちに起こります。
974 :
970 :2006/04/27(木) 15:12:57
クローズはきちんと行ってます。
最初に開いたファイルに書き込みとかしてるの?
976 :
970 :2006/04/27(木) 15:14:12
書き込みはしてません。読み込むだけです。
読めないファイルとコードを晒してくれたほうが早いな
とりあえず、open出来たかどうかとか、読み込み成功したかとかは is_open(), good()とかで確認してる?
979 :
970 :2006/04/27(木) 15:19:17
丸コピでスマソ。 fi.open(fileChar, ios::in | ios::binary); if (fi){ while(charaNum < 100){ charaNum++; fi.seekg(1, ios::cur); } fi.seekg(0, ios::beg); while(!fi.eof()) //ファイルの最後にきたら終了 { sprintf(cha2, "%s", cha1); fi.read(cha1, 1); sprintf(chan, "%s%s", cha2, cha1); if (strcmp(chan, "le") == 0){//改行 strs.erase(strs.end() - 1); strvec.push_back(new string(strs, 0, strs.size())); strs = ""; fi.seekg(2, ios::cur); }else{ strs.append(cha1);//文字を保存 } } fi.getline(chars, 255); strvec.push_back(new string(chars)); } fi.close();
つバッファオーバーフロー
初期化してないcha1の使いまわしでcha2が溢れてるだけじゃねーの?
982 :
970 :2006/04/27(木) 15:32:19
再度読み込む際は、これのあるオブジェクトごとdeleteしてるので、 バッファオーバーフローは無いと思うんですが。 一応格納する文字列のサイズは読み込む際は毎回0になってます。
983 :
970 :2006/04/27(木) 15:33:19
sprintf(cha1, ""); sprintf(cha2, ""); で一応初期化はしてます。
chaではじまる変数の宣言と読み込もうとしたファイルのサイズも晒せ
985 :
970 :2006/04/27(木) 15:37:15
vector<string*> strvec;//ファイル内容行ごとに格納 string strs;//一行読み込み int charaNum;//文字数 char cha; char cha1[2]; char cha2[2]; char chan[4]; char fileChar[100]; ifstream fi;//ファイル入力 ファイルサイズは34.6kb〜65.9kbです。
sprintf(cha1, "");がまずい 最初の一バイト目だけ'\0'で初期化されるけど、ニバイト目にはゴミが入ってる可能性がある。 fi.read(cha1, 1); で一バイト目に文字を入れたのはいいけど、ニバイト目に運良く'\0'が入っていれば次の sprintf(chan, "%s%s", cha2, cha1); で期待通りの動作になる。 でも、ニバイト目に'\0'じゃないなにか ('A'とか)がはいってると sprintf(chan, "%s%s", cha2, cha1); で readで読んだ一文字目 + 'A' + '\0'が現れるまで延々と続く ゴミ文字列がchanにコピーされる chanのサイズが4バイト分しかないんで、3文字+'\0'を越える長さの文字列を入れると悲しいことが起こる。 readした直後に cha1[1] = '\0';とかやっとけば問題ない 二文字目にたまたま何が入ってるかは、おまいのプログラムのつくりによるんだが 一回目は'\0'が入ってて、二回目以降は違うものが入ってるんだと思う
987 :
970 :2006/04/27(木) 16:09:04
ありがとうございました。 おかげ様で上手く行きそうです。 助かりました。 こんな落とし穴があったとは。
std::ifstreamやofstreamなどのファイルストリームが デストラクタで自動的にcloseされるようになっていない のには何か理由があるのですか?
>>970 最後まで読んでstd::ios::eofbitとかstd::ios::failbitが立ってしまってんだろ。
C++のファイルストリームは、Cとは違い、一度これらのフラグが立ったら、
自動ではクリアされない。そして、クリアしないと入出力が停止される。
clear()汁。
991 :
デフォルトの名無しさん :2006/04/28(金) 07:47:59
俺の股間もよく failbit がたってしまいます。 clear() しても今度はすぐにストリームが空になって eofbit たってしまいます。
これだからスパゲティちんこは・・・
993 :
デフォルトの名無しさん :2006/04/28(金) 08:32:04
openできなくなるよりマシ
(脳内)彼女のソケットも open できません。
STLつかうと一気に実行ファイルサイズが10倍に?!
>>997 環境によるだろ。
俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力
ランタイムを使用するようにして使っているが、例えばstd::vectorを
使っても使わない時と比べ10Kほどしか増えない。
すげえ!うむごくろう
1000
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。