1 :
デフォルトの名無しさん :
04/06/02 23:08 C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
テンプレートライブラリ(STL含む)に関する質問は
専用の別スレにお願いッス。
過去スレ、関連スレ、関連リンクなどは
>>2-9 あたり
4 G E T
6 G E T
8 G E T
Z
14 :
デフォルトの名無しさん :04/06/02 23:51
前スレのclassとstructだけど、javaからきた人(?)はinterfaceのかわりにstructとか 使ったりするのかな?
15 :
デフォルトの名無しさん :04/06/02 23:53
>>14 逆に聞くがインターフェイスでprivateにすべきメンバとは?
17 :
デフォルトの名無しさん :04/06/03 00:20
以下のコードをコンパイルすると、 g++-2.95 (gcc 2.95.4 20011002 Debian)ではエラーなしでコンパイルされるけれど、 g++-3.2 (gcc 3.2.3 Debian) では最後につけたエラーになります。 これは、どうなるのが正しいのでしょうか? (ちなみに TestBuilder というツールで発生するコンパイルエラーのエッセンスです。) ----- tst.cpp #include <iostream> using namespace std; typedef int PLI_INT32; typedef struct t_vc_record { PLI_INT32 vc_reason; } s_vc_record, *p_vc_record; extern "C" int chpiPliValueCBF(p_vc_record vcRecordP); extern "C" { typedef int chpiPliValueCBFT(); } void acc_vcl_delete (int * object_p, PLI_INT32 (*)(p_vc_record), char *user_data, PLI_INT32 vcl_flags); int main() { char* ch; acc_vcl_delete(NULL, (chpiPliValueCBFT*)chpiPliValueCBF, ch, 2); } int chpiPliValueCBF(p_vc_record vcRecordP) { cout << "chpiPliValueCBF" << endl; } ---- エラーメッセージ g++ -c -o tst.o tst.cpp tst.cpp: function 内の `int main()': tst.cpp:18: error: invalid conversion from `int (*)()' to `PLI_INT32 (*)(t_vc_record*)'
ごめんなさい。 以下のようにするとコンパイルが通りました。 typedef int chpiPliValueCBFT(p_vc_record); ということは、2.95 は、(C っぽく)ポインタを自動変換するけど、 3.2 では、(C++ らしく)ポインタを自動変換しないので、 エラーになるということでしょうか?
>>19 改行が多すぎるといわれたので、つめてしまってました。
実際には、以下の行でエラーになってました。
acc_vcl_delete(NULL, (chpiPliValueCBFT*)chpiPliValueCBF, ch, 2); }
STLつかうと一気に実行ファイルサイズが10倍に?!
>>22 環境によるだろ。
俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力
ランタイムを使用するようにして使っているが、例えばstd::vectorを
使っても使わない時と比べ10Kほどしか増えない。
>>1 すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。
はいはい、スレ1つにつき1回だけだよ。 このスレじゃもう終わりだよ。
C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。 とかいうエラーが出るんだけどこれってどうすればいいのですか?
>>27 #include "stdafx.h"
後死ね。
>>28 言葉が悪いな。それで教えているつもりか。
まぁヒントぐらいにはなったな。
うむごくろう。
つりはよそでやれ。あとググれ。
ググレカレー
32 :
デフォルトの名無しさん :04/06/04 01:32
ファイルからMD5ハッシュ値を計算して16進表示させたいんですが CryptCreateHashは使えるでしょうか。 文字列のハッシュ値は求めれるようですが、サイズの大きなファイルから 求めるにはどうしたらいいのでしょうか。
>>32 このスレのタイトルを声に出して10回嫁。
>>32 そのファイルが読み込めるだけの記憶域を取得できれば可能。
だがその前にスレタイ読んで回線切って(tbs
35 :
デフォルトの名無しさん :04/06/04 07:45
fopen系、fstream系、CreateFile系 みんなさんはファイル入出力どれ使ってますか! (というかどれが好み?) 最近ftream系を使い出して機能豊富に脱毛してたんだが、 いかんせん使い方にクセがあって戸惑ってますよ。
>>35 そりゃ、fstream。C++スレだしな。
個人的にはCStdioFileがおすすめだよ。
>>35 iostreamが楽
#DirectXのファイル入力これにしてくれよ~>MS
>>35 ライブラリを使わない時は API。それ以外は fstream。
fopen は間違っても使わない。
取り合えず禿になる前に慣れろ。
便乗で質問なんですが FILE構造体とかストリームオブジェクトが管理する入出力バッファって、 どこら辺に配置されているんでしょうか? まぁ、そうそう手が出せない領域に置かれるとは思うんですが
>>40 手の出せない領域ってなんだ?
例えばVC++6.0の標準ライブラリならソース追っかければ分かるが、最終的にFILE構造体を
確保してるのはただのmallocだが。
はじめまして、こんにちは! VC++ 6.0 で CrystalReports 10 を使って帳票を印刷 するプログラムを作りたいと考えています。 でも、いくら探しても方法やサンプルコード等どこに も載っていません。 どなたかご存知の方いらっしゃいませんか? よろしくお願い致します。
>>42 このスレのタイトルを声に出して10回嫁。
と言っても理解できそうにないな。
スレ違いだ。VCスレに逝け。
>>11
Win32APIスレだと思うが
意外とfstream使ってる人多いんだな! 慣れるまで我慢して使ってみる事にします。 所でfstream::read()でバッファに読んだ時に 実際に読んだサイズってどこから取ってくるんでしょう? 読む前と後でtellp()って事はないですよね・・・。
>>43 お口は悪いようですが、親切なんですね。
教えていただいたところを見てみます。
ありがとうございます。
>>45 int basic_istream::gcount( );
>>40 C++ の場合、basic_filebuf がソレ
>>45 fstreamなんて糞だから間違っても使うな。
fopen系で処理しとけば問題ない。
std::stringの後ろ1文字削るのにresizeとeraseどっちがいいと思う?
どちらも使わずそのまま使う。
例外について教えてください。とある関数が void f() throw(std::bad_exception) { ... throw int(); } とあったとすると、int型は関数の例外指定に無いので、throwすると 代わりにbad_exceptionが投げられると本にあったのですが、これだと throw int()の時点で強制終了されてしまいます。 throw std::bad_exception() とすると、外側の関数でbad_exceptionが キャッチできるのですが・・・。ちなみにVC.NETです。 なぜ終了してしまうのでしょうか?
53 :
デフォルトの名無しさん :04/06/05 08:11
>>52 ISOでもJISでもいいが規格票の 15.4 の 8 を読んでみれ
横槍でスマンがもまいらひとつ教えてくれ。 規格表、規格表ってよく出てくるけど、あんなもの カネ出して本当に買ってるのか? コンパイラ作るワケじゃないし、禿の本で十分 だと思って漏れは買ってないのだが、何かお得 な情報が詰まってるのか??
>>52 >とあったとすると、int型は関数の例外指定に無いので、throwすると
>代わりにbad_exceptionが投げられると本にあったのですが、
どんな本だ?(((( ;゜Д゜)))ガクガクブルブル
>>57 こういう事だろう。VC++6.0のような古い処理系では動くかどうか知らんが。
#include <iostream>
#include <exception>
void my_unexpected_handler()
{
throw 1234;
}
void f() throw(std::bad_exception)
{
throw int();
}
int main()
{
std::set_unexpected(my_unexpected_handler);
try {
f();
}
catch (const std::bad_exception& e) {
std::cout << e.what() << std::endl;
}
catch (int i) {
std::cout << "User defined unexpected hadler threw " << i << std::endl;
}
}
>>50 pop_backみたいな、ぴったり合う操作が無いな。push_backはあるのに。
resize(size()-1)のほうが効率はよさそう。
erase(end()-1)のほうがソース上に突然現れたときに意味がとりやすそう。
まじめなソースなら、
inline void pop_back(std::string& s){ resize(s.size()-1); }
と定義してしまうのが最善手かと思う。
レスありがとうございます。 私の説明がおかしかったようで、もう少し正確に書くと、本には class A; class B; void f() throw(A) { throw A(); //A型例外を送出 throw B(); //unexpected()を呼ぶ→unexpeted()がterminate()を呼ぶ } bad_exceptionをした場合・・・ void f() throw(A, std::bad_exception) { throw A(); //A型例外を送出 throw B(); //unexpected()を呼ぶ→unexpected()がbad_exceptionを送出 } とまぁこういったことが書いてありましたので、たとえばint()をスローする と当然bad_exceptionが投げられて、外側でbad_exception型の例外がキャッチ できるのかと思ったのですが・・・違いますか?
>>54 俺は買ってるが。プログラミング言語 C++ は言語制作者の手による本だとは
言っても、結局、微妙なところになると載ってないし。
JIS から買うと高いが ANSI から PDF で買えば US$20 しないぞ。
ISO で規格制定した C++ をJIS/ANSIから買えるって?
1000ページの解説本ですら解説しきれない仕様そのものが問題だな。
>>60 違う。unexpected()関数はデフォルトでは常にterminate()しか呼び出さない。
set_unexpected()でunexpected()の代わりに呼び出す関数を入れ替えた時のみ、
その入れ替えられた関数がstd::bad_exceptionを投入する。§15.5.2.2
66 :
デフォルトの名無しさん :04/06/05 14:37
あるクラスAが、別のクラスBのインスタンスへのポインタを シングルトンで取得する場合、クラスBのコンストラクタ、デストラクタ は発動するのでしょうか?その場合、発動タイミングはいつですか?
>>67 サンクスコ。2003の最新のですた。
でも1998のpdfは今はもうタダなんでつか?>61さんは
$20って書いてましたが。。。
>>66 それだけじゃだれにもわからない。
自分で使っている「シングルトン」の実装を調べれ。
質問おながいします。 会社の規約でグローバル関数をcallするときは、クラスのメンバと 見分けやすくするために :: を明記するように言われてます。 でc++コード中でよくcの標準関数をつかうのですが、getcharを ::getchar() と書いたらコンパイルが通りません。(その他の関数は知っている限り とおります) なんか問題があるのでしょうか? VC6でもVS7.1でも同様の結果ですた。
>>70 C++なら<cstdio>をインクルードしてstd::getcharが正解。
でも、VC6では通らないかもしれない。
>>71 レスどうもです。
#include <cstdio> はできないんでつ。というかなぜか
全部のコードがstdio.hなんでつ。(単に古いからだと思うんでつが)
先輩はgetchar()でええやないかって言うんですけど、なんで
::が付けられないのか気になって仕方ないもんで。
>>70 ごめんVCのgetcharはマクロでも定義されてるみたい。
#include <cstdio>
#ifdef getchar
#undef getchar
#endif
これでstd::getcharでいけるようになる。
どっちがいいかは微妙。
規格はこのマクロ定義を許しているんだろうか?
gccのcstdioでstdio.hのマクロは全部#undefされてた。 やっぱ規格としては、std::getcharで使えないとダメなんだろうな。
>>71 調べててレス遅れました。
「VCのgetcharはマクロでも定義されてるみたい」でハッとして
VCのソース見たら
#define getchar() getc(stdin)
とされてて、これはまあいいのですが、次に
#define getc(_stream) (--(_stream)->_cnt >= 0 ? 0xff & *(_stream)->_ptr++ : _filbuf(_stream))
とマクロ展開されてました。
これでは ::getchar() が通るわけないでつ。スッキリしますた(´・∀・`)
どうもありがとう。。。 それにしてもvcってへんな実装でつ。
getcはマクロで実装してもよかったような希ガス。
>>77 たった今DLしますた。なんかわからんけど
ディスカウントが効いて$13.5ですた。
サンクスコですた(・∀・)!!
runtime_errorクラスの派生クラスでrange_errorっていうのが 標準でありますよね。内部演算の範囲エラーということのようですが これってどういうことでしょうか?オーバーフローやアンダーフローは わかるのですが。
vector<int> v(10); v[15]=5; bitset<16> bs; bs[20]=true;
81 :
デフォルトの名無しさん :04/06/05 19:45
>>54 52のような質問をする必要がなくなるという事例を現に目撃しながら、何が聞きたいんだ?
>>80 それっていわゆるout_of_rangeという例外クラスにあたるんじゃ
ないですかね・・。つまりロジックで回避できるものという。
runtime_errorというのは、プログラムのスコープの外で単純に回避
できないイベントを通知するのだそうです。
派生クラスは
range_error
overflow_error
underflow_error
このrange_errorというのがよくわからないんです。
>>82 overflow, underflow と並んでるってことは、その手の「範囲外」を通知するのに
使うことを想定してるんじゃないの?
有効な値の範囲が連続なら underflow, overflow だけで表現できるけど、
とびとびだったりすると、どっちとも言えんよね。
84 :
デフォルトの名無しさん :04/06/05 20:37
85 :
デフォルトの名無しさん :04/06/05 20:53
>>84 vtblは関係ないよ
いいから、言うとおりの順に紙に図かいてみろ
・Object型のオブジェクト1個(仮にaと名づける)
・aへのポインタ1個(仮にpaと名づける)
・paへのポインタ1個(仮にppaと名づける)
・Test型オブジェクト1個(仮にbと名づけ、aがbの部分オブジェクトになるように)
・bへのポインタ1個(仮にpbと名づける)
・pbへのポインタ1個(仮にppbと名づける)
おまいさんがやろうとしていることは、
reinterpret_cast<Object**>(ppb)だ
>>84 Test **t=0;
Object **o=t;
これが出来ないから
>>85 指摘ありがとうございます。
ネットで調べたら
reinterpret_castは単なる型変更であり、たとえ派生関係があったとしてもポインタのアドレス自体はキャスト前と変わりません。
その意味でreinterpret_castは非常に危険なキャストといえるでしょう。
とありました。正直Castについて、完全に理解してないもので、とりあえずCastの部分が私が間違っていたということでしか、まだ理解できてません
が、返事が遅くなるといけないから、一応レスを書きました。Castについて勉強して、もう一度検討してみたいと思います。
せっかくレスを頂いたのに、まだ理解できなくてすいません。
>>86 なるほど、わたしのしてたことは、それに似たことだったのですね、上で書いたように、もう一度じっくり検討してみます。
どこに着目すればよいかわかりましたので、大変助かりました。ありがとうございます
>>80 vectorは確かoperator[]で範囲外アクセスした場合、未定義だったと思う。
vector<int> v(10);
v[15]=5;
v.at(15);
でatの方は例外を投げたと思うけど。
bitsetの方は覚えてない。
>>88 std::bitsetも[]による範囲外アクセスは未定義のふるまい。
90 :
デフォルトの名無しさん :04/06/06 00:56
std::bitsetの要素は1bitですが、要素がN bitのものはありませんか?
93 :
デフォルトの名無しさん :04/06/06 10:59
Nの大きさに合わせてvectorを使ったりbitsetを使ったりする ラッパーを作ればよい
ちょっと質問なんですが、 #include <iostream> class A { public: int& test; A(int& a):test(a){}; }; int main(int argc, char *argv[]){ A *p; { int c = 1; p = new A(c); std::cout << p->test << std::endl; } std::cout << p->test << std::endl; return 0; } 2回目のp->testは安全ですか? 一応大丈夫みたいなんですが。
>>95 ポインタを返す関数の戻り値に、
その関数のローカル変数のポインタを使うようなもんだ
>>96 >>97 やっぱそうですか。
じゃあ int& を const int& にした場合どうなりますかね?
一時オブジェクトをconstリファレンスで受けると寿命が延びますよね。
その例として型がintなのはよろしくないかもしれませんが。
>一時オブジェクトをconstリファレンスで受けると寿命が延びますよね。 ソースきぼんぬ
コンストラクタ抜けた時点でデストラクタ呼ばれてるようですorz。 寿命が延びるといったのは受けた変数と同じ寿命になるという意味です。 直接受けた変数と同じになるだけみたいですね。考えてみれば当りまえかもしれませんが。
>>95 コードブロックの最後にデストラクトするのは、実装依存ではなくて
仕様。それにコンパイラは、ブロック外でアクセスされるのを
検知して、寿命を延ばすことはしない。(警告を出すことはありうる
だろうけど)
ARMに書かれているのは、テンポラリがconst参照されている場合
、その参照の寿命にしたがうということで、ここではcはテンポラリ
じゃないからね。
>>103 というか cのとこがテンポラリだったとしても直接受けるのはコンストラクタの引数なので
コンストラクタ抜けた時点でデストラクタ呼ばれるんですよね。
>コンストラクタ抜けた時点でデストラクタ呼ばれるんですよね。 { int c = 1; p = new A(c); std::cout << p->test << std::endl; } ← ここで呼ばれるんじゃね?
>>105 cのとこが一時オブジェクトだった場合、Aのコンストラクタが終了した時点で一時オブジェクトのデストラクタが呼ばれます。
>>106 p = new A(C());
こんな事やってんじゃね?
>>95 == 104
>というか cのとこがテンポラリだったとしても直接受けるのはコンストラクタの引数なので
>コンストラクタ抜けた時点でデストラクタ呼ばれるんですよね。
レス遅れてすまそ。そうだった。漏れも勘違いしてた。
そのテンポラリで初期化されたのなら、参照変数に束縛(?)されるだろうけど、
変数として渡されたのなら束縛できないね。(コンパイル時に値(テンポラリ)が
確定しないから、C++が寿命管理できない)
で、誰にも束縛されてないから、すぐに(この例だとコンストラクタ抜けたあと)
削除されちゃうね。束縛されてれば最大テンポラリの作成されたスコープいっぱい
生きられるみたいだけど。
>>110 A(int& a):test(a){}; を
A(int& a):test(int(a)){};
みたくしたらテンポラリで初期化するから生き続けるかなあと思ったけど
(もちろんこんなことするくらいなら値渡しすればいいんだけど)
コンストラクタ抜けたらやっぱり死にました。そういうもんなんですかね。
ところで参照のメンバを使う時ってどんなときですか?
>>111 > ところで参照のメンバを使う時ってどんなときですか?
生成順序、破棄順序に明確な親子関係がある時かな。
被参照クラスは参照するクラスのコンストラクタで渡さなきゃいけないし、
参照するクラスのデストラクタが呼ばれる前に非参照クラスが破棄されると
普通は困るから。
ところでみなさん、C++ のソースファイルの拡張子は、何にしてますか? .C .cpp .cc
cxx
.cpp
VC++だと拡張子つけないと勝手にcppだからcpp。 つか、クラスの新規作成で勝手にファイル生成させてるが。 Linux上でgccに食わせるのはなんとなくccだったりする。
zshでは、cpp は、C++ の拡張子としては、扱われてなかった。
え、設定変更できないの?
zstyle を使えば、変更できます。
ちょいと本読んでたら気になる表現があったのですが デフォルトコンストラクタを明示的に呼び出す・・・ というのは、どういうことでしょうか?明示的じゃない 呼び出しっていうのもあるんですか? たとえば class A{ ... }; A c; とか A c(); とかって違うのでしょうか?
int i; と int i(); は違う。
123 :
デフォルトの名無しさん :04/06/06 20:10
>>121 もしかして「デストラクタの明示的な呼び出し」の間違いか?
全然関係ないが
A c; はオブジェクトの定義
A c(); は関数の宣言
たぶん、explicit の話だろう。
>>114 .EXTENSIONOFC++SOURCEFILE
あ、 引数なしのコンストラクタ呼び出しって A c(); という具合じゃだめなんですか・・・関数宣言になるんですね。 じゃあ A c; または A c = A(); でデフォルトコンストラクタ呼び出しってことですかね。 いずれにせよ明示的って意味がわかりませんね・・・。
読み間違いの予感
だから、「explicit+コンストラクタ」でぐぐってこい
>>128 デフォルトコンストラクタにexplicitもクソもあるか。
明示かどうかで挙動が変わるのは組み込み型のデフォルトコンストラクタ。
その明示的と明示的じゃないというのは、表現方法はどう違うのでしょうか?
131 :
デフォルトの名無しさん :04/06/06 22:59
>>130 例えば、デストラクタなら
{
hage stroustrup;
} // 暗黙の呼び出し
this->stroustrup::~stsoustrup(); //明示的な呼び出し
132 :
デフォルトの名無しさん :04/06/06 23:08
const hage& hage::operator = (const hage& BullShit) { this->hage::~hage(); this->hage::hage(BullShit); return *this; }
s/stsoustrup/stroustrup/ s/stroustrup/hage/ 吊ってきます
135 :
デフォルトの名無しさん :04/06/07 01:55
A.h (class Aを定義) A.cpp (実装を定義) とやって、A.cppで、static A gA; などとグローバルインスタンスとして A を定義し、それをsingletonとして ポインタを返すメンバ関数をAに用意しておきます。 main.cppの方でそれを呼んで class Aのsingletonを使ってメンバ関数 をコールするというような使い方をする場合、 class Aのコンストラクタ、デストラクタはいつ呼ばれるのでしょうか? 多分、static A gA; がメモリー上に実際に生成される時だと思うんですが それっていつなんでしょうか?
>>135 色々自分でいじくってたら自己解決しました。
すんまそん。
>>133 吊るより
9階からああ飛び降りろ。
間違っても芝生のないところでやれ。
できるなら30階以上のところでやれ。
確実に死ねる
141 :
デフォルトの名無しさん :04/06/07 11:45
C++ では類の実体を函数の返値にできるよね?
C++には自信があったのですが、141の日本語が理解できない漏れは、9Fからフェンスめがけて飛び降りるべきでしょうか。
「クラスのインスタンスを関数の返値にできるか?」 ってことか。それならイエスだが。 しかし、なんでわざわざ回りくどい聞き方するかね。
144 :
デフォルトの名無しさん :04/06/07 13:05
カタガナ語???
>>144 そんなにオナニー好きなのに
よりよいオナり方を人に訊くのか…
入門書買え、読め、と叩かれそうなぐらい初歩の初歩の質問を、 さも高度な質問のフリをするためには効果があるわけだな。 しかし、141がDQNであることは、はっきりした。
必死な低学歴が大量なスレですね
149 :
デフォルトの名無しさん :04/06/07 17:51
>>142 カッターで頚動脈切ってもらった上で15Fぐらいからダイブしたほうがいいぞ。
今は9Fからダイブするのがナウイ
今死ぬなら60F。
C++はCに比べて遅いというのは良く聞く話ですが、具体的にどれくらいですか? なんとなく↓くらいかと思う C>>C++>>>>>>>>>>>>>>>>Java
具体的に聞きたいならどういったコードの実行性能かを具体的に書け
>>153 科学計算用途です。行列演算とか、フーリエ変換とかが入った計算。
C++の既存の科学計算ライブラリ >>>>>>>>>>>>> 152の書いたCの科学計算コード
>>155 ライブラリ呼び出しだけで書けると思ってるの?ヴァカ?
>>152 処理系もライブラリもコードも示さないで比較もくそもないと思う。
そして処理系もライブラリもコードも示せるなら自分で計測すれ。
純粋な数値計算でC/C++の差が出ることってある? 標準ライブラリやメソッドコールの差はあるにしても。
>>158 数値計算はライブラリの質が大きいが、シミュレーションとか、
もっと一般的に言って物理エンジンなんかはどうなのさ?
>>152 全く聞かないけど?
実際は、C≒C++>>>>Java ぐらいじゃないか?
CとC++とJavaで同じ処理を試すということは、
クラスライブラリなどを一切使わないってことだよね?
> C≒C++>>>>Java で、良いんじゃないかな?
>>158 あるよ。
expression template などを使わず。単純に見易さとか書きやすさだけを求めると
遅くなるよ。もっともC++ではそういう書き方もできるという意味で、C流に書けば
いいだけなんだけどね。
#expression templateも+,-,*などの単純計算ならなんとかなっても逆行列なんかには
#無力だけど。
継承レベルを出来るだけ浅くして、オブジェクトの生成も出来るだけしないようにすれば遅くならないよね。 って、Cで書けってことか?(w
164 :
デフォルトの名無しさん :04/06/08 22:53
>>164 162 じゃないけどMATRIX operator+(MATRIX const&, MATRIX const&) とか。
何も考えずに書くと、戻り値で値のコピーが発生して遅くなりがち。
>>163 君にはきっと C のほうが向いていると思う。
結局書き方の問題であって、生成されるオブジェクトの 最高実行速度という意味では厳密に C++ == C ってことでは? それに加えて、C++より広範囲の抽象化をサポートしていわけで。 (仮想関数ならそれなりの実行時コストをはらって、また、templateなら 実行時コスト無しで)
>>165 その計算はCだろうが戻り値のコピーは避けられないと思うが?
戻り値最適化を前提にしちゃいかんのはわかるが
Cで書けば同等の役割を持った上で高速に動作するコードを示してほしい
つーか expression template の話してるところで
「何も考えずに書くと」のケースの話されても一体何と何を比べてるんだって感じなんだけど
>>164 一番速度差が出やすいと言われるのはこんな場合。C++だと、
Matrix a,b,c,d,e;
for(int i = 0; i < takusan; i++){
a = b*c+d-e;
}
ってな計算。
なーんにも考えず二項計算だけ定義すると、
b*cの結果、それと+dの結果、
-eの結果、それぞれを確保、開放
繰り返してたらそりゃ遅くなるでしょ。
C流に書けば、a.b,c,d,e,tmp,tmp2,tmp3は適当に定義してあって、
関数にはポインタで渡すとして
tmp =(XXX &)malloc(sizeof(datasize) * matrixsize);
tmp2 =(XXX &)malloc(sizeof(datasize) * matrixsize);
tmp3 =(XXX &)malloc(sizeof(datasize) * matrixsize);
for( i = 0; i < takusan; i++ ){
mul(b,c,tmp);
add(tmp,d,tmp2);
sub(tmp2,e,tmp3)
}
で作業域は一回だけ確保しとけばいいってこと。
でも、計算式そのまま書けば計算できるC++流の関数と
C流の関数両方用意しとけばいいからC++が遅いってことにはならないよ。
Cだと見にくい書き方しかできないけど。
あと、式テンプレートは結果の作業域は用意しなくてもいいんだが、
結局計算式そのものをどっかに格納しとかなきゃいけなかったりする。
(XXX *) だった、しばらく書いてなかったもんでスマソ
C++は速度を犠牲にして保守性を向上させているというのは都市伝説の類ですか?
>>169 言いたいことは分かるんだけれども
その例はC++でも
結果を格納するためのオブジェクトと op= の形式の演算子使うだけで
C流の関数なんて使わなくともそこそこ可読性を保ったままパフォーマンスを同等にまで上げられる。
しかもこれ、割とよく知られている最適化テクニックなんであまり適切な例ではないような。
速度求めるならSSE2命令使ってコーディングしてるatlas + fortranが速い。 SSE2命令有効にしてコンパイルしてもこれほど速くならないと思う。 C/C++からコールするにしても行/列アクセス順序入れ替えるのは面倒だし、 オーバーヘッドは必ず発生するしね。
>>173 Intel系ならそうですね。WSやマックは切り捨てですか?
atlasが速いのは、出来るだけキャッシュに入るように工夫してるのが大きいと思うのですが…。
InterlのMKLなんかはP4のパイプラインの分岐予測を乱さないように最適化されているみたいですし。
そこまで行ったら、言語の問題じゃないような気がする。
175 :
デフォルトの名無しさん :04/06/08 23:55
ちと気になったので質問します。 ファイル名を格納するchar配列があります。 この配列は幾つファイルが有るかわからないので動的に増やせるようにしたいです。 そこで今は以下のようにしています。 int n = 10; struct FILENAME{ char lpsz[MAX_PATH]; }; FILENAME* files = new FILENAME[n]; が、これってわざわざ構造体なんか定義しなくても出来るようにならないでしょうか。 無理とは解ってますが以下とかじゃ駄目ですし。 char* files[MAX_PATH]; files = new char*[n];
fortranの場合並列処理に分割し易いとかそういった理由で科学計算の 分野ではC/C++より早いって話しだよね? 逆にfortranってC/C++みたいな自由度はないのでは? ただ、CとC++の高速度ソフトウエアの記述能力といった意味では全く 同一だと思う。
>>175 std::stringとかstd::vector<char>とか使え。C++なんだし。
>>175 char** filenames = (char**)malloc(sizeof(char*)*n);
じゃだめなのかね。
>>175 つ[std::vector<std::string>]
しまった、C++スレでした。鬱山車脳。
というか構造体を定義することと動的配列の実装に何ら関連性がないのだが。 型名をどう記述してよいかわからないだけなら typedef で十分だし。 実際は「動的配列どうやって作れるの?」ってだけの話なのか?
char (*files)[MAX_PATH]; files = new char[n][MAX_PATH];
>結果を格納するためのオブジェクトと op= の形式の演算子使うだけで >C流の関数なんて使わなくともそこそこ可読性を保ったままパフォーマンスを同等にまで上げられる。 >しかもこれ、割とよく知られている最適化テクニックなんであまり適切な例ではないような。 そりゃ、技を駆使すればC++も速くなるよ。 でも、多大なる努力を駆使して得られる処理速度は、誰でもすぐに書けるCの処理速度に どれだけ漸近させられるかってだけ。 その努力が数値計算ユーザにどれだけ支持されるかってこと。
> 誰でもすぐに書ける うーん、ダウト
>>183 何言ってんのかわかんない。
void add(MATRIX&, const MATRIX&, const MATRIX&);
みたいなC式のスタイルはC++でもできる。
C++式のスタイルは使いかたによってはパフォーマンスが悪い、それだけだろ。
>>174 >Intel系ならそうですね。WSやマックは切り捨てですか?
Pen4 に atlas 使って遅い用途ならWSも糞マックも役にたたんだろうからどうぞ捨ててくれ。
故意にC++を難しくみせようとしているヤツがいるな。
op= と op じゃ実装も記述の手間もろくすっぽ変わらん。
問題なのは可読性が下がることだけ。
>>169 が言ってるのは、
a = sub(add(mul(b,c), d), e);
より mul_assign(b,c, tmp); ...(以下略) とする方が早いという以上の何者でもない。
それをC++の演算子オーバーロードに置き換えれば op と op= の違いになる、というだけ。
可読性と保守性と速度を全て満たした言語は無いのか?
>op= の形式の演算子使うだけで ふーん。Matrix計算の場合+=.-=は確かに使えるね。 *=が使えると思ってる時点でオバカさんだな。 どうやったら使えるか解説してくれないか?
おおっと、定数には使えるよ A *= 3.0; とか A /= 5.0; とかね。
浅はかな
>>172 ,
>>187 は、
A *= Bの計算を作業域使わずダイレクトにできると思ってるんだろうね。
おめでたいこった。
>>190 話のポイントのつかめんやつだな。
CとC++でどこが違うかって言ってるんだ。
>>166 でも一時オブジェクトは確保してるだろ。
どこで一時オブジェクトがいらないなんて話になったんだ?
#さらに言うと *= の場合、
中途で確保する一時領域は行単位で済むから * よりも
オーバーヘッドは小さくできるぞ。
>>191 Cでは作業域使わずダイレクトにできるのか?
出来ないよな。なら特に今回の話に関係無いよな。
で?
>>192 >>193 作業領域を中で確保して値渡しで返す(もしくはswapする)のと、
外から作業用兼結果用の領域をもらうのとは結構違うと思うよ。
>>192 おつむの悪い僕ちゃんだな。
いいかい。
op= を遣う理由で一時作業領域を省略できる以外になにかあるのかい?
Matrixの*=の場合はそうならないから指摘してるんだよ。
##さらに言うと *= の場合、
# 中途で確保する一時領域は行単位で済むから * よりも
# オーバーヘッドは小さくできるぞ。
ハイハイ。がんばれよ。頭だけじゃなく往生際も悪いようだ。
void mul(Matrix *ret,const Matrix *a,const Matrix *b); Cで書くとこういう関数になると思うが この時、retとaのポインタが指す領域が別々とは限らないため、 Matrix &operator *=(const Matrix &a); と関数内部は同一になると思うが、そういうことを言ってるのではないの?
>>195 いいでしょう。
*= については、a *= b ではさらに新たな一時オブジェクトを作る tmp2 = a * b; に対して改善が見込めないという部分は認めよう。
でも、Cでこの書き方より速くできるかという部分については納得する意見をもらってないよね。
>>196 だーかーらー ret,a,bが全部違った時は作業領域いらないでしょ。
その恩恵はC++のoperatorじゃあずかれないでしょ。
>>197 さっきからでてる三項の関数使えばいいじゃん。
C++だからってoperatorにこだわることないんだよ。
実際に数値計算のライブラリも三項引数の関数用意してるよ。
>>198 いや、全部違うかどうかは関数内部でわからないでしょ?
まさかポインタが違うかどうかifでチェックするの?なわけないよね?
え? ifでチェックすればいいじゃん。 っていうかこの問題、式テンプレート使うとなるとまた変わってくるのかも。
速度云々とかいいながら条件分岐なんか使う気なのか。
通りすがりの横レスだけど
確かにC++使ってるとoperatorとかtemplate使いたくなるよね。
そんな事やってる間にチューンを忘れるとか疎かになりがち。
そう言いつつET使ってキャッシュも意識して頑張るんだけど。
>>199 restrictって言おうとしたけどCだな。それに保証も出来んか。
ifチェックすんのかよ! パフォーマンスがどうたら言うてる割に現在のCPUでペナルティ大きいifチェックかぁ。 まぁ想定してるmatrixが俺と違うのかもね。 内部で動的にメモリ確保したりするようなヤツならifチェックくらい別にかまわないか。
>>197 結局、出力パラメータに対して
operator の戻り値コピーの部分(最適化してくれないとして)がネックになるって話なのね。
>>200 expression template はないって前提でしょ。
一応、それならパフォーマンスをある程度保ったまま
はるかに直感的に式書けるんだからまあ文句は出ないと思う。
もちろん式格納領域はいるけど今問題の一時オブジェクトのオーバーヘッドはなくなるわけだし
式テンプレート使ってメリットあるのははせいぜい乗算ぐらいまででしょ。 blitzもublasも逆行列なんかを使うのが悪いと言うようなスタンスだし。 実際、逆行列に使ったところで逆に覚えとかなきゃいけない要素が多くなると思う。
>>201 >>203 バカかおまえらは?
気になるならチェックしないバージョンつくって使いわければいいだろ。
operatorにこだわるならそういうことすらできないんだよ。
>>206 お前にバカっていわれたくないなぁ。
つか、お前のレスは人格攻撃、見下しばかりでつまらん。
そんなヤツとは議論しても実りがない。お前パスな。
どうぞ、勝利宣言でもなんでもしてくださいな。
>>204 式テンプレート一時期凝った時があるが
4x4のMatrix値返しした時のほうが早くなって愕然とした記憶がある。
あまりに凝ると最適化が効かなくなるんかいな??もしくは単にミスってたかな。
>>205 そこはそれでかまわないと思うんだけど、、、
まあ俺が実際に使うのは乗算と加算ばっかりだから要望ないだけかも。
数値計算屋さん(なの?)としてはどういう風にしてほしいものなのかな
>>196 ちょっとまってチェックするっていっても関数の頭でポインタのチェックするだけだろ?
ループ内部で条件判断するわけじゃないの無視できるでしょ?
ふつう行列演算C++でかくなら演算できるかどうかの行、列数のチェックはするだろうし。
一般にoperator=でもソースとデスティネーションの同一性のチェックはふつーするでしょ?
#行き着く先のET使っても、保守性が向上するとは言いがたいと思うのだが。
#blitz 見やすいか?使いやすいか?
>>207 あ、ごめん。ちなみに俺は194=198=200=206で189とは違うから。
勝利宣言はしますけど。
まともな行列ライブラリなら行列の乗算は式テンプレート使うんだろうね。
LiDIAってライブラリには3引数の関数あったけど。
211 :
デフォルトの名無しさん :04/06/09 02:38
こうしてみると、人は説得力のあることを言えないときに その代替として人を馬鹿にするんだってのがよくわかるね。
あ、185も僕でした。
>>211 つまんない揚げ足とられたから腹立っただけだよ。
213 :
デフォルトの名無しさん :04/06/09 03:01
いや、罵倒と質問ばっかで、肝心の自論については
雰囲気しか示していない
>>189 =
>>195 が主な対象。
最後に、
>>204 > operator の戻り値コピーの部分(最適化してくれないとして)がネックになるって話なのね。
最適化なんてしようがないと思う。
ホント、カッターで刺した小学生の気持ちがよくわかる。 刺した上で9Fから突き落としたくなったよ。
>>210 3引数の関数とは例えば
A * B * C
を計算するような関数かな?
でもこれを計算する場合でもtmp領域は必要だよ。
数学上、2項演算しか定義されてないから(それで十分だから)
2項の計算結果をどっかに保存しないと次項の演算に移れない。
ただし、3項以上の演算を定義することでtmp領域の確保回数を
減ずることはできる。
実際、newmatなんかは行列計算の開始宣言、終了宣言して2項毎の
tmp確保を避けてたと思う(随分前に使ってたので記憶が定かでない)。
>>181 そんなとこです。
>>182 なるほど、()で括ってやれば良かったんですね。
どもでした。
220 :
デフォルトの名無しさん :04/06/09 11:46
結局 C だとどんな魔法を使って C++ より高速に算術演算を行えるのか、誰か分かった? キャッシュラインのサイズに応じたベクトル計算の自動分割とかしてくれるのかな・・・
OOP機能を駆使すると遅くなるので、Cの機能しか使いません。
>>221 こんな感じ?
struct Matrix matrix_mul(struct Matrix a, struct Matrix b) { ... }
C++はinline使いまくれるからCより速い
>>223 inline にすれば100%早くなるってもんでもない。
無駄にプログラムサイズが大きくなると、キャッシュミスが多くなるし。
inline があれば、高速化のために手動で関数を展開しちゃうという
愚行に走らなくて済むのは確かだけど。
あと、C言語でもコンパイラによっては inline 展開するようになってるし。
227 :
デフォルトの名無しさん :04/06/09 15:14
do{ cout << "終了しますか? Yes = y, No = n" << endl; }while(cin.get() != 'y'); このコードを実行して、「n」を入力すると 「終了しますか? Yes = y, No = n」の部分が二回表示されてしまいます。。 キチンと表示させるには、どうしたら良いのでしょうか?
> キチンと表示 ????
cout << "終了しますか? Yes = y, No = n" << endl; do{ }while(cin.get() != 'y');
do { cout << "終了しますか? Yes = y, No = n" << endl; } while (cin.get() != 'y' && cin.get() != '\n');
ごめん わすれて
これでどうだ? do { cout << "終了しますか? Yes = y, No = n " << endl; } while (cin.get() != 'y' && cin.get() == '\n');
>>230 ああ、要するにコレ、バッファに「\n」が溜まってたって事なんですね…
なるほど、良く分かりました。
>226 >222は皮肉じゃないの?
きっとこうなってるんだよ。 struct Matrix { struct Matrix_t *m; };
すいません.蒸し返すようで悪いですが少しだけ.
>>169 >結局計算式そのものをどっかに格納しとかなきゃいけなかったりする。
そのような式オブジェクトは理想的な最適化の結果
コードから排除されるだろうというのがET支持者の一応の主張ではあるんですが・・・.
>>172 三項以上の演算,例えば行列におけるa + b + cなどにおいては
op=の形式では抽象化によるペナルティを喰らう可能性は残ると思います.
>>195 以下のようなコード(中途半端な擬似コードで申し訳ない)だと192さんの指摘するように,
一時オブジェクトは1行分だけで済むように思えるのですが違うのでしょうか?
Matrix &Matrix::operator*=(Matrix const &rhs)
{
assert(*thisの列数==rhsの行数 && rhsの行数==rhsの列数);
Row tmp;
for(size_t i = 0; i < *thisの行数; ++i){
tmp = *thisのi行;
for(size_t j = 0; j < *thisの列数; ++j){
*this(i, j) = 0;
for(size_t k = 0; k < *thisの列数; ++k){
*this(i, j) += tmp(k) * rhs(k, j);
}
}
}
return *this;
}
>>200 式テンプレートでは左辺と右辺の依存関係の問題は
代入メソッドの選択に一任される形になるかと思います.
通常の代入operator=では一時オブジェクトに結果を保存してから代入(swap)する形を取り,
ユーザが代入による依存関係の問題が発生しないことを保証できる場合のために
式オブジェクトから直接代入するための関数を別途用意する,とか.
>>205 通常,線形代数の数値計算では逆行列を陽に求めるのは最終手段(通常はご法度)なので
blitzやublasのスタンスは適切だと思います.
>>239 「俺は俺のやり方がなぜうまくいかなかったかが知りてーんだ。
そんな安易な解決策はとっくに思いついてんだよゴミクズどもが!」
ってちゃんと言わないと駄目だよ。
>>237 rhsが正方行列じゃなかったら困らない?
あと、rhsってなんの略?
>>241 なんで正方行列である必要があると思うの?
rhs = right hand side
>>242 列数が変っちゃうから。
なるほど。right(left) hand valueしか知らなかった。
返事がないな。
>>243 237のままだと正方行列である必要があります.
なので,237のコード中のassertで一応そのことを表明しているつもりです.
>>245 ほんとだ。よく見てなかった。でもそうじゃない場合は困るよね。
Matrixの乗算っていうのはたまたま出た例で、op=で一時オブジェクトが必要なときは
C式のスタイルよりパフォーマンスが悪くなるっていうのがもともとの議論。
大きな行列の場合にはデータ本体はシェアしておいて copy on write とか使うようにするのはどうかな・・・ オーバーヘッドもたいしたことないと思うんだけど。
>通常,線形代数の数値計算では逆行列を陽に求めるのは最終手段(通常はご法度)なので >blitzやublasのスタンスは適切だと思います. 逆行列のETなんかはやろうとしてもできない。もしくはパフォーマンスの向上、 リソースの節約に寄与しないからこそ提供できない。 できないってのとやらないのは違う。 技術的にET実装は非常に難しいことをはっきり言うべき。難しいので提供できませんでしたと。 それを数値演算で逆行列を使うのはおかしいなどというのはイソップの狐と同じ。
249 :
デフォルトの名無しさん :04/06/09 23:07
逆行列の計算はもとのマトリックスを破壊してもいいなら、 作業領域はほとんどいらないし、逆行列のひとつの成分を計算するのに もとの行列のすべての成分が関係するから式テンプレートを使うメリット はまったくないな。 式テンプレートを使わず逆行列のメソッドを提供すればいいのになんで blitz++はやらないのかね? それを使うかどうかはユーザが決めればいいんだがな。
つまりは行列に限らず、巨大なデータを何段階にも扱う計算はC++は苦手と考えてよろしいか?
>>250 C++ が苦手というか、operator overload で「数式っぽい見た目」でプログラミング
するのと相性悪いんだと思うよ。
これが 4x4 行列と 4 次ベクトル限定で、ベクトル演算用のレジスタ積んでる
プロセッサだと話が変わってくるけど。演算子オーバーロードを使う場合でも、
o 演算子に対応する関数をインライン展開
o 行列やベクトルの要素がコンパイラ最適化によってうまくレジスタに乗る
と、陽に関数呼び出しを行う C スタイルの書き方より早くなることもある。
>>250 C++でもCのような書き方をするなら別に苦手ではない。
それでも効率より見やすさや安全性を考えてクラス化してるんだと思う。
Adobeのソフトや、Windowsなんかは全部C++使ってるんでしょうか? 速度重視のコアの部分はCで書いてて、外側の部分はC++のような気がするんですが…。 どうなんでしょう?
254 :
デフォルトの名無しさん :04/06/10 00:02
最近C++を始めたばかりです。 ・ある物の状態を監視 ・その状態を表示 といった単純な事がやりたいのですが、その状態を表すクラスを↓のように定義して class Status{ public: Status() : dat(0){}; virtual ~Status(){}; void set(int i) { dat=i; } int is() { return(dat); } private: int dat; }; メイン関数では↓のように作りました。 Status st; // 監視側 if(ある物の状態==true){ st.set(1); } // 表示側 if(st.is()==1){ 表示; } が、これだと表示側からもdat.set()が呼べてしまうので危険です。 現状ではfriendを使ってやってるのすが、すっきりしません。 こういう場合、普通は(オブジェクト指向的に?)どのように作るものなのでしょうか?
4X4ぐらいの小さい配列だとだとpure C に比べてETのオーバーヘッドが目立つだけだよ。 もちろん何も考えず作業領域をoperator毎に作るようなコードに対しては アドバンテージがあるかもしれないけど。 大きな配列を持ってこないとETは逆効果
>>254 コメントを日本語で書くのはやめることだな
>>256 言わんとしているのは
「監視」を英語に直して+パターン
ということかな
s/監視/監視側/
説明用のコメントだろ。アフォだね。
Observer Pattern?
>>259 じゃあ、おまえは「ひまわり」でも使ってろ(プ
さぁ盛り上がってまいりますか
>>246 237は行列同士の*=で1行分しか一時領域が要らないのではないか,
という疑問を単に投げただけのもので,議論の本筋からそれたものでした.すいません.
>でもそうじゃない場合は困るよね。
はい困ります.ただ,困るのはCでもC++でも同じことだと思います.
>op=で一時オブジェクトが必要なときはC式のスタイルよりパフォーマンスが悪くなる
というのは,上の議論において未だ論拠が指摘されていないように見えます.
自分としても,Cスタイルにおけるmultiply_assign(Matrix &a, Matrix const &b)という記述と
operator+=の記述との間にパフォーマンスの差を生じさせるものがあるとは思えないです.
>>248 いえ,私が指摘したいのは,
「ETを実装{しない/できない} -> 数値演算で逆行列を使うのはおかしい」
ではないです.
数値演算で逆行列を使うことは悪いとするスタンスは適切ではないか,ということだけです.
ただ,これは数値計算の一般論の指摘でこのスレで書くべきことではなかったです.すいません.
>>249 >式テンプレートを使わず逆行列のメソッドを提供すればいいのになんでblitz++はやらないのかね?
以下は私の中途半端な知識による考えです.適当に流してください.
通常,行列の逆行列が真に必要となる場面は非常に限られ,ほとんどの場合,
逆行列を陽に計算するよりも適切なアルゴリズムを選択する方が
計算量・精度双方の観点から圧倒的に有利になります.
例えば,行列の逆行列と{ベクトル/行列}との乗算では直接逆行列を計算することは論外で,
通常はLU分解法で行列を三角化してから計算します.
なので,あえて逆行列を陽に求めるメソッドを提供せず,逆行列を表す式オブジェクトとの演算を
適切なアルゴリズムにdispatchしているのではないかと愚考します.あくまで私見です.
265 :
デフォルトの名無しさん :04/06/10 00:49
みなさんはbad_alloc例外ってどう扱ってますか? 最近VC6.0から7.1に移行してとまどってる厨房です。 いままでは、 char* buf = new char [256]; if (buf) { delete [ ] buf; } みたいにしてたのを、 (auto_ptr, shared_ptrを使わないとすると) try { char* buf = new char [256]; delete [ ] buf; } catch (bad_alloc&) { delete [ ] buf; ← 例外の場合も開放しなきゃだめ? } にすればいいんでしょうか。 nothrowを指定するっていう方法もあるけど、 なんかDEBUG_NEWがあるとコンパイルエラーになるし...
>>264 >例えば,行列の逆行列と{ベクトル/行列}との乗算では直接逆行列を計算することは論外で,
>通常はLU分解法で行列を三角化してから計算します.
LU分解は大規模疎行列には使わない。逆行列を陽に求めないというのは同意。
>>266 LU分解は密行列にしか使いませんね.舌足らずでした.すいません.
>>265 > みなさんはbad_alloc例外ってどう扱ってますか?
即興プログラムなら放置してabort()逝き。
まともなプログラムなら適切にcatchを配備。
> delete [ ] buf; ← 例外の場合も開放しなきゃだめ?
まずは、コンパイル通してから出直せ。
>>264 >はい困ります.ただ,困るのはCでもC++でも同じことだと思います.
>というのは,上の議論において未だ論拠が指摘されていないように見えます.
>自分としても,Cスタイルにおけるmultiply_assign(Matrix &a, Matrix const &b)という記述と
>operator+=の記述との間にパフォーマンスの差を生じさせるものがあるとは思えないです.
過去ログちゃんと読めよ。昨日さんざん話したっていうのに。
A *= B の場合、一行分の作業領域もしくは行列1個分の作業領域とコンストラクタ、swapの呼び出しが必要。
C = A * B の場合、行列一個分の作業領域とコンストラクタ、コピーコンストラクタの呼び出しが必要(RVOが使えなければそれ以上)。
multiply(Matrix& C, const Matrix& A, const Matrix& B) を使った場合、
&C == &A の場合、A *= Bと一緒、
&C == &B の場合、一列分の作業領域もしくは行列1個分の作業領域とコンストラクタ、swapの呼び出しが必要。
&C != &A && &C != &B の場合、領域もコンストラクタもswapもいらない。
三番目のパターンはoperatorでは実現できない。受ける変数のために行列一個分の作業領域とコンストラクタが必要でも、
コピーコンストラクタ分は得する。あと変数を使い回せるという利点もある。
Matrix A = ...;
Matrix B = ...;
Matrix C = ...;
Matrix D = ...;
Matrix E;
//E = A * B * C * D;
multiply(E, A, B);
multiply(A, E, C);
multiply(E, A, D);
>>265 VCに限定していいなら__try~__finallyを使う。
ちょっとしたものを書くときにクラス化しなくていいのは便利なんだけどな。
標準にして欲しい。
>>264 議論を理解してないようだけど、
multiply_assign(Matrix &a, Matrix const &b)とoperator+=を比較してるんじゃないよ。
>>187 参照。
スマン。265の回答にはなってない。
>>271 自分の理解が浅く,議論を蒸し返しただけでした.申し訳ないです.
finally使うんじゃもうC#つかった方がいいんじゃないの?
>>264 >例えば,行列の逆行列と{ベクトル/行列}との乗算では直接逆行列を計算することは論外で,
論外かどうかは用途とか行列サイズによる。理論式上では多用する分野もある。現実問題にアプローチ
する前に理論検証したい場合だってある。
あるいは自分が作った疑似逆行列アルゴリズムと理論式どおりの逆行列アルゴリズム間で精度や速度がどれだけ違うか
比較したい場合もある。
うまくいかなかった場合、元の理論がわるいのか、誤差が利いてきてるのか切り分けたい場合だってある。
そんなもんはケースバイケース。論外とするのはサイズの大きいマトリックスで実行時間もかかるし、求めたところで
誤差が大きくなって使い物にならないって言う場合。
事実、数値計算電卓のMATLAB/Octaveでは用意はしてる。
除算は理論的にワンショット(最小システムクロック)で算出できないから用意しませんでした。というプロセッサより
用意したがそれなりに実行コストはかかります。というのがユーザとしてはありがたいと思う。
ただ、逆行列のET実際はほとんど不可能だ。
>>274 C#なんていうクソ遅い言語は問題外。ベンチマーク取ってもVC7.1の1/2以下
の速度しか出ない。
>>276 それをいうなら
見やすいC++のコードを書いたら同機能のCの1/4の速度になったことあるよ。
もっというと、Cだと遅すぎるのでasmでチューンしたら3倍速くなったことがあるよ。
全部Verilogで書き直して組み合わせロジックだけで実現できたので1クロックで
処理できるようになったことがあるよ。
必要に応じて開発手段を選択するのが設計。
>>257 Observer Patternを調べてみて、だいたいどのようなものかは
分かったのですが、実際に監視側と表示側のソースをちょっと
書いていただけないでしょうか?
初心者なもんでそういう設計自体の方法がよく分からなくって・・・
>>263 こちらもできればお願いします。
>>265 bad_allocはnew演算子内から投げられる
bufには値は代入されていない
解放する必要がある/ないの前に
どこを解放するつもり?
解放はできるけれど、解放した段階で未定義動作になります。
283 :
デフォルトの名無しさん :04/06/10 08:42
s/解放は/解放しようとすることは/
>>277 どうもよくわかんないんだけど、このレスで "C++" っていうとテンプレートや
オペレータの再定義等の C にない機能を使ったコードに限定されるの?
漏れはクラス一切無しのコードでも C++ で書くけど。
ネームスペースとか C99 風のいつでも出来る変数宣言とかありがたいし。
それで別に C より遅くなってる気もしないけど・・・
C 相当のコードで速度差がないのは自明なので議論の対象にならないだけ。
例えばg++, gccでC相当のコードのアセンブラが同一になるのは自明なの? この部分のコンパイラは同一のコード同一の人間が書いてる?
このケースで「当然同じような速度になるはず」と思えないようだった ら、コンピュータのプログラミングに対するセンスが欠如してると認識 したほうがいいよ。 ちなみに gcc と g++ だと、ソースコードがプログラミング言語非依存 の形式になった後は、まったく同じルーチンで最適化されてアセンブリ 出力される。VC++ の cl.exe の中身なんて知らんが、C と C++ でわざ わざ別の最適化なんてするとは思えないでしょ。
289 :
デフォルトの名無しさん :04/06/10 14:03
全く同じプログラミング言語非依存の形式になるかどうか。
290 :
デフォルトの名無しさん :04/06/10 16:26
227で質問した者ですけど、 cin >> data; した後、バッファに「\n」が残ったりしますけど クリアするには、「cin.get()」とか「cin.ignore()」しかないんですかね?
291 :
デフォルトの名無しさん :04/06/10 17:04
>>291 でも、象徴的に書ける「>>」が好きなんですよ。
「getline()」だと、Cと変わらないですし…
293 :
デフォルトの名無しさん :04/06/10 17:46
>>292 string使うから、それだけでも大きく違う。と、思う。
少なくとも、Cと変わらない、は偏見じゃないか?
>>293 Cと変わらないはちょっと言い過ぎでしたが…
それと、stringつかうというのはどういう事ですか?
本を持ってる人にしか分からない質問で申し訳ないのですが Exeptional C++ の34ページの >T::operator=()は、例外を投げた際に代入しようとしていたTオブジェクト >の値が変更されてないことを保証しなければならない。 の意味が分かりません。そんな必要は無いと思うんですけど。
296 :
デフォルトの名無しさん :04/06/10 19:18
>>294 char[]じゃなくstd::stringが使えるからって事でしょ。
改行残るのは、なんかflushとかしたらよかった気がする。
環境依存かもしれんしうろ覚えだから違うかもしれんけど。
297 :
デフォルトの名無しさん :04/06/10 19:39
120 名前:番組の途中ですが名無しです[] 投稿日:04/06/10 02:39 ID:DlgC++i0
>>116 「かわいい彼女」といっても三日で飽きるわけだが。
121 名前:番組の途中ですが名無しです[sage] 投稿日:04/06/10 02:40 ID:Qn1mrozU
>>120 3日で飽きても
なにもないより全然マシじゃないのこのC++野郎
あともう一つ。swapが例外を投げないことを強調していますが、 アトミックでありさえすれば例外は投げてもよいように思えます。 なんで例外投げちゃいけないんですか?
>>298 標準化委員会でそう決定したからです。理由は標準化委員会に問い合わせて下さい。
>>299 こちらに聞かれてもこまります。
禿げに聞いてください。
>>299 どういうことですか?
コンテナとかの swapも throw()宣言されてませんが。
>>295 ん~、科学的には説明できないけど、感覚として。
Cでも関数がエラーを返したのにポインタ経由で渡した引数を
ぐちゃぐちゃにされたらムカつくしな~。
sturct Nanka iremono;
iremono.sono1 = saisyokarahaitteitamono;
if(ERROR == NannkaChoudai(&iremono)) {
assert(iremono.sono1 == saisyokarahaitteitamono);
}
これでassert()に失敗したらムカつく。
それと同じようなものを感じる。
もしoperator=( )が例外を投げたのに中途半端にオブジェクトが
変わっていたらきっとムカつくな。
>>287 $gcc -dr hoge.c
$g++ -dr hoge.cc
とした時の出力はちょっと違うんだよねえ。
しかし最終的なアセンブラコードはほぼ同じ。どうしてでしょう。
わざわざCとC++で分けないでしょってのは概ね同意だけど、 CとC++は仕様量が格段に違うんだから それによって最適化しやすくなったり、 逆に不確定要素が増えて最適化しにくくなったり ってのはあると思うんだけど、なんで誰も指摘しないのかな。
>>304 例外に対処するためのコードが埋め込まれたりして?
スレの流れを折ってしまって申し訳ないですが、 vectorのN番目の要素を削除したいときって、 erase()を使うしかなくて、erase()の引数はイテレータしかないですよね。 そこでこんな↓関数を作ってN番目の要素を指すイテレータを取得しようとしたんですが・・・ template <class Cont> Cont::iterator GetNItr(Cont c, int n){ Cont::iterator it = c.begin(); for(int i = 0; i < c.size(); ++i, ++it) if(i == n) break; return it; } 帰ってくるのは不定値ばかり。一体なぜなんでしょうか?(試した環境はVC6です。) それ以前に「N番目の要素のイテレータの取得」なんて かなり使いそうな気がするんですがBoostとかにもないですよね。 やっぱり「イテレータ=反復子」という名前に反した使い方だからですかね??
不定値とだけ言われても困るけど つーか std::advance じゃだめなん?(戻り値として iterator を返してくれないから使いにくいけど)
erase(vec.begin() + n) ってやれば?
つーかvectorならbegin() + NでN番目を指すiteratorが帰ってくるはずだが
>>304 >なんで誰も指摘しないのかな。
ヴァカなお前に付き合うの嫌だから。
>>306 とりあえず、その関数は
引数で Cont c ってやってるから、コンテナがコピーされ、コピーされた方の要素を指すイテレータが返るからダメになる。
Cont &cなら思ったとおりにいくんじゃね?まc.begin()+Nの方が断然いいが
ファンクタ書く時に、 operator() 内で、 static std::vector< double > tmp; ってインスタンス作るのと、 private 内に、std::vector< double > tmp のインスタンス作ってoperator() 内で使うのと どっちがいいんですか?
>>312 privateインスタンスのほうがstaticよりマシ。
>>296 それは分かるんですが…
「cin.getline()」使用時に「std::string」をどの様に利用するのですか?
たぶん、そっちじゃなくてstd::getline()のことを言ってるんだと思うよ。
>>316 なるほど。「std::getline()」だったのですね。
良く分かりました。
>>301 throw() 宣言すると、コンパイラが例外処理のためのコードを追加するから、
パフォーマンスを考えれたら、throw() は入れない。
あと、operator= が例外安全でなければいけない理由は、
simpleDBTable.Current["NAME"] = "MONA";
のような簡易データベース中の項目を置き換えるコードがあったとして、
この中で例外が発生したとき、すでにある項目が消されたら困るでしょ?
>>318 >パフォーマンスを考えれたら、throw() は入れない。
なるほどパフォーマンスの問題ですか。
>この中で例外が発生したとき、すでにある項目が消されたら困るでしょ?
そんなことは分かっているのですが(基本的に全ての関数はアトミックにすべき)、
この文脈でその必要はないのではと。例外投げられたら deleteされるので。
>>319 > 例外投げられたら deleteされるので。
そうは言えない。
T x = initial_value;
try
{
x = new_value;
}
catch( ... )
{
}
// x はまだ生きている。
// ここで x の値は initial_value か new_value か、どちらかであると言えなければ、
// 以降、 x へアクセスしたときの動作が把握できない。
>>318 > 例外投げられたら delete される
誰が delete するのさ?
君はデータベースの更新に失敗したら即座にテーブルを破棄するのか?
何らかの例外が発生したときに、
1. その例外を呼び出し元に正しく通知する。(例外中立)
2. 例外が発生しても、オブジェクトの状態は変化しない。
もしくは例外を出さない。(例外安全)
というのが、例外安全の基本。これを
>>295 は理解しているのだろうか?
コンストラクタで例外が発生した場合、そもそもオブジェクトそのものが作成されないが、
代入処理の場合、例外が発生しても依然としてオブジェクトは存在している。
例外から回復して、オブジェクトを再度いじろうとしたときに内容が不定では話にならない。
>>320 >>321 >>322 おんなじこと何度も何度も書きやがって。んなこたー分かってる。
Exceptional C++ 33,34ページの話だYO!
catch してから deleteしてるだろ。
だからクラスTにアトミックな代入演算子は要求しないと思うんだよ。
あと swapについて。
確かに例外を投げないほうがいいときもある。
例えば73ページの第二の試み。最後に代入演算子使ってるけど、例外を投げない swapがあればそれで解決する。
でも Stackの例だとアトミックであれば例外は投げともよいと思うんだよ。
そこらへんどーよ。
>>295 まあ、おちついて。
"代入しようとしていたTオブジェクト"
とはコピー元をさしてっるて解釈はどお?
コピー元がconstでもmutable変数含んでりゃ
同にでも出来るし。
swapについてだけど、逆にswapが例外を投げる可能性がある場合、
swap(v1,src.v1);
swap(v2,src.v2);
swap(v3,src.v3);
見たいなメンバ関数を例外安全にするのは大変だYO!みたいな事が
言いたかったって解釈はどお?
>>323 > Exceptional C++ 33,34ページの話だYO!
そんなコード片の話をしてたのか、そりゃ気付かなかった。
例外発生したときの対応がdelete一択なら、たしかに、そんな要求はないよ。
でも、
>>295 で引用された2行が、より一般的なケースでの指針である可能性はないのかい?
本読んでないからわかんないだけかもしれないけど。
>>324 > "代入しようとしていたTオブジェクト"
> とはコピー元をさしてっるて解釈はどお?
明らかに問題外。
>>326 そお?例えばCOWな実装のstringの場合
代入時にコピー元にも影響ありそうだけど
>>324 よく分からんけど自己代入ってこと?
でもコピー先は newしたばっかの領域だし。
swap についてはその通りですね。
でも Stackの例は適切ではないと思います。
>>325 >でも、
>>295 で引用された2行が、より一般的なケースでの指針である可能性はないのかい?
そう読めなくもありません。訳の問題なのかも。
でも 58ページに
Stack を例外安全にするために、唯一例外安全にしなければならないTのメンバ関数
なんて書いてます。
>>323 そういうことかよ。まぁ、悪かった。
でも今は会社だから手元に本がないんだよなー。
ただ、すこし言わせてもらえば、
アノ本は 代入処理は以下の形式にしなさいというのがキモで、
途中のイロイロは、すべて以下のコードにもっていくための「布石」だと思う。
this_type & this_type::operator=( this_type const & rhs )
{
this_type( rhs ).swap( *this );
return *this;
}
だから、途中のコード云々で話をするのはまったくもって無意味だと思うのだが、どうか?
状態が「不定」なオブジェクトは delete 出来るの?
>>331 できないかもしれない。
けど、最低限それだけは保証してもらわないと、どうやっても回復できなくなってしまう。
例外に対する対応がプログラムの終了以外ほぼ選択肢がなくなってしまうだろう。
(ほかには、そのオブジェクトに2度と触らないようにするくらい?)
解体すらできなくなってしまうような仕様のクラスは作らないのが常識だろう。
>>332 > その swapは例外を投げない保証をする必要ありますか?
this_type::operator=()への要求として例外安全性が必要なければ、
必要ない。
this_type::operator=()への要求として"no-throw gurantee"が必要ならば、
swapへの要求として引数に対する"no-throw gurantee"が必要。
this_type::operator=()への要求として"strong gurantee"が必要ならば、
swapへの要求として引数に対する"strong gurantee"が必要。
this_type::operator=()への要求として"basic(以下略)
s/引数に対する//
>>334 まあつまり例外を投げない保証をする必要はないですよね。
この本 swapが例外を投げないことをやたら強調してますが、その理由が示されていないように思えます。
>>330 > その swapは例外を投げない保証をする必要ありますか?
ある。
>>330 のコードにおいて、swap が例外を発生させる場合を考えると、
>>322 の 2. を満たすためには、
operator= は以下のように直す必要があるが …
this_type & operator=( this_type const & rhs )
{
this_type temp( rhs );
... // this の状態を保存する。※1
try { temp.swap( *this ); }
catch( ... )
{
... // this の状態をもとにもどすコードを入れる ※2
throw;
}
return *this;
}
ここで、※ にどのようなコードを入れればいいかを考えるといい。
さらに、A.swap( B ) において、A のメンバの一部と、Bのメンバの1部だけが
入れ替わった状態で例外が発生すると、
>>322 の 2. を満たせなくなる。
面倒なことをイロイロ考えなくてもいいように、swap は例外を出しちゃ駄目ってことになってるの。
>>336 例外が発生したときには、内部状態が変更されていないことを保証するクラス(群)を
構築する際には、例外安全な swap を用意すると便利だよ、STLもそうしてるよ、
っていう話だと思うけど。boost も同じ方針ですよね。
>>313 何故なんでしょうか?
また、マシって事は他にお勧めがあるんですか?
>>337 だーかーらー swapはアトミック性だけ保証してればいいんじゃないですか? アフォ?
>>338 あなたの言う例外安全っていうのは例外を投げないって意味ですか?
例外を投げないことがアトミック性を実現する一番簡単な方法ってなら分かりますが、
Exceptional C++ は swapが例外を投げないってことを強調しておきながら
そのちゃんとした説明がなされていないと思うんですよ。
>>340 swap がけして例外を投げないわけではない。
ポインタのスワッピングだから例外を投げないのだよ。わかるか?
>>341 ???
組み込み型のスワッピングは例外を投げませんね。
再帰的に全てのスワッピングは例外を投げませんね。
swapは例外を投げないものだってのは分かります。
例外投げたらなんか無理してるってのも分かります。
でも Exceptional C++ 48ページに
> Swap() はどんな状況下であっても例外を投げない。
> Swap() のこの特徴こそが、Stack自身の例外安全に関する論証の要なのだ。
って書いてます。
Stack 内で StackImpl::Swap()は2回使われていますが、
これらが例外を投げたとしても Stackの例外安全性は損なわれないと思うんです。
そもそもC++の例外処理ってプロの方々は積極的に使っているので しょうか?あんまりパフォーマンスがよくないとかいう話も聞くし。 どちらかというと、プログラムの連結とかそういうときに持ち出すの ですか?
>>342 StackImpl::Swap のコードは、3つの std::swap から成り立っていて、
そのすべてが組込型に対するスワッピングである以上、StackImpl::Swap は
決して例外をスローしない。ここまではいいと思う。
そして、Swap が例外を投げない以上、これを積極的に使わない手はない。
で、それをふまえた上で、
>>342 は、次のどちらを言いたいのか?
1. Swap が無くても例外安全に出来るじゃないか。
2. Swap が決して例外を投げないというその理由がわからない。
どうも、あなたの言いたいことがピンとこない…
>>344 僕が言いたいのは、Exceptional C++ の48ページの主張の真意を教えてくれ(Stackの例、間違ってんじゃねーの?)ってことです。
Stack がアトミックなのは Swapが例外を投げないからじゃなくて Swapがアトミックだからだ。
Swapが例外を投げないのはただの結果であって、この場合必要ではない。
と、僕は思うんです。
あー同じこと何回書いただろう。
C++で、継承についてわからないことがあります。 class A { SetOne(); SetTwo(); }; class B { SetOne(;); } class C { SetTwo(); }; というクラスがあったとします。クラスB、CはクラスAにある関数と同じものを一つずつ持っています。 このとき、同じことを何度も定義すると無駄なので、継承を考えますが、必要ない関数まで継承されて しまいます。継承先で、必要のない関数を消す方法などはないのでしょうか? また、何か解決策がありましたら教えてください。
必要な関数だけのクラスを作りましょう。
>>346 class A : public B, public C {};
なんじゃないのか?
>>346 struct afo { virtual SetOne() = 0; };
struct sine { virtual SetTwo() = 0; };
class black { /* ry */ };
class c { /* ry */ };
class A : public afo, public sine { black b; c dakko; /* ry */ };
class B : public afo { black b; /* ry */ };
class C : public sine { c dakko; /* ry */ };
>>345 Swapは絶対に例外を投げない を
Swapは絶対に失敗しない に読み替えれば納得いくんでない?
>>350 もったいぶらないではっきり言えよ。
なにが言いたいのか全くわからねえよ。
それぞれ関数の中で、同じ構造体に値を渡すのですが、この場合多重継承で考えると かなりややこしい作りになってしまうんですが、もっとすっきりしたものにできないでしょうか? できれば多重継承はない方向でいきたいと思ってます。
346です。
355 :
デフォルトの名無しさん :04/06/11 22:07
JAVAのStringTokenizerと同じような機能を持つ関数って CやC++にはないですかね? 地道にクルクル回すしかないのでしょうか。
>>351 それで理解できないなら、その程度の頭ってことだ。
>>357 考えてみても分からん。まじで分からん。
教えてくれ。たのむ。
ソースはかなり長くなってしまうので無理ぽいです。 なのでかなり端折りますが、以下のような構造体を持つクラスがあります。 これはDirectXで用意されている構造体です。 typedef struct _D3DLIGHT9 { D3DLIGHTTYPE Type; D3DCOLORVALUE Diffuse; D3DCOLORVALUE Specular; D3DCOLORVALUE Ambient; D3DVECTOR Position; // ディレクショナルのとき無視 D3DVECTOR Direction; // ポイントのとき無視 float Range; // ディレクショナルのとき無視 float Falloff; // ポイント、ディレクショナルのとき無視 float Attenuation0; // ディレクショナルのとき無視 float Attenuation1; // ディレクショナルのとき無視 float Attenuation2;// ディレクショナルのとき無視 float Theta; // ポイント、ディレクショナルのとき無視 float Phi; // ポイント、ディレクショナルのとき無視 } D3DLIGHT9; type には ポイントライト、スポットライト、ディレクショナルライトがあります。 それぞれのライトには適用されず無視される変数というのが存在しています。 パラメータの前に書いてあるメッセージがそれです。 この構造体のすべての値を変更できるように、それぞれに対してセッターを作ると 実際に使用するときに、間違って無効なパラメータを設定してしまう場合があると思います。 これを防ぐために、3つのライトそれぞれをクラス化して、無効なパラメータを設定するような 関数は省きたいと思っています。
よーやくわかったよ。だからこれで最後。 わたしが想像する サッターさんの真意は、 P35 や P37 のガイドラインおよび、P42 の 3 にあると思う。 それをうけての P48 の記述。 彼の譲れない部分(信念)として、「例外を起こす可能性のある処理」をすべて最初に行い、 「例外を投げる可能性のある処理で状態変更をしてはならない」わけ。 例はあくまで例。言いたいことはコレ。 以下駄文。国語のテストみたいなもん。 Swap に求められていることは、「アトミック」だとか「例外安全」とかいうことではないと思う。 本当に求められているのは、きっと「絶対に失敗しない」こと。 「ここまで来れば絶対成功する」という保証。だから、アトミックであることはもちろん、例外を投げるなんて論外。 まぁ、そういう宗教だと思えばいいじゃん。
あ、360 = 342 ね。
362 :
デフォルトの名無しさん :04/06/11 22:32
>>360 あっはっはー
やーい逃げた逃げた
何が宗教だ ぼけ
例外を投げるくせにアトミックというのがよくわからん。 教えてエロいひと!!
>>359 struct PointLight : D3DLIGHT9 {
ポイント用セッター
};
としておいて、生の変数には直接触らないと誓う。
もしくは、AbstructLightクラスのメンバにD3DLIGHT9を持たせて、外からは触らないようにするか。
どっちにしろ、あんまりこだわっても大して嬉しくはならないので、適当なところで妥協することを薦める。
そもそも例外安全な代入をやりたいのに、代入とは別の処理であるSwap()が失敗されちゃあ、たまらん。 失敗する可能性が本来の代入処理より増えるのであれば、そんなロジックは採用したくない。
>>360 >>361 >>362 え? 騙られてんの?
>>360 なるほどねえ。そう考えればつじつまは合わなくもない。
例はあくまで例というけれど、そんな破綻した例を持ち出して 48ページのような強い物言いをするかな?
信念があるのはよいけれど全く例が伴ってないよ。
>>323 に書いたように swapが例外を投げちゃいけない例ってのがあって、しかもその信念にぴったりなのにね。
本の内容に納得いかないのなら、著者に文句を言うべきだ。
>>364 >>生の変数には直接触らないと誓う。
誓うというのは、基本的に自分ならば大丈夫ですが、それ以外となると不可能なので。
妥協して無駄に同じ処理を記述するようにします。
ありがとうございました。
>>365 そんなレベルの話をしてるんじゃねえよボケ、と言いたいところだけど
著者の真意は案外そんなとこかもしれない。
>>367 そうですね。これだけ粘っても誰も説明できなかったので、著者は電波ってことで納得します。
スレ汚しスマソ。
370 :
デフォルトの名無しさん :04/06/11 22:59
295の態度が徐々に変わってゆく姿が笑える。
>>369 >>363 の質問にも答えてやってくれ。
例外を出して、かつアトミックな処理の例とか出してくれると助かる。
>>371 そんなもん try,catch 使えばいくらでも書けると思うけど、好みじゃないので。
例えば
>>330 最初のコピーコンストラクタが失敗しても、状態は変化していない。
その後の swapは例外を投げない、もしくはアトミックなので例外が起きても大丈夫。
最後の returnは参照渡しだから例外を投げない。
より一般化すると
>>314 template <class Container, class BasicOp>
void MakeOperationStrong( Container& c, const BasicOp& op )
{
Container tmp(c); // Copy c
op(tmp); // Work on the copy
c.swap(tmp); // Cannot fail
}
op() がアトミックじゃなくても swap()がアトミックであれば、副作用が一つの処理なら
どんな処理でもアトミックにできると思う。
副作用が二つあったりすると、例外を投げない swap() が必要になると思う。
まあ swap()は例外を投げないべきだけどね。
文章いじったらおかしくなった。 op() がアトミックじゃなくても swap()がアトミックであれば大丈夫。 アトミックな swap()があれば、副作用が一つの処理ならどんな処理でもアトミックにできると思う。 にして。
あぁ、アトミックってそっちかYO! てっきりクリティカルセクション的なアトミックを連想したよ。 つまり、 T temp( a ); a = b; b = temp; ってあったら、そのすべてが必ずひとまとまりに行われるってのを想像した。
>>295 は釣り師だったということで、終わりにしようぜ。
>>339 staticインスタンス
×寿命が(おそらく)不必要に長くて、さらにその寿命はほぼ制御不能。
×さらに関数内staticは関数外からのアクセスは不可能。
○毎回作り直さないので、生成、破棄のコストがかからない。
×マルチスレッドに対応不可能。
privateインスタンス
○寿命はファンクタの寿命を超えない範囲で自由に制御できる。
○メンバ関数を通してアクセスが可能。
×毎回作り直すので、生成、破棄のコストがかかる。
○マルチスレッドに対応可能。
お勧めは、ファンクタのコンストラクタでstd::vector<double>への参照を受け取り、
メンバにポインタを保持する方法。
アルゴリズムのファンクタ引数は値渡しで実装されている可能性が高いので、
コピーのコストを抑えた方がいいケースが多い。
>>355 boost::tokenizerでかなりの事はできない?
>>368 ポイントライトの位置設定とスポットライトの位置設定が同じ処理になることが偶然
と考えれば、別の関数としておくことに意義を見出せないか?
>>376 それを指針に考え直してみます。
詳しい説明有難うございました。
380 :
デフォルトの名無しさん :04/06/12 08:57
EUCからShift Jisに変換するにはどうしたらいいでしょうか?
nkf
382 :
デフォルトの名無しさん :04/06/12 10:45
>>376 特徴としてあげている箇条は大筋いいが
目的が示されていない以上そこまでだろ
どっちがお勧めという根拠がないぜ
383 :
デフォルトの名無しさん :04/06/12 10:55
>>380 EUC2SJISを使えば変換してくれるよ♪
384 :
デフォルトの名無しさん :04/06/12 10:57
visual cとturbo cとc言語とc++との 区別が付けられません
385 :
デフォルトの名無しさん :04/06/12 10:59
>>384 区別をつけられなくて困っていることがあるのか?
386 :
デフォルトの名無しさん :04/06/12 11:00
小文字厨らしいな
387 :
デフォルトの名無しさん :04/06/12 11:04
>>384 >(visual cとturbo c)と(c言語とc++)との
E-mailとインターネットはどっちがいいですか?
ってのと同じくらい的外れな質問だぞ
>>380 EUCコード&0x7f7fしてからwctombs()だっけ?
390 :
デフォルトの名無しさん :04/06/12 12:16
小文字厨なんてのもいるのか
いるようだ。 全角厨より、100倍マシだと思うけど。
wcstombs()か。つーか寧ろmbcjistojms()で一文字ずつ変換した方が楽か。
>>390 それが何か?
まぁ実際には、自分でコーディングしちゃうんだけどね。
395 :
デフォルトの名無しさん :04/06/12 12:46
>>394 &0x7f7fしたら1バイト目の8ビット目まで0になってしまうと思うんだけど。
396 :
デフォルトの名無しさん :04/06/12 12:51
>>395 それがなにか? EUCの最上位ビットなんて(コードページを切り替えるための)飾りですよ。
飾りを取れば只のJISですから。
#但し、所謂1バイトかなの判定はそれ以前に行う必要があるけど。
>>397 私にはあなたの言いたいことが判らない。
380 :デフォルトの名無しさん :04/06/12 08:57 EUCからShift Jisに変換するにはどうしたらいいでしょうか?
度々スマソ。 wcstombs()がコード変換すると何でか思い込んでたよ。 私が勘違いしてただけなのね。
setlocale(LC_ALL, "jpn"); char buf[101]; wcstombs(buf, L"あいうえお漢字", 100); puts(buf); いや、普通にUCS-2からSJISに変換してるが@VC++6.0
文字コードの変換じゃなくて、表現形式の変換。
C+++++++++++++++++++++++++++++++++++++++
EUC-KR からだったらどうするよ
CreditCard *card = new CreditCard("岸部四郎") if( ! card ){ printf("ブラックリストに載っています"); return 0; } card.buy(1000000); delete card; return 0; こんな風にしたいんですが、 new("岸部四郎") CreditCard() を回避できないでしょうか?
???
えっと、 ・初期化エラー時nullを返すにはnew内で初期化 ・初期化に引数をとるにはコンストラクタ内で初期化 で、両立する方法は new("誰それ") CreditCard() とありました。 しかしできれば普通の書式が良いのですが、他に無いでしょうか? それともnullチェックより例外を使うべき?
>>406 class CreditCard{
CreditCard(const char *);
public:
static CreditCard *New(const char *name){
if(name in list){
return 0;
}
return new CreditCard(name);
}
};
CreditCard *card = CreditCard::New("岸部四郎")
if( ! card ){
printf("ブラックリストに載っています");
return 0;
}
card.buy(1000000);
delete card;
return 0;
意味が分からないというか、 その前に本をよく読んでいないか読み間違えていないか? new で引数をとるコンストラクタを用いたいなら、 new CreditCard("岸部四郎")以外ないと思うが、 回避したいって何が問題で何を回避したいの?
>>409 ありがとうございます。
ただ、やはり特殊な書き方になってしまうので避けたいです…。
>>410 ・初期化失敗時にnullを返したい
・普通にnew CLASS(引数)を使いたい//こっち重視
です。
newをオーバーロードして new(引数) CLASS() でも、
>>409 さんのCLASS::New(引数)でも、
一つ目をクリアする代わりちょっと浮いちゃうので…。
一つ目を諦めると例外を使うことになりますが、あまり失敗の多いところで使うと良くない気がして…。
他に解決方法はあるでしょうか。(例外で問題なければそうします)
滅多に失敗しないのなら、なおさら例外を使うべきでは?
>>409 はファクトリちっくだしそんなに特殊な書き方だとは思わないけど。
>>411 >他に解決方法はあるでしょうか。
無い。
相談の範囲を多少逸脱するかもしれないけど。
チェックしたいのがブラックリストのみで、
それに必要なのがコンストラクタで与える名前だけなら、
ブラックリストをメンバ変数としてもち
内部で
>>409 のような処理を行うメンバ関数をもつ発行者クラスを
別に用意してチェックを分離したほうがスマートだと思う。
>>412 失敗はそれほど多くは無いと思います。が、後学のためにと思って。
>>413 そうですか…。勝手に CLASS.Create() はdelphiスタイルと思い込んでいました。
>>414 分かりました、ありがとうございます。他の方法をとります。
>>415 なるほど…。今回の場合ですが、例が不適切でした。
実は一段下でそれに似たことを行っており、(例? Deal *deal = card.startDeal() )、
かつcardを多数作るわけではなかったので三重は大げさかなと思った次第です。
今回は例外で行きますが、今後三種類の方法を適宜使い分けることにします。ありがとうございました。
情報が小出しになった&長文失礼しました。
417 :
デフォルトの名無しさん :04/06/13 00:08
Cスレより誘導されてまいりました。同じことを質問しますがお許しください。 データの初期化について質問します。 例えば以下の例が有るとします。 enum Type { taaa, tbbb, tccc, tlast }; static char* lpType[tlast]; void main() { lpType[taaa] = "aaa"; lpType[tbbb] = "bbb"; lpType[tccc] = "ccc"; printf(lpType[tbbb]); } これはこれで上手く行ってる訳ですが何となく美しくない。 そこでこれをlpTypeを宣言した時に初期化したいわけですが 何らかの方法って無いでしょうか。 要は static char* lpType[tlast] = { [taaa] = "aaa", [tbbb] = "bbb", [tccc] = "ccc", }; 見たいな事が出来ないかなぁと思うわけですが。
418 :
デフォルトの名無しさん :04/06/13 00:11
グローバルなクラスオブジェクト ...を要素とする配列 ...をメンバ変数にもつクラスオブジェクト ...がTypeを添え字にとる配列オペレータを定義 していれば、できるんじゃねーかな。
enum Type { taaa, tbbb, tccc, tlast }; template< std::size_t N > class lpType { static char[] tmp; public: static ostream& operator<<( ostream& os ) const { os << tmp; } }; lpType<taaa>::tmp = "aaa"; lpType<tbbb>::tmp = "bbb"; lpType<tccc>::tmp = "ccc"; template< std::size_t N > lpType<N>::tmp = "not defined"; int main( void ) { std::cout << lpType<taaa> << std::endl: }
あ~、間違えてら。
いろいろ調べてみましたがどうやらVCはC99に対応していないようなので
>418の方法は無理みたいですね。
それにC99を使うとなるとC++は使えなくなるようなのでこれも問題です。
とりあえず今回は勉強になったのでこれで良しとします。
有難うございました。
>>420 ここまでやるぐらいなら最初にmainで定義したほうが良さげです。
これはこれで面白いのですが。
423 :
デフォルトの名無しさん :04/06/13 08:40
Javaで言うとことのプロパティファイルを読みこむ自社製ライブラリがあります。 名前=値に加え、型情報などの情報が「バイナリ形式」として納められています。 ↓イメージ(実際はバイナリ) long=name1=-123 unsigned long=name2=123 char *=name3=hello ↓値取得のクラス&メソッド(名前と型が一致しないと例外発生。型を取得するメソッドはない。) void Conf::Conf(const char *file); void Conf::getValue(const char *name, long *l); void Conf::getValue(const char *name, unsigned long *lu); void Conf::getValue(const char *name, char **s); ■このクラス&メソッドを下のような形式にラッピングしたいと思っています。 適切な型 ConfX::getValue(const char *name); 基底クラスをあとから作る?例外で条件分岐?なにかよい方法ありませんか?
>>423 どうすれば「よい」とみなすのか示せボケ
CBaseを基底クラスとしたCAとCBと言うクラスが有ります。 そしてCBaseにはhoge()と言う仮想関数を実装しています。 そして現在、以下のようなコーディングをしていますがー CBase* pBase; switch (i) { case 0: pBase = new CA; break; case 1: pBase = new CB; break; } pBase->hoge(); 正直綺麗じゃないし無駄なような気がします。 クラスを配列に定義して以下のように何とか出来ないでしょうか。 pBase = new class[i];
>>426 typedef CBase* NewFunction();
template< typename T > CBase* New(){ return new T; }
NewFunction* const table[] = { &New<CA>, &New<CB> };
pBase = table[i]();
428 :
デフォルトの名無しさん :04/06/13 16:35
>>427 うーん、色々やって見ましたが上手く行かないです。
これをどこら辺に定義すれば良いのでしょうか。
とりあえず、こんな感じじゃ無理でした。
#include <windows.h>
typedef CBase* NewFunction();
template< typename T > CBase* New(){ return new T; }
CBase* const table[] = { &New<CA>, &New<CB> }; // エラー
CTest::CTest()
{
int i = 1;
CBase* pBase = table[i]();
}
エラーメッセージ
error C2440: 'initializing' : '' から 'class CBase *const ' に変換することはできません。(新しい動作 ; ヘルプを参照)
コンテキストはオーバーロードされた関数の非不明瞭を考慮しません。
っと、上のままの場合だと以下でした。 >CBase* const table[] = { &New<CA>, &New<CB> }; // エラー NewFunction* const table[] = { &New<CA>, &New<CB> }; // エラー error C2440: 'initializing' : '' から 'class CBase *(__cdecl *const )(void)' に変換することはできません。(新しい動作 ; ヘルプを参照) スコープ内でこの名前を持つ関数でターゲット型に一致するものはありません。
>>429 class CBase{};
class CA : public CBase{};
class CB : public CBase{};
typedef CBase* (*NewFunction)();
template< typename T > struct NewT{ static CBase* New(){ return new T; } };
NewFunction table[]={&NewT<CA>::New,&NewT<CB>::New};
int main(){
CBase *p=table[0]();
>>431 上手く出来ました。有難うございました。
constは捨てろってことだな
VS2002にVCToolKit2003をいれてstlport4.6.2でboostコンパイルできた人いる? error LNK2019: unresolved external symbol "__declspec(dllimport) int __cdecl swprintf(unsigned short *,unsigned int,unsigned short const *,...)" が4個ほど出るよ…
変な組み合わせすんなよ 2002使えるってことは2003もらってるはずだろ
アカデミックだったり(泣
439 :
デフォルトの名無しさん :04/06/14 02:23
コンストラクタにテンプレート引数を渡したいのですが引数を使って 暗黙的?に渡す以外はコンパイルエラーになってしまいます A自体にtemplateをつける以外でどのようによびだせばよいでしょうか? struct A { template<class T>A() { cout << typeid(T).name() << endl; } template<class T>A(T) { cout << typeid(T).name() << endl; } }; int main() { // A a<int>(); こういう感じで呼びたい A a(1); //かっこ悪い return 0; }
何で、 >A自体にtemplateをつける以外で こんなことしたいの?
ちょっとした型推論ですよ。ありがたく省略しないと。
442 :
デフォルトの名無しさん :04/06/14 05:57
>>439 もしかしてVCか?
明示的なテンプレート実引数の
正当な形を撥ねるケースよくあるぞ
コンストラクタで、そういったことがしたいなら、以下のような手を使うとかね。 ちょっと格好悪いかも知れんけど。 template< typename T > struct type{}; template< typename T > A::A( type<T> ) { cout << tyoeid(T).name() << endl; } A a( type<int>() );
444 :
デフォルトの名無しさん :04/06/14 14:16
>>377 そんなものがあったんですね。ありがとうございました。
で、さっそく使ってみたのですが、
tokenizer.hppをincludeしてビルドしたところ、以下のようなビルドエラーが出ました。
boost\tokenizer.hpp(60) : error C2039: 'begin' : 'CString' のメンバではありません。
c:\program files\microsoft visual studio\vc98\mfc\include\afx.h(368) :
'CString' の宣言を確認してください。
C:\VC_PROJECT\0806\01\Main1.0β_0806\SetUserEntryDlg.cpp(310) :
コンパイルされたクラスのテンプレートのインスタンス化 '__thiscall boost::tokenizer<class boost::char_delimiters_separator<char,struct std::char_traits<char> >,char const *,class std::basic_string<
char,struct std::char_traits<char>,class std::allocator<char> > >
::boost::tokenizer<class boost::char_delimiters_separator<char,struct std::char_traits<char> >,char const *,class std::basic_string<char,struct std::char_traits<char>
,class std::alloca
tor<char> > >(const class CString &)' の参照を確認してください
問題の個所は
template <typename Container>
tokenizer(const Container& c)
: first_(c.begin()), last_(c.end()), f_() { }
となっています。これってboostのバグなのでしょうか。それともこちらの設定か何かが悪いのでしょうか。
長くてすみません。
>>444 CString じゃなくて std::string を使うべき。
すみません。 読ませるのをCStringじゃなくstringにしたら通りました・・ お騒がせしました。
boost::functionにtemplate関数を代入したいのですが、 以下のコードではコメントアウトした部分ですべてコンパイルできませんでした。 何とかならないでしょうか? #include <iostream> #include <boost/function.hpp> template< typename X > void testFunc( const X x ) { std::cout << typeid(x).name() << std::endl; } int main( void ) { //boost::function< void ( const int ) > f; //boost::function< template< typename X > void ( const X ) > f; //boost::function< void template< typename X >( const X ) > f; //boost::function< void ( template< typename X > const X ) > f; f = testFunc; f( 1 ); return 0; }
>>448 boost::function<void (const int)> f; // constはなくても変わらない。
f = static_cast<void (&)(const int)>(testFunc); // void (*)(const int)でも良い。
キャストすれば良かったのか… とおりました、ありがとです。
本番が出来ませんでした…orz boost/graphの boost::in_degreeをつっこみたいのですが。宣言だけ書いてみます。 template< class Config, class Base > inline typename Config::degree_size_type in_degree( typename Config::vertex_descriptor, const adj_list_helper< Config, Base >& );
関数の戻り値の型(?)がoperatorとなっているものを 見かけたのですが、これはどういう意味でしょうか。
>>449 ふつうは、キャストを嫌ってこっちだとおもうが。
boost::function< void (int) > f = testFunc< int >;
455 :
デフォルトの名無しさん :04/06/15 00:18
newで作った配列の初期化はどのようにすればいいのでしょうか? 文法がよくわかりません。 int *p = new int[3] = { 1, 2, 3 }; や int *p = new int[3] { 1, 2, 3 }; とやっても構文エラーがでてしまいます。 JavaやC#は下のやり方でいけるのですが。
>>456 ガ━━━━━━∑(゚д゚lll)━━━━━━ン
>>455 #include <vector>
static int const initial[3] = {1,2,3};
std::vector<int> v(&initial[0],&initial[3]);
459 :
デフォルトの名無しさん :04/06/15 03:16
class A { protected: int a; public: int GetA() const { return a; } void SetA(int a) { this->a = a; } }; class B : public A { protected: double b; public: }; このようなクラス関係で B bInstance[100]; bInstance[1].SetA(50); const A* ptr = bInstance; ++ptr; int result = ptr->GetA(); とやるとポリモーフィズムでresultに50が入ると思うのですが、 実際には正しい値が得られません。 どこがおかしいのでしょうか?ご教授下さい。
>>459 C++のポリモはポインタが指してる先のオブジェクトへの操作
( *ptrか ptr ->mem_function() )についてだけで
ポインタそのものの操作(この場合、++ptr)に対しては
ポリモではないから。
つまり++ptrが間違い。
>>459 ポリモーフィックなクラスを配列にしてはいけない。
参考:More Effective C++ の
「項目3: 配列をポリモルフィズム的には扱わない」
462 :
デフォルトの名無しさん :04/06/15 03:48
>>460 そういうものなのですね。ありがとうございました。
>「項目3: 配列をポリモルフィズム的には扱わない」 C++っていたるところで腐臭がする言語ですね。
そうでもないよ。
やっぱり C++は ダサい な
ポリモーフィックなクラスへのポインタ配列を使えばいい。 基底クラスやそこから派生したクラスを同一の配列に押し込むのは、サイズの違う 構造体を一つの構造体配列に無理矢理入れるのと同じ。破綻して当たり前。
467 :
デフォルトの名無しさん :04/06/15 07:32
>>452 struct mona { operator giko (); };
なら、mona型からgiko型へのキャスト
mona c;
(giko)c;
ポリモーフィックはJavaでは良く使うんだがC++ではちょっと難しいね
469 :
デフォルトの名無しさん :04/06/15 09:44
boost::tokenizerについて2つ質問です! typedef boost::tokenizer<> tokenizer1; tokenizer1 token( strLine ); for( tokenizer1::iterator it=token.begin(); it!=token.end(); ++it ){ cout << "TOKEN: " << *it << endl; } strLine には id001,あいうえお,pass,1, という文字列が入ってます。 で、 it の中の tok_ を見てくと、一回目は "id001" がちゃんと切り出されているのですが 二回目は "あいう" となっていて 三回目は "お" となっています。 区切り文字が "," 以外にも使われているのが原因か、日本語がだめなのかどちらかだと思います。 区切り文字を指定する方法、日本語を使う方法、わかりませんか? 2つめ。itに入ったトークンをCString か std::string か char[] にコピーするにはどうしたらいいでしょうか。
単なるポインタの理解の問題に見えるけど? 459ってポリモーフィック関係ある?
>>468 Java や C# のようにいちいち new するやり方なら、C++ も似た様な動きをすると思うけど。
>>470 関係ないですね。
C++ 的にはこの場合ポインタじゃなくて iterator をつかうべし、ということになるんでしょうね。
アドホックに済ませるならポインタ進めるための Next とかいうメンバ関数を用意するとか。
C++のごちゃごちゃな仕様を組み合わせた結果 直感に反する挙動を示したからっていまさらキーキー言うのはナンセンスだよ。 カレーに肥料としての効果を期待するようなもんだ。
すみません。質問ですー DB検索結果を格納するために 連想配列を使用してやろうとおもっているのですがなかなうまくいきません。 vector<map<string, string>>の型に格納予定です。 要素のmapにアクセスできないみたいです。 どのように書けばうまくアクセスできるのですか? typedef StringHash map<string,string> typedef VectorStringHash vector<StringHash> VectorStringHash *pvsh // 検索結果格納済み vector<string> vstrFieldName // フィールド名 for (VectorStringHash::iterator vit = pvsh->begin(); vit < pvsh->end(); vit++) { for (vector<string>::iterator it = vstrFieldName.begin(); it < vstrFieldName.end(); it++) { StringHash shMap = *vit; StringHash::const_iterator n = (StringHash::const_iterator) (*vit).find(*it); string strMap = n->second; //Segmentation faultでおちちゃう。 } }
475 :
デフォルトの名無しさん :04/06/15 15:39
C++のときはnewは滅多に使わないな。 遅くなるし...面倒だし... 継承もメモリもったいないからなるべくしない... ようにしてる
>>474 つーか、そのコードじゃコンパイル通らんぞ普通。
フリーのコンパイラを入れて、とりあえず何か作って練習しようと思ってるんですが GCC と Borland C++ Compiler だとこちらの方がおすすめとかありますか? ・特殊な部分がなく汎用的で、後から別の環境に移りやすいか ・初心者にも使いやすいか の2つを気にしてるんですが・・・
>>478 Win32APIに触って窓出したりする必要ないならCygwinのgccが無難なんじゃないの。
フリーのbccは進歩止まってるし。
>>479 フリーのBuilderXに新しいBCCついてるよ
>>474 x < it->end() って意味あんの?
x != it->end()じゃね?
すみません。解決しました。
>>483 さんの助言で見直したところ
表示ルーチンはまったく関係なかったようです。
mapを作るときにどうやらスコープを考えてなくつくったようで
内容がすべておかしくなってました。
お騒がせしました。
487 :
デフォルトの名無しさん :04/06/15 19:37
>>478 フリーって時点で「初心者向き」は消えたも同然
ベテランにとって必要な機能に限定した軽快な味が売りだからね
手取り足取りのサポートが欲しければ金がかかるのは世の常だよ
>>478 gcc しかないと思う。
風変わりな拡張を多用しないし、処理系固有のクラスライブラリとか覚えなくて済むし。
あと、コンパイラに「使いやすい・使いにくい」っていう差は特にないと思う。
あまり古いものだと規格準拠度が落ちて問題あるかも知れないけど。
>>488 >処理系固有のクラスライブラリとか覚えなくて済むし。
は? 別に付属してるもの全部覚える必要なんぞ無いだろ?
オーバーライド可能な演算子にカンマがあるのですが これって何の用途があります?
>>492 とはいえ、無理に使わないほうがイロイロな意味で幸せな気もする。
495 :
デフォルトの名無しさん :04/06/15 23:11
ま、そんくらいでトリッキーとか言い出す人の発言としては嘘じゃあんめえな
>>495 一見してデフォルトとまったく違う動きをするようなコードは、避けたほうが
良いと思うけどな。演算子オーバーロードにせよプリプロセッサのマクロに
せよ。
ネタとしては面白いけど。
>>467 レスありがとうございます。なんとなくそんな気がするのですが、
(giko)c
というより
giko(c)
ではないのでしょうか・・・それともどっちでもいいんですかね。
498 :
デフォルトの名無しさん :04/06/15 23:17
>>497 いてっ
おめーに突っ込まれるとな・・・
俺もヤキ回ったな
499 :
デフォルトの名無しさん :04/06/15 23:20
>>499 昔ハマったのは operator&& のオーバーロード。C/C++ だと組み込み演算子の && は
短絡評価できることが保証されているから
return foo() && bar();
だと foo() が真なら bar() は評価されない。しかし operator&& オーバーロードして
あると bar() も評価されちゃうので、意味合いがまったく違ってしまう。
字面が同じで一見してバグを発見できずに数人が半日無駄にした覚えあり。この
オーバーロードをしたヤツが、その後どうなったかはとても言えない。
501 :
デフォルトの名無しさん :04/06/15 23:31
>>500 >return foo() && bar();
こんなんでハマんなや
C++じゃねぇが、Pikeの組み込みstring型の算術演算子オーバーロードは流石にやりすぎだろと思ったな。 わからんでもないんだが。 C++だとboostのpathあたりか。spiritあたりまでいっちまうともうどうでもいいんだが。
503 :
デフォルトの名無しさん :04/06/15 23:34
極論するとoperatorはまったくいらない(代入でさえも) 「やりすぎ」かどうか論じるには基準が必要
504 :
デフォルトの名無しさん :04/06/15 23:52
>foo() が真なら bar() は評価されない foo()が偽なら bar() は評価されない じゃない?
>>484 コンテナのiteratorがRandomAccessIteratorなら、あり。
それ以外のイテレータなら、なし。
最近、「実装とインタフェースの分離」を耳にする事が多いのですが、 ここでのインタフェースって何を指しているのでしょうか? 例えば、 class Implと、class Infcが在ったとき、Implの方には実装に必要な privateインタフェースのみが定義されていて、publicインタフェースは無しで、 Impl内で、friend class Infcが記述されていて、InfcにImplのインタフェースを 移動していると言うことでしょうか?例を示して貰えないでしょうか?
>>506 ごく簡単な例だと、例えば簡単な html パーサを書いていて、タグの情報をクラス化するとしたとき、
インタフェイス IHtmlTag を
class IHtmlTag {
public:
virtual const string& get_Name() const = 0;
virtual const HtmlAttr& get_Attributes() const = 0;
};
と定義し、実装は
class CHtmlImpl : public IHtmlTag
{
string m_strTag;
HtmlAttr m_attributes;
virtual const string& get_Name() const { return m_strTag;};
virtual const HtmlAttr& get_Attributes() const { return m_attributes;};
};
なんてしておく。
多重継承やcontainment で複数のインタフェイスを持つクラスなんかも作れる。
利点はイロイロあるけど、産業的にはクローズドソースでクラスライブラリを公開できる点が重要。
>>507 ほほ~。多重継承の場合は、LokiのGenLinearHierarchy等で複数のインタフェースを突っ込んだら
いい訳ですな。containmentは初めて聞くのでちょっと分かりません。後、
クローズドソースでクラスライブラリを公開できるって言うのと、.cppは公開せずに.hppのみの
公開の違いが分かりません。良かったらフォローお願いします。
>>508 C++ はたとえ private なものでもメンバ変数ひとつ増えるとオブジェクトサイズが
変わってしまう。インターフェースと実装を分離しない場合、内部的な改修で
あってもバイナリ互換性が崩れる可能性があるのでマズい。
以前は Microsoft の DLL でも、この手の変更が合ってとつぜん動かなくなる、
なんつー問題がしばしば発生してた。
510 :
デフォルトの名無しさん :04/06/16 22:48
>>506 Cで言うところのソースとヘッダの分離におけるヘッダにあたる。
ヘッダだけ公開しといて、ソースはそれに合うように作れと。
標準化委員会なんかが好むやり方を想像すればいい。
インタフェイスだけのクラスでも、そのサイズは最低1だったと思ったのですが、 そこから継承されたクラスは、その分、大きくなるのでしょうか?
512 :
デフォルトの名無しさん :04/06/16 23:02
>>511 1バイト?
確かに実装は未規定だが
さすがにそれは難しそうだな
>>510 実装とインタフェースを分離した場合でも、実装とインタフェースのヘッダファイルは
両方とも公開しますよね?分離した場合何か特に利点となる場合があるのですか?
514 :
デフォルトの名無しさん :04/06/16 23:06
>>513 実装については一切公開しないのがインターフェイスというやり方。
現実には実装も公開しちゃってるケースよくあるけど、それは妥協の産物。
>>511 1 バイトなのはポリシークラスでしょ。仮想関数あったら、最低ポインタ 1 個分は
必要。
継承した場合は単一敬称なら相変わらずポインタ 1 個分。多重継承すると
ポインタ n 個分になる実装が一般的。あと仮想継承は話が別。
>>514 それでは自分で独自のインタフェースを書く場合困らないのですか?
>>513 実装側のヘッダは公開する必要ないけど。コンストラクタを陽に呼び出すのではなく、
インターフェースに従ったオブジェクトを作成する関数や、あるいはファクトリクラス
を公開する。
// 公開ヘッダ
struct IFoo {}; // 純粋仮想関数いろいろ
IFoo* CreateIFoo(); //
// 非公開ヘッダ
class CFoo : public IFoo {};
// 非公開実装
IFoo* CreateIFoo() { return new CFoo; }
Microsoft の COM まわりのドキュメントが参考になると思うぞ。
518 :
デフォルトの名無しさん :04/06/16 23:12
>>516 もしかして
#define インターフェース 実装
状態か?
あー、すいません、勝手に、 template< typename Interface > class Impl : public Interface { ... } を妄想していました。
520 :
デフォルトの名無しさん :04/06/16 23:26
>>519 Impl* pObj; ってやろーとしたろ?
Interface* pObj = new Impl; もダメ
さあどうする?
522 :
デフォルトの名無しさん :04/06/17 00:14
string型をchar型へのポインタに変換するにはどうしたらいいのでしょうか。
c_str
524 :
デフォルトの名無しさん :04/06/17 05:28
標準コンテナってデストラクタが仮想関数じゃないから 継承できないんだよな。(パフォーマンスのためなんだろうか) virtualって一文字追加すれば良さそうなんだが... このためだけに2つも実装書くのも面倒そうではあるが...
>>525 機能拡張したい場合は、
できないよりできた方がイイと思うんだが...
完成されたものであれば、その必要はないだろうねぇ。
そもそもコンテナをポリモフィックにdeleteする場面ってあるんだろうか?
>>526 10中ハック、526がタコ。
といったところ本人がそれに気づくはずもなし。
まぁ、気がむいたら問題を書いてみな。
このスレの前の方にいた、継承するときには必ずデストラクタをvirtualにしなければならないと思い込んでるヤシだったりして。
つーか、STLコンテナにPolicyがあればいいだけなんだがな。
>>527 のような場合に
virtualじゃなかったら欠陥になりうるじゃん。
気を付けろといえばそれまでだけどw。
(だから、自分が管理してないコードに使うときはこわくて使えない。)
一般にポリモフィックな動作であれば問題ないコードで問題に
なるわけで、たぶんこれは継承じゃないんだなと邪推。
struct NV{~NV(){}};
struct EX :public NV{~EX(){}};
boost::scoped_ptr<NV> p(new EX);
とか?
・virtualメソッドを持つクラスを定義する場合、デストラクタもvirtualにする。 ・virtualメソッドをもつクラスを継承する場合、デストラクタもoverrideする。
>>532 それはそうかもしれないが、重要なのはなぜそうなのか?ということだ。
>>526 にも理解できるよう説明すること。(20点)
>531 boostのスマートポインタで扱う場合、そのケースでもメモリリーク(確か)しないよ。 試しにやってみなよ。
>>535 #include<iostream>
#include<boost/scoped_ptr.hpp>
struct NV{~NV()//virtual をあえてつけてない
{std::cout << "~NV" << std::endl;}
};
struct EX :public NV{
~EX()//virtualにすると呼ばれないだけでなく、下記の呼び出しでアボーンしちゃう
{std::cout << "~EX" << std::endl;}
};
int main()
{
{boost::scoped_ptr<NV> p(new EX);}//~NV
}
>>530 その通りですね。(以下はイメージ的なもの)
#include<iostream>
#include<boost/scoped_ptr.hpp>
struct Virtual{virtual ~Virtual(){} };
struct Non_Virtual{};
template<typename T,typename P_V=Non_Virtual> struct SEL{
SEL(){}
~SEL(){ std::cout << "~SEL<T,Non_Virtual>" << std::endl; }
};
template<typename T> struct SEL<T,Virtual>{
SEL(){}
virtual ~SEL(){ std::cout << "~SEL<T,Virtual>" << std::endl; }
};
template <typename T,typename P_V=Virtual> struct SEL_EX :public SEL<T,P_V>{
SEL_EX(){}
~SEL_EX(){ std::cout << "~SEL_EX" << std::endl;}
};
int main(){
{boost::scoped_ptr< SEL<int,Non_Virtual> > p(new SEL_EX<int,Non_Virtual>);}std::cout << std::endl;
{boost::scoped_ptr< SEL<int,Virtual> > p(new SEL_EX<int,Virtual>);}
}
>>535-536 メモリリークしないのは shared_ptr
ためしに、
>>536 の main を以下のように書き換えて見れ。
int main()
{
boost::shared_ptr< void > p( new EX );
return 0;
}
標準ライブラリとかAPI的なものは普通は継承しないんだから デストラクタにvirtual付いていなくても仕方が無いような気がするんだが。 継承しても、クラスの内部的な動作を差し替えるようなことはできないし。 単なるラップ+αなら、メンバとして持ったって同じような気がする。 ソースを見てデストラクタを確認したり、ドキュメントを見なければならないのは 確かに危険だが、Javaのfinalに相当するものが無いからなぁ。
>>538 ほんとだ。
{boost::shared_ptr<NV> p(new EX);}//~EX~NV
shared_ptrのコンストラクタってメンバtemplateになってるから
指定した型(NV)から推測されるポインタに代入しないで、
実際にコンストラクタに引き渡された型で
削除用の関数オブジェクトも生成しちゃって処理してるのか...。(頭イイ)
だからvirtual付けてない場合は、
{boost::shared_ptr<NV> p(dynamic_cast<NV*>(new EX));}//~NV
としちゃうと意図的にメモリリークを起こせると...
>>539 C++ で継承禁止クラスを作ることは可能だよ。
どやって?
>>543 ええと、これ仮想継承で実現するのか。
デストラクタをvirtualにするよりメモリ食うのではなかろうか。
デストラクタvirtualよりパフォーマンスが良いなら考えるけどな。
>>543 以下のコードでどれだけメモリを食うか調べた。
(VC++2003)
struct A : public nonderivable< A > { int a; };
struct B { virtual ~B(){} int b; };
struct C : public B, public nonderivable< C > {};
int main()
{
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
cout << sizeof(C) << endl;
}
結果は A, B は 8 、C は 12 と出た。
パフォーマンスにはあまり影響はなさそうだけど…、ようわからん。
で、けっきょくいえることは、Policy として使うだけのクラスは、protected なデストラクタにするか、 char_traits などのようにすべてのメンバを static で持つかどちらかにしろということだ。
>>524 STLコンテナの継承にはprivate継承がお薦めですよ.
使うメンバー関数だけusingするといいです.
#include <deque>
using namespace std;
class A: private deque <int>
{
typedef deque <int> Base_;
public:
A (): Base_ () {}
A (const A &p): Base_ (p) {}
A &operator = (const A &p) {if (&p != this) {Base_::operator = (p);} return *this;}
virtual ~A () {}
using Base_::push_back;
};
int main () {
A a0;
a0.push_back (0);
return 0;
}
>>547 usingでそんなことできたんだ。
知らなかった。
>>547 で基底クラスのデストラクタは呼ばれる事が保証されるの?
>>549 よくわからんが、
private継承だから、基底クラスのポインタにすることはできない
>>549 基底クラスのポインタでインスタンスを保持できないんだから
デストラクタは必ず呼ばれると思う。
> virtual ~A () {} ひょっとしてvirtualは不要になる?
>>550 ,551
そういう意図です.
>>552 混乱させたようですが,
デストラクタのvirtualはなくてもOKです.
これがなくても,先祖クラスのデストラクタを呼び忘れるなんてシチュエーションは起き得ないです.
Aをpublic継承する可能性があるなら付けておきましょう.
sed 's/先祖クラス/派生クラス/'
>>543 >ここまでするメリットを感じない。デメリットのほうが大きそうだしね。
「デメリット=無駄にメモリ喰う」って類のことを言ってんなら
デバッグ版の時だけギミックを仕掛けといて
リリース版の時にはギミックを外すようにしとけばいいんじゃない?
STLコンテナにvirtualなデストラクタがないことが心配っていう人は、 struct person { char name[256]; int age; }; こんなやつも同じ理由で心配になるのかな?
557 :
デフォルトの名無しさん :04/06/18 06:56
EffectiveC++に確かこんな記述があったはず。 (若干表現は違ったかもしれない) >基底クラスのポインタを介して派生クラスのオブジェクトを >削除するとき、基底クラスのデストラクタがvirtualでないと >、その結果は不定となる。 >不定とはコンパイラはどんなコードでも好き勝手に生成しても >よいということだ。 この記事を読んでからは 特定のコンパイラで制限付きで動いてても virtualでない場合は(似非)継承は避けることにした。 ポリモフィックな動作を保証できなくなるなら 他のキーワードがあっても良かった気がする。
>>536 微妙にうそついてすまんかった。
>>538 scoped_ptrだとリークするんだねぇ。
scoped_ptrリークする可能性のあるコード書いたこと無かったから知らなかったよ。
560 :
デフォルトの名無しさん :04/06/18 20:07
>>557 基底クラスオブジェクトへのポインタって考え方に固執することないじゃん
テンプレートあるんだし
>>557 そもそも仮想関数が1つも無いクラスのオブジェクトを
ポリモフィックに使わない。というか使えない。
そんなクラスに仮想デストラクタが必要なんだろうか?
他のメンバ関数は仮想で無いのに。
と、ひさびさに小一時間問い詰めたい。
562 :
デフォルトの名無しさん :04/06/18 21:37
あの非常に初歩的なことかも知れません、いいですか? #include <iostream.h> とやるよりも、 #include <iostream> using std::cout; using std::cin; using std::endl; とかってする意義はあるのでしょうか? <iomanip.h>とかも全て<iomanip>でわざわざ using して使われてます。 どなたか知ってる方。
>>563 #include <iostream.h>
はものすごく古い
デストラクタでぐちゃぐちゃうざい。 C#つかえよ。 どーでもいいよそんなもん。臨機応変にやれよ。
古いのは分かるんですが、何かが劣ってるとか <iostream>だけしかできないことがあるとかはないんでしょうか?
568 :
デフォルトの名無しさん :04/06/19 00:49
C#じゃなくても __gc あるもん~。
>>567 劣っているというか、
string.h が困るよね。
古くて規格外というのは、大きな欠点だと思うが。
>>572 >あんまり良く分かりません
「まったく分かりません」だろ?
名前空間について調べてみ
>>573 古いかもしれないけど規格外ではないだろ?
>>575 1998年の時点でdeprecatedなんだから、そろそろアウトにしたいなぁ。
まつまり基本的に古いものは排せってことですね。 良く分かりました。
578 :
デフォルトの名無しさん :04/06/19 01:18
古いiostreamの実装ってよく知らないんだよなー。 2000年からプログラミング始めたから。 std::stringとの連携、たとえば ostream& operator<<(ostram&, const string&); getline(istream&, string&); なんかは、"iostream.h"には存在する保証が無い・・・のかな?
580 :
デフォルトの名無しさん :04/06/19 01:21
これはiostreamそのものとは関係無いか。
つまり、賞味期限きれたものと、きれてないものどっちがいいかというと そらー、食えるとしても新しいほうがいいじゃないかと。
iostream.hって規格内なの? 14882:1998にそんな記述見つけられなかったし、VC7.1に入ってないけど。
いまだかつてiostream.hがC++の規格に存在したことはない
586 :
デフォルトの名無しさん :04/06/19 09:07
ライブラリの作りの良し悪しは、規格化されているか否かとは無関係
規格化されていても問題ある定義体はいくらでもある(例: gets)
>>573 にプと言ったのはマジレスだよ
プ
>>586 実際にそうした定義が山ほどあるとしたところで、
数があるから問題じゃないというわけじゃなし…
えーと、悪い奴はだれだ!
誰が悪いのかは知らんが「規格外」ってことは #include <iostream.h> int main() { cout << "hoge" << endl; return 0; } と #include <iostream> int main() { std::cout << "hoge" << std::endl; return 0; } で同じ結果が得られるって保証がないんだよね?
590 :
デフォルトの名無しさん :04/06/19 15:42
わたくしJava厨なのですが、最近 C++ の勉強をはじめました。 WindowsでもLinuxでも使えて、 フリーで使えて(業務用途不可でもいいです)、 Eclipseライクな操作性の C++ のIDEがあったら教えてください。
>>561 抜け道(非仮想デストラクタを持つ基底ポインタで派生クラスを削除)塞いどくのは,
別に悪いことではないのではないでしょうか.
そのままでは警告なりエラーなりはでないんですし.
ただ561は,確かにそうかもしれないと思った.
立て札たてとかなくても抜け道通る奴はあんまりいないかな.
>>590 知らんけど、EclipseライクがいいんならEclipse自身のC++サポートは駄目なの?
593 :
デフォルトの名無しさん :04/06/19 16:50
>>589 得られる保証も得られない保証もない
ISO/IEC14882が規定しないライブラリは
ISO/IEC14882ではユーザ定義であって
正しいか正しくないかを論じることができない
おまえさんの口ぶりから察するに
言いたそうなことは痛そうだが・・・w
Realメディアファイルを再生するプログラムを書きたいのですが、 フィルタに何を指定したらいいのでしょうか。 ユーザに、作ったソフトに加えて、RealMediaSplitterをインストール してもらい、それのフィルタを使って再生する方法なら分かるのですが、 RealMediaSplitterの代わりに、本家のRealPlayerをインストールしてもらうだけ で、Realメディアファイルを再生できるようになる方法が分かりません。
>>591 派生クラスを作るだろう人の実力によるよな。
初心者に毛が生えたような人だとすると
「どーあっても安全にしたい。効率なんか二の次だ」って
考えてvirtualつけることもあるだろう。
10659氏が言ってくれているように仕掛けを付けとくのも強力。
継承可能かどうかドキュメントに記しておくことも手助けにはなる。
デストラクタprotectedもある。ケースバイケースだな。
>>561 そういわれてみればそうですね。
仮想関数をなくしてデストラクタを非仮想関数にしてしまう
クラス設計もそれはそれでいいのですが、
本来継承するべきでないのか、
あるいはそれを断念せざるを得ない状況を生み出すという見方もないでしょうか?
(使用者側からはPolicyで選択できるのがいいです。)
まぁC++の場合、C#のsealedやJAVAのfinalのように継承を禁止されない分、
自由度が高いという見方もあるのかもしれません。
宗教論争みたいになってきたんでこれくらいでやめにしておきます。w
つきあってくださった方、ありがとうございました。
>>596 > 派生クラスを作るだろう人の実力によるよな。
同意.
私は(未来の自分も含め)派生クラスを作る人(以後,利用者)を信用しないほうですから,
安全性を優先してます.
作成者が利用者をコントロールする手段を提供するのは重要なことだと思います.
(そういう意味では543,555は私的にはヒットでした.)
次の言語規格改定では,この辺をもう少し頑張って欲しいですね.
599 :
デフォルトの名無しさん :04/06/19 20:53
int* abc と int *abc の違いは何なのでしょうか?。*って、読み方なんでしたっけ?。
600 :
デフォルトの名無しさん :04/06/19 21:02
>>599 見た目だけ。
みにくいし
int* a, b;
とかしてはまるからそういう記述はやめとけ。
* = asterisk
* = 菊門
602 :
デフォルトの名無しさん :04/06/19 21:06
規格上違いが無いのですが、実際に出力されるオブジェクトに違いが出ることがあります。 理由はわかりません。
603 :
デフォルトの名無しさん :04/06/19 21:07
base* でdeleteする時点でデストラクタがvirtualかどうかくらい点検しろよ
605 :
デフォルトの名無しさん :04/06/19 21:12
>>604 いろいろ試してみてください。
結構予想と違う振る舞いが多いですよ。
>>603 利用者の点検を言語レベルで強制できればいいんですけどね.
607 :
デフォルトの名無しさん :04/06/19 21:30
ださげんご
はげんご
>>603 「base* でdeleteする」のが利用者でない場合ってのはありえないでしょうか?
極端な例を出すと,
// designer.h
struct Must_Not_Derive {void memfun0 () {} ~Must_Not_Derive () {}};
void func (Must_Not_Derive *p);
// designer.cpp
void func (Must_Not_Derive *p) {delete p; p = new Must_Not_Derive;}
// user.cpp
struct Derived: public Must_Not_Derive {~Derived () {}};
int main () {
Derived *p (new Derived);
func (p);
return 0;
}
で,利用者がdesigner.cppを閲覧できない場合.
設計者は利用者がよもやMust_Not_Deriveを継承するとは考えてない.
一方,利用者はMust_Not_Derive::memfun0を使いたいのだか,
コンポジットあるいはpriavete継承が面倒臭いので,
funcでdeleteされることとは知らずにpublic継承してしまった.
例が極端だけどこういうはまり方はないでしょうか?
612 :
デフォルトの名無しさん :04/06/19 23:04
>>600 int* a, b;
とかしてはまるからそういう記述はやめとけ。
この場合は、aもbも、ポインターになるのですか?それとも、bは整数?。
614 :
デフォルトの名無しさん :04/06/19 23:08
>>610 引数が非constのfuncが何をする関数かを知らずに使うわけか
答えられないなら黙ってていいよ。 レスつけるのは別に義務ってわけじゃないからね。
617 :
デフォルトの名無しさん :04/06/19 23:13
>>612 自助努力をしろ
初心者であろうがベテランであろうが関係ない
これは人間性の問題
スレ荒らして楽しいかい?
619 :
デフォルトの名無しさん :04/06/19 23:18
int* a, b; って書く人はやはり多いんですか? 私は絶対 int* a; int* b; と書きます。
>>620 その前に、
int* a,b;
と
int *a;
int *b;
は意味が違う
622 :
デフォルトの名無しさん :04/06/20 00:11
>>620 a と b が
・同型でなければならないとき
・たまたま同型なだけのとき
で書き方わけてるよ
漏れは int* a; 派だな 型の記述なんだから型の方にくっつけたいよ。 ポインタ宣言は一行に一個。
int * w ;
int * (a,b);
626 :
デフォルトの名無しさん :04/06/20 00:27
>>623 そんなのは伺いをたてること
こっちから押し売りすることじゃない
LPINT
628 :
デフォルトの名無しさん :04/06/20 00:31
>>626 文盲か?
とりあえず馬鹿は引っ込んでてくださいな。
int *a,*b; int *c; でFA
631 :
デフォルトの名無しさん :04/06/20 00:35
>>629 コーディング基準は俺ルールじゃないってことだよ
こうやって不毛なコーディングスタイル論争が始まるんだな
633 :
デフォルトの名無しさん :04/06/20 00:38
>>632 ム板ではなくマ板でやれば
少しは実りがあるはずだ
635 :
デフォルトの名無しさん :04/06/20 00:42
>>634 そういう意図はない
スタイルはプログラム技術じゃない
PGの社会に関することだ
>>621 そうです。
つまり、勘違いや間違いを起こさないように、と言う意味です。
int* p1,*p2; を int* p1,p2; と書き間違えたからって問題になるケースがあるかな? 大抵コンパイルエラーになって、んで訂正して終わりっしょ。
はぁ、またこれか。
640 :
デフォルトの名無しさん :04/06/20 05:26
double ** m_tblに領域をnewしたいのですがどうすればよいですか? まず、 m_tbl = new (double *) [TBLNUM]; //TBLNUM個のdouble*型を割り当て として次に *m_tbl[i]=new (double *) [EACH_TBL_ARRAY];//おのおののm_tbl[i]にEACH_TBL_ARRAY個の配列へのポインタをセット のようにしたいです。 上記だとコンパイルエラーになります。
641 :
デフォルトの名無しさん :04/06/20 05:33
>>640 *m_tblの型はdouble *だろ。
642 :
デフォルトの名無しさん :04/06/20 05:39
そうでした *m_tbl[i]=new double[]ですね。 でもその前にm_tbl=new(double*)[]がエラーってしまうのですが。
あともう一つ。 *m_tbl[i]はm_tbl[i]の間違いだろ? 要するに *m_tbl[i]=new (double *) [EACH_TBL_ARRAY]; ↓ m_tbl[i]=new double[EACH_TBL_ARRAY];
たびたびありがとうございます。 最初の記述は m_tbl = new double* [TBLNUM];としたらOKでした。 もっと勉強します。
>>598 でも、543の仕掛けでエラーになったとして、
派生クラス作る人がヘボだと、ただ悩むだけになってしまったり。
ドキュメントちゃんと書けよってことか。
やっぱりこういうの綺麗にコンパイルエラーにする仕組みは欲しいよな。
これスレのFAQに入れておこう。 int * i; int* i; int *i; どれでも好きなやり方にしろって。
647 :
デフォルトの名無しさん :04/06/20 09:29
>>645 最後の一行を除き激しく同意
小技に凝る前に大きな忘れ物だ
648 :
デフォルトの名無しさん :04/06/20 09:30
>>647 > 小技に凝る前に大きな忘れ物だ
具体的にはどういう意味?
ドキュメントを書くってことだろ。
651 :
デフォルトの名無しさん :04/06/20 13:42
ソースツリーはどうやって決めてますか? なにか良い本やWebがあれば教えて下さい。 これから作るシステム構成は ・いくつかのサブシステムからなる。 ・共通のコマンドユーティリティがある。 です。 lib, src, lib/src ???
C++ スタイルのキャストを使えと良く聞きますが、やっぱり C スタイルより C++ スタイルでキャストした方が良いのでしょうか?
安全性を考えるならC++キャストのほうが良いだろうな。
Cスタイルのキャストを禁止にするようなコンパイルオプションとかあったらいいな。 ってもうある?
655 :
デフォルトの名無しさん :04/06/20 13:56
>>652 const_castやreinterpret_cast, mona(giko, c)はともかく
(char *)0を(char*)(0)と書けという根拠は希薄
>>655 漏れは精神衛生上C++にしてる。
混ざってると気持ち悪い。
>655 static_cast<char *>(0) ( ゚∀゚)アヒャ
659 :
デフォルトの名無しさん :04/06/20 15:06
>>655 (char *)(0)はCスタイルじゃないか?
static_cast<char *>(0)
または
template<typename T> struct id{typedef T type;};
id<char *>::type(0)
かと。
そこでEffective C++ですよ
661 :
デフォルトの名無しさん :04/06/20 15:10
>>658 いいたいことはわかるが
reinterpret_castでないあたりから
耐え難い腐臭が・・・
>>614 利用者のスキルが低い場合にはありえることじゃないでしょうか?
funcは今回は適当に名前を付けましたが,
その中でdeleteしてることを全く連想させない名前である可能性はあるわけです.
これを否定するために,私としても561みたいにこの状況が起こり得ないことを示したいですね.
>>645 ,647
「ドキュメントちゃんと書けよ」ってのには異論の余地は無いですが,
設計者が利用者とコミュニケーションが取れないことを仮定して,
対策を講じておくのはいいことだと思います.
また,利用者が設計者を信用しないことも同様に安全性を高めると思います.
私に反論して下さる方には,利用者と設計者の立場を分けて考える視点が欠落していると思います.
どうでしょうか.(煽ってなんかないですよ.念のため.)
皆さんそれぞれ作ってるものが違うでしょうから一概には言えませんけど,
virtualディストラクタが(ディストラクタに限らなくてもいいですが.)
全体のパフォーマンスに影響与えてる局面って,
結構少なくないですか?
663 :
デフォルトの名無しさん :04/06/20 15:33
>>662 >利用者が設計者を信用しないことも同様に安全性を高めると思います
では、STLもコンパイラもCPUも信用せずに何ができるのか聞こうか。
664 :
デフォルトの名無しさん :04/06/20 15:37
プログラミングができる。
>>659 float(0) はC++タイプ、同様に(char*)(0) もC++タイプ
>>660 reinterpret_cast<char*>(0)
↑間違い
666 :
デフォルトの名無しさん :04/06/20 15:39
背後が壁の席でしか仕事をしない俺だって愛用の道具はあるさ
reinterpret_cast<char*>(0) これって何で間違いなの?
>>663 ここでいう,安全性とは
利用者と設計者の意志疎通がうまく行ってないことに起因する危険に対する安全性です.
そういう意味ではSTLもコンパイラも自前で設計した方が安全ですよ.
ただ,私にはその能力も時間も無いので機能的規模が小さくなっちゃうでしょうけど.
669 :
デフォルトの名無しさん :04/06/20 15:51
>>668 >利用者と設計者の意志疎通がうまく行ってないことに起因する危険に対する安全性です.
ここまではいいが
>そういう意味ではSTLもコンパイラも自前で設計した方が安全ですよ.
なんでそうなるんだよw
おまえさん、プロのコンパイラ屋よりもマシなコンパイラ作れるのか?
>>669 利用者と設計者が同一人物であるほうが利用者と設計者の誤解が少ないと言いたいのです.
> おまえさん、プロのコンパイラ屋よりもマシなコンパイラ作れるのか?
そんなの無理です(笑).
だから「機能的規模が小さくなっちゃう」と書いてるんですよ.
まぁそんなのは最早STLとは呼べないんでしょうが.
>>670 >利用者と設計者が同一人物であるほうが利用者と設計者の誤解が少ないと言いたいのです.
・・・・・・
>>670 大体同じ意見。細かいところに話が行き過ぎてる気がするな。
ライブラリ作成者と利用者という立場で分けて考えると
ライブラリ作成者が課した決まりで利用者を縛りたいのは当然。
今話題になっている継承可能か否かという条件に関しては、それを行う時に
1. もしJavaのfinalのような言語仕様があれば、
利用者にも原因がわかりやすいコンパイルエラーにできる。
2.
>>543 のような仕掛けを用意して、とりあえずコンパイルエラーにする。
3. 継承不可能とドキュメントに書いておく。
4. (別の解法だが)効率無視してデストラクタvirtualで好きに継承させてしまう。
これくらいの選択肢があるぞと。
で、最もスマートなのは1。ドキュメントもほとんどいらないが今のC++では現実的じゃない。
2、3はドキュメント化して、利用者に守らせることが必須になる。
(2の場合は違反して継承した場合のコンパイルエラーを示しておかないと混乱の元)
4をやるかどうかはライブラリ作成者のポリシーによる。
俺は一連の流れからこんなふうに感じた。
>>665 g++3.3ではポインタに関してコンストラクタ記法はCスタイルキャストと全く同じ挙動を取るから、
(char *)(0)がどちらと等価かは実験では判断できない様だ。
従って、実際上どうでも良い事になるな。
文法上はどうなんだろう。
>>672 中点を幾つも書きたいだけなら、いちいち引用とかしなくていいです ;-)
>>673 Great! 私の意見はこの中にまとまってます.
>>547 は潔癖の傾向があって
自分が提供したライブラリを利用した場合、
どんなヘボプログラマが利用者でも可能な限り問題が起きないように
したいと思っているんだろうな。気持ちはよくわかる。
virtualの効率に関して言えば、最近だとケータイアプリの
ゲームなんかを作っている人は気にするんではなかろうか。
こういう環境で汎用的なライブラリを作ろうとすると、
「何でもvirtual付けとけ」とはならないような気がする。
>>673 あぁ,しまった.「private,protected継承」ってのも入れて下さい.
安全性を第一に優先する私としては,
1. Javaのfinalのような言語仕様
2.
>>543 のような仕掛けを用意して、とりあえずコンパイルエラーにする。
3. private,protected継承を検討する.
4. 効率無視してデストラクタvirtualで好きに継承させてしまう。
5. 継承不可能とドキュメントに書いておく。
の順でしょうか.
デストラクタがvirtualでないクラスを継承したら警告するコンパイラってないの?
>>678 よく考えると,「private,protected継承」するのは利用者で,
他の項目は設計者ですね.
すみません.
>>678 俺の見た感じこの話にはいくつか段階があって
Q. ヘボ利用者にポリモーフィズム周りで安全なライブラリを提供するには?
A1. デストラクタproteccted
A2. デストラクタvirtual
A3. 継承禁止
A3-1. Javaのfinalのような言語仕様
A3-2.
>>543 のような仕掛けを用意して、とりあえずコンパイルエラーにする。
A3-3. 継承不可能とドキュメントに書いておく。
のような形だろうか。
> 3. private,protected継承を検討する.
これはライブラリ作成者側から縛れないので疑問符。
>>673 で 4に関して別の解法と記したのはA3の実現方法を論じているのに
それより上位の解法を出すのは反則かなと考えていた。
C++な人はdelphiを馬鹿にしますがdelphi->c++ と移る人は多いと思われます。 つまり、c++の練習用ともなっているわけで 妨害する理由がいまひとつわかりません。
突然、何の脈絡もなくそんなこと言うヤツの精神構造がいまひとつわかりません。
>>679 g++だと,
-Wnon-virtual-dtor 非仮想デストラクタについて警告する
ってのがあるけど,なんだか効いていないようです.
あと,
-Weffc++ Effective C++ 式の指針からはずれるものについて警告する
ってのがあって,これはbase class `class Hoge' has a non-virtual destructor
と警告してくれます.
>>547 話し続けてくれてありがとう。この話題はすごく楽しめた。
>>543 のような手法を知るきっかけにもなったし。では撤収。
喧嘩するなおまいら仲良くしろ(´☻ω☻`)
689 :
デフォルトの名無しさん :04/06/20 20:42
Λ_Λ \\
( ・∀・) | | ガッ
と ) | |
Y /ノ 人
/ ) < >__Λ∩
_/し' //. V`Д´)/
>>688 (_フ彡 /
s/ヌルポ/空ポ/
690 :
デフォルトの名無しさん :04/06/21 00:07
g++って、using namespace stdなしでcout使っても怒られない。 -Wall使ってもだめ。 どうすれば、ちゃんと怒られるようになるの?
>688 ダウト。 5.2.10-8 に明示的に書いてあるべ。 | 8 The null pointer value (4.10) is converted to the null pointer value of the destination type. 従って、reinterpret_cast<char*>(0) は char* 型のヌルポインタになる。 後、reinterpret_cast による変換は実装定義だからビットパターンが同じになるとは限らない。 サイズが十分なら「戻したとき」に同じになるだけ(5.2.10-5)。
>>690 間違って iosteram.h をインクルードしてない?
693 :
デフォルトの名無しさん :04/06/21 00:14
>>692 そんな奇妙な名前のものはインクルードしていません。
まずこんな関数が有るとして bool Foo(){ return false; } でこの時、 main(){ int a = 0; bool b = true; if (a == 0 && b || Foo()) // A a = 1; if (a == 0 && b || Foo()) // B a = 1; } と言う事をするとAではFoo()は呼ばれません。 これはbがtrueだからFooを実行しなくともifは真になる為、呼ばれないのは解ります。 しかしBではFoo()が呼ばれてしまいます。 漏れ的考えではa=1になってる為に最初のa == 0で偽になり、その後の条件は実行されないと思っていましたが・・・。 これは一体何故でしょう? なお、コンパイラはVC++6.0です。
('A`)<ヒロシです…
>>696 B のほうは
if (偽 && 偽 || Foo()) // B
なんだから、
if (偽 || Foo()) // B
と同値で、まだ Foo() によって真になる可能性がある。
>a=1になってる為に最初のa == 0で偽になり、その後の条件は実行されないと思っていましたが・・・。 左辺で偽になってるために、右辺が実行されるのでは....
おっと間違い、最初のは if (偽 && 真 || Foo()) // B ね。結論は変わらんが。
>>696 &&と || の優先順位の仕様を確認しよう。
MSDNだと、「優先順位と評価順序」という項目があるはずです。
初心者ほどわざと難しく書いて自分を混乱させるのが得意だからなぁ。
「難解な書き方するのがプロ」とかは、思わない方がいい。
素直に括弧つけてれば避けられるようなヒューマンエラーは自力で避けよう。
>>691 ごめん。調べてみたら、まだ結論が出てない話みたい。
ttp://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#463 漏れの意見は"SUGGESTED RESOLUTION"と同じく、
reinterpret_cast<T*>(0)は実装定義の変換であるべきだと思う。
そして、null pointer(これならガッてされない?)を取得する方法として
reinterpret_cast<T*>(0)としない理由を、「間違い」ではなくて
「static_cast<T*>(0)のほうが良い」と訂正しておく。
あと、
s/値0のビットパターンによる/値0から実装定義の変換によって得られる/
これでいいかな?
s/ってなんでつか(´・ω・`)
ヒューマンエラーのリスクを極力減らしてこそ、プロだ罠。 ポインタだろうが配列だろうが、パフォーマンスはそんなに変わらんし、 無闇にポインタ使うのは最初のうちだけに汁。 かといって無闇に関数に参照渡しするのはマズイけど。
>>704 swap(文字列置換)
viエディタやPerl言語などで用いる有名な正規表現
>>704 sedスクリプトの置換コマンド。たぶんsubstituteの略。
>>706 ありがとう(´・∀・`)
ぐぐっても出てこなかたーYO!
>>707 同じくサンクスコ(・∀・)
なんかのスイッチかと思いまつた
あ、そうか、||の方を括弧で括らなきゃ駄目でしたね。 アホだ、俺。あまりに初歩過ぎて気が付かなかった。 つか、今までコレよくまともに動いてたな。 たまたまデバッグで発見したんだけど。
>>710 自分のソースなら間違いと気付けるけど、
他人のソースだった場合は、間違いなのか意図的なものなのか、
分からない事が多い。
あるなあ、それ。 しみじみ。
714 :
デフォルトの名無しさん :04/06/21 06:18
>>690 歴史的な事情により、そういうバージョンも残っている
STLも初期のバージョンではstdで囲われていなかった
715 :
デフォルトの名無しさん :04/06/21 06:20
>>702 そーゆーことを言いながら
素直に憶えれば避けられるようなヒューマンエラーは放置か
他PGの文法理解度に依存した(もしくは、甘えた)記述を
避けてこそ堅牢な開発が可能。
「素直に憶えれば避けられる」とか、気合とか、修行とか、
精神論まがいな言動をカマす人間は、
一生、独りでソース管理やってればいいだけのこと。
先入観が大きいほどに見逃す危険も大きくなるという
人間の心理を理解できない、
>>715 が実に憐れだ。
ぶっちゃけ、「自分以外のPGはアホだから配慮してやる」でも構わん。
718 :
デフォルトの名無しさん :04/06/21 09:09
ポインタとオーバーロードと標準変換のからみってどう思う? char* c; fc(c); の呼び出しって、void fc(char*)が存在しない場合、 だいたい次の順で呼び出されるのが決まる。 1.fc(char*) or fc(char* const) 2.fc(const char*) or fc(const char* const) 3.fc(volatile char*) or fc(volatile char* const) 4.fc(const volatile char*) or fc(const volatile char* const) 5.fc(void*) or fc(void* const) 6.fc(const void*) or fc(const void* const) 7.fc(volatile void*) or fc(volatile void* const) 8.fc(const volatile void*) or fc(const volatile void* const) 9.fc(bool) or fc(const bool) or fc(volatile bool) or fc(const volatile bool)
>>718 > fc(char*) or fc(char* const)
これ、オーバーロードじゃないよ。同じ関数。
>>718 > fc(bool) or fc(const bool) or fc(volatile bool) or fc(const volatile bool)
これも全部同じだな。
fc(char*) or fc(char[]) これも同じだな。
>>681 Java や C# じゃないんだから、非ポインタで普通に(ポリモじゃなく)クラスとして便利に使える
場面も多々あるわけで、ポリフォできないから継承ダメ、っていうのは方向性として漏れはすきじゃないなー。
派生クラスから基底クラスへのポインタに変換するトコがあればエラーなり警告なり出してくれる程度でいいや。
連想配列を使おうと boost を導入したのですが、 連想配列を扱う関数名が分かりません。 知ってる方がいれば教えてほしいのですが。
>>723 連想配列なら標準のstd::mapがお勧め。
ちなみにboostのProperty Mapはmapっぽいものに対する
共通のインターフェースであって、連想配列そのものではない。
725 :
デフォルトの名無しさん :04/06/21 18:15
【教えてください】 いま、C++でカウンターCGIを作ってるんですが、 更新を押してもカウントしなようにするには なにを使えばいいのですか? なにかヒントになりそうなページとかあったら教えてください。
>>719-721 フォローどうもです。
fc(char*) = fc(char[]) = fc(char* const)
fc(const char*) = fc(const char[]) = fc(char const*)
ですね。
後から関数が加わったときに呼び出し先が変わると困る場合は
標準変換に頼って関数を呼びださないで
きっちりキャストしとかないとまずいってことなのかな。
>後から関数が加わったときに呼び出し先が変わると困る場合は こういう場合はオーバーロードしない方がいいんじゃないか?
delete [] a, b; とした場合ってaもbも配列扱いのdeleteになるのでしょうか? それとも int *a, b; みたいになっちゃうのでしょうか?
730 :
デフォルトの名無しさん :04/06/21 19:59
>>716 甘ったれはそっちだろ
規格票を読んでない人がそのことの正当性を強弁する姿は
マニュアルを読んでないユーザが直情で当たり散らす姿とそっくりだ
無知そのものに罪はないが、居直りが加われば間違いなく足手まとい
初心者には厳しさの中に優しさを持って接するが
周囲の足をひっぱるお荷物は叩き出すのが唯一の正当防衛
自分の仕事に関わる規格に精通しようと勉強する人の
やる気をくじくような毒電波をまき散らすな
あんた1人の甘ったれじゃ済まされない威力業務妨害なんだよ
先輩から吹き込まれたならアフォの伝統は浄化しろ
731 :
デフォルトの名無しさん :04/06/21 20:05
質問があります。(next = NULL)っていうのが あるサイトのプログラムにあるのですが、 NULLって一体なんでしょうか? 文字でもないみたいだし。 教えてください。お願いします。
>>731 0に展開されるマクロ。
ポインタに変換される事を意図していると表明するために使われる事がある。
>>729 delete [] a; b;
となる
734 :
デフォルトの名無しさん :04/06/21 20:24
735 :
デフォルトの名無しさん :04/06/21 20:25
えっと、あのC++を始めたばかりで、 マクロとかよくわからないのですが・・・ もう少し簡単に説明するとどういう事なんでしょうか? お手数ですが、お願いします
736 :
デフォルトの名無しさん :04/06/21 20:27
電車ガール
>>735 そのレベルの質問だと初心者スレのほうがいいでしょ。
ただし、そっちでも「自分で調べろ」「入門書嫁」で終わる
可能性が高いですが。
>>730 >周囲の足をひっぱるお荷物は叩き出すのが唯一の正当防衛
「言うは易し、行うは難し」だよ。
ネットで怪気炎あげるのは構わんが実際に叩き出すにしても、
そのための労力・時間も馬鹿にならん。
むしろ、甘ったれてるのは君だろ?
>自分の仕事に関わる規格に精通しようと勉強する人のやる気をくじく
そのくらいで挫けるならさっさと挫けてしまえばいい。
職人的な聖域を徹底排除することがPMにとって重要。
よし! 730は740に返答するんだろうけど、 言いたいこと全部書いたら敬語に変換して送信してみよう。
742 :
デフォルトの名無しさん :04/06/21 22:56
>>740 >「言うは易し、行うは難し」だよ。
行えない香具師からのインカムでおまんま食えてるわけだがw
職人やりたくない奴の侵入社員が何物よりも迷惑なんだよ
や る 気 ね ー や つ は 出 て け
どこの職場にも通じる鉄則だ
またスレ違いの話題で盛り上がる 頭の可笑しい方々がいらっしゃいますねw
「言語の規格」と、「人間にとって理解しやすい規格」はイコールじゃない。 C/C++も例外でなく、C/C++である規格が定義されているからといって その規格を無理に使う必要はない。 あえて思い切って、高度で煩雑な規格の使用を制限して、 多数派PGの理解レベルを優先したとしても、 決して資源の無駄にはならないだろう。
>>742 人事にかかわったことがない万年下っ端は楽でいいな。
>>742 の職場は、職人的な高い技術が求められているにも関わらず、
新入社員がスタッフとして送り込まれてくるらしい。可哀相に(w
大した仕事でもないのに職人気取るヤシって邪魔だよな。
747 :
デフォルトの名無しさん :04/06/21 23:07
>>744 無能PGの理解レベルを優先して何の勝負をしてるんだ、おまえんとこわw
投稿者について言及してもヒートアップするだけで実りはないですよ.
「人妻にかかわったことがない…」と語読。 もえ。
どっちの主張もうなずけるんだがな。 不特定の人と関わる仕事をしているのであれば これからメンテするかもしれないヘボプログラマのためにわかりやすい 書き方をしてやれる能力も必要だし、素人にはぱっと見紛らわしいような 仕様を理解しておく能力も必要でしょ。 そんな一方的な見方ばかりしてないで仲良くしてくれよ。
あえて思い切って、高度で煩雑な規格の使用を制限して、 HSPを使用し、多数派PGの理解レベルを優先したとしても、 決して資源の無駄にはならないだろう。
752 :
デフォルトの名無しさん :04/06/21 23:15
>>751 規格票が理解できねって? ああ、そりゃお気の毒に・・・
だったらわざわざここに来る必要は無い。 のぞいて荒らしてることろを見ると、少しはやってみたいんだろ。 だったら大人しく教えて下さいといいなさい。
>>752 ネタにマジ煽りされても困るなぁ。
なんつーかさぁ、もうちょっと心に余裕持てよ。
でもさ、いまどき C++ で能無しがこなせる業務あるかな。 ドライバ書きとかゲーム書きとか、あんまヘボだと言語がどうとかいう以前に業務が難しい領域が多くない? ・・・・とオモタけど携帯のソフトがあったか・・・
3日前からずっとやってない?
>>753 大人しく教えて下さい
で、何を教えてくれるの?そもそもお前はどのレスに言ってるの?
C++やると性格が歪むって本当らしいですね?
>>759 あるひとつの問題に対してアプローチがいくつもあり、
それらひとつひとつが曲者だからね。
追いかけるのに疲れ果てて性格が歪むのも無理はない。
これは、C/C++をマスターしていると思っている人間ほど顕著である。
いちいち他人のコードを自分流に修正せずには
いられない脅迫観念にとりつかれているからだ。合掌。
>>759 規格票が理解できねって? ああ、そりゃお気の毒に・・・
>>760 ひとつしかない方が異常だとおもうけど。
763 :
デフォルトの名無しさん :04/06/21 23:42
よっぽど悔しかったらしいなw
>>742 は、問題が起きたら俺が泥をかぶればいいという気質の人間だろう。
さもなくば、事情を知らない煽りか?
前者であれば、口は悪いが心の熱い人間であるといえよう。
実際問題、無能PGが配置されてしまったとして、
そのフォローに奔走するのは結局
>>742 自身だからである。
>>740 は、意外と冷酷な人間だろう。
途上国の安価PGに下請け発注することを専らとしているに違いない。
742も740も俺の自演ですが何か?
>>725 私は直前のIPを保持して同値ならカウントアップしないようにしています。
クッキーは好きじゃない。
自分自身が参照したときもカウントアップしないようにするといいかも。
こっちは自分なのでクッキーでもいいかな。
それよりもC++でCGI作らせてくれることがうらまやしい。
SAKURAはC止まりなので。
delete [] a, b; とした場合ってaもbも配列扱いのdeleteになるのでしょうか?
>>768 >>733 delete a,b; とし、a,bをクラスにして、
bのデストラクタが呼ばれない事を確認してみろ。
770 :
デフォルトの名無しさん :04/06/22 20:03
delete [] (a,b)としたところで何の問題の解決にもならん気がするが。
772 :
デフォルトの名無しさん :04/06/22 20:24
>>771 768は何かの「解決」を求めているか?
deleteといえば、プログラムが終了になるときは、 特にdeleteで解放しなかった領域も解放されるんですよね? プログラムが終わった後まで影響しないですよね?
774 :
デフォルトの名無しさん :04/06/22 21:47
>>773 絶対されるとも言えないし、絶対されないとも言えない
処理系によってはやばいってことですか? プログラムの終わらせ方としては 普通にmainのreturnで終わる場合やexit()やabort()。 main終わるときにローカルオブジェクトはデストラクタ 呼ばれるんですよねぇ。 exit()を呼ぶと、後処理やってくれるようですが スタックの巻き戻ししないんで、ローカルオブジェクト はもれるって話みたいで、例外使うなりしてちゃんと deleteしたほうがいいんですかね、というかみなさんは そうしますか?
777 :
デフォルトの名無しさん :04/06/22 22:01
>>776 >後処理やってくれるようですが
このへん全然ダメ
ちゃんと調べろ
>>773 OS依存。まぁ、普通はプログラム終了時に
リソースは全て回収される罠。
>>773 メモリに関して言えば、多くのOSや環境でその通り。
デストラクタは走らないので、例えばテンポラリファイルを作るクラスなど開放時に
処理が必要なオブジェクトはちゃんと delete する必要がある。
780 :
デフォルトの名無しさん :04/06/22 22:03
>>778 >OS依存。まぁ、普通はプログラム終了時に
このへん全然ダメ
ちゃんと調べろ
>>776 デストラクタを動作させる必要があるなら、ちゃんと delete する。
「~ほうがいい」とか言うより、仕様や期待する動作の通りに動くように
プログラムを書けばいいだけだと思うけど。
exitは単に静的オブジェの破棄、バッファフラッシュ、クローズ処理を 行う。atexitで登録した関数も呼ぶ。
783 :
デフォルトの名無しさん :04/06/23 00:35
どなたか CINT
ttp://root.cern.ch/root/Cint.html の日本語でのマトモな解説サイトとか御存知だったら教えて下さい。
google先生にお伺いしても大したサイトは引っかからないし、
本は絶版になっちゃってるみたいだし。
このソフトすごいと思うんですけど、マイナーなんですかね。
C++インタープリターってここにいる人達なんかにとってはちょっとしたスク
リプト感覚でC++が使えて非常に便利だと思うのですが。
日本人の作者がいるからメールしてみたら? どこかで聞いたことがある名前だったと思う。
>>784 そこ行ったらspybotが喚き出した。
787 :
デフォルトの名無しさん :04/06/23 11:09
ご教授お願いします。 VC++6でUnicodeです。 LPTSTR szHoge = new TCHAR(MAX_PATH); ZeroMemory( szHoge, MAX_PATH * sizeof(TCHAR) ); int nRtn = (GetDlgItem( IDC_EDIT_HOGE ))->GetWindowText( szHoge, MAX_PATH * sizeof(TCHAR) ); LPTSTR lpTgzPath = new TCHAR( nRtn + 1 ); ZeroMemory(lpTgzPath, (nRtn + 1)* sizeof(TCHAR) ); CopyMemory( lpTgzPath, szHoge, nRtn * sizeof(TCHAR) ); delete szHoge; IDC_EDIT_HOGEのコントロールから取得した文字列をlpTgzPathにコピーするんですが、 delete szHoge; にて例外が発生します。 何がいけないんでしょう・・・? 宜しくお願いいたします。
LPTSTR szHoge = new TCHAR(MAX_PATH); delete szHoge; ↓ LPTSTR szHoge = new TCHAR[MAX_PATH]; delete [] szHoge;
>>767 サンクスです。
その方法でやってみます。
790 :
デフォルトの名無しさん :04/06/23 11:53
>>788 グハ orz
サンクス。もう仕事辞めます。
>>787 誤:LPTSTR szHoge = new TCHAR(MAX_PATH); // 値MAX_PATHで初期化された 1 つの TCHAR を newする
誤:LPTSTR lpTgzPath = new TCHAR( nRtn + 1 ); // 値nRtn+1で初期化された 1 つの TCHAR を newする
正:LPTSTR szHoge = new TCHAR[MAX_PATH]; // MAX_PATH個のTCHARの配列をnewする
正:LPTSTR lpTgzPath = new TCHAR[ nRtn + 1]; // nRtn+1個のTCHARの配列をnewする
だら~っとで良いので、もういっぺん C++ の本とか読み直しておいた方が余計な苦労せずに済むかも。
あと、szHoge みたいなのはいちいち new しないで、ローカル変数の方が良いと思う。
っていうか、スマートポインタ使えよ
なんでもスマートポインタを使えばいいわけじゃないし、この処理では明らかに不要だろ。
この処理とやらの外側でWin32構造化例外を拾っている可能性はあるからスマートポインタが不要とはいえんな。
>>787 GetWindowTextやCopyMemoryで中身は上書きされるんだからZeroMemoryはいらない
テキストの長さだったらGetWindowTextLengthでわかる
int nSize = (GetDlgItem( IDC_EDIT_HOGE ))->GetWindowTextLength();
LPTSTR szHoge = new TCHAR(nSize);
(GetDlgItem( IDC_EDIT_HOGE ))->GetWindowText(szHoge, nSize);
>>794 deleteミスるぐらいならスマートポインタ使えってことだよ。
っていうか今どきnewとかつかわんよ
スマートポインタ使えとだけ言っても何の疑問も解決しねえだろカス
>>797 >っていうか今どきnewとかつかわんよ
はいはい、脳内「今どき」はあんたの頭の中だけにしときな( ´,_ゝ`)プッ
800 :
デフォルトの名無しさん :04/06/23 14:22
素で質問です。 new以外に何使えばいいんでしょうか?
801 :
デフォルトの名無しさん :04/06/23 14:23
前もって全部staticで宣言しておけばいい。 リソースの量を把握できなくていったい何の為のC++プログラマか。
動的に増やさなくちゃいけないから new があるんじゃ
またC厨が暴れているのか。
mallocで十分
ただ騒ぎたい奴が8割
ポインタの参照 *& ってどんな意味があるのでしょうか? 例えば、void func( char **& ) に参照つけるのはどうしてですか?
>>808 void func( char **&p)
だとしたら、funcでpをいじるんじゃないですか?
*pではなく、**pでもなく。
>>808 普通の参照と同じだが?
void func(char *&rp)
{
static char c = 'd';
rp = &c;
}
char *p;
func(p);
811 :
デフォルトの名無しさん :04/06/23 17:44
ダイアログ上のフォーカスをTABで移動していって、ボタンにフォーカスが来ると 点線と黒い影が出ると思うんですけど、 そこからSetFocusでフォーカスを別のとこに移動させると 点線だけ移動して、黒い影がボタンに残ったままになってしまいます。 この黒い影を強制的に消すにはどうしたらいいでしょう?
>>811 キミはそれをC++の話題だと思うのか?
813 :
デフォルトの名無しさん :04/06/23 17:51
>>812 VC++やらMFCの話をここでしてはいけないのですか?
・::std::vector< TCHAR > を使う。 ・ATL ないし、MFC を使っているならば、CStringT< TCHAR > を使って、 あらかじめサイズをしてした後で、GetBuffer() ・_bstr_t を使って、SysAllocStringByteLen を使い、領域確保してから、 GetBSTR() でバッファ取得。だが、この方法はオススメしない。
815 :
デフォルトの名無しさん :04/06/23 17:52
あ、VCのスレがあるんですね。失礼しました。
ポインタと参照ってほとんど同じものだと思ってました…orz
>>811 Microsoft の Windows の話だと仮定して返事してみる。
黒い影は「デフォルトボタン」の印で、フォーカスとは必ずしも関係ない。
あとはWin32 API スレで続けた方がいいよ。C++ と関係ないし。
>>813 811 はおそらく Windows の UI の仕様に関する質問で、別に MFC も VC++ も関係ないみたいだけど・・・
ん~、以下のrfuncとpfuncの違いは何なのでしょうか? それと、rfunc( aaa ) と記述できない事と何か関係ありますか? #include <iostream> void rfunc( char *& rp ) { rp[0] = 'a'; } void pfunc( char * pp ) { pp[0] = 'b'; } int main( int argc, char **argv ) { char aaa[100]; char *bbb; bbb = aaa; rfunc( bbb ); std::cout << aaa[0] << std::endl; pfunc( bbb ); std::cout << aaa[0] << std::endl; return 0; }
>>820 リファレンスを取る時は実体が必要。aaaは単なるポインタに変換され、それは
実体がない(変数に入っていない)のでリファレンスを取ることはできない。
無理に取ろうとすると一時変数が作られる。
>>820 rfuncもpfuncも引数(この例ではそれぞれrpとpp)に対して操作を行っていないので、
違いが大きく現れない。
rfuncでは、例えばrp = 0;とすると、これがmainのbbbに反映される。
pfuncではこれは起こらない。
このあたりはポインタとの絡みは関係なく参照という物の性質なので、
参照渡しについて復習してみる事をお勧めする。
rfunc(aaa)と書けないのは、aaaがポインタ変数でないから。(ポインタに変換可能であるに過ぎない)
ポインタのリファレンスはむしろこっちの使い方の方が多いな。&pとして呼び出す 手間を省く。 #include <iostream> void rfunc(char*& rp) { rp[0] = 'a'; } void pfunc(char** pp) { (*pp)[0] = 'b'; } int main() { char a[] = "abc"; char* p = a; pfunc(&p); std::cout << *p << std::endl; rfunc(p); std::cout << *p << std::endl; }
関数の中で引数に対してnewとかしちゃうと、 pfuncの引数のとり方では悲惨なことになりますね。 (まぁそういうことはあまりやらないけど)
ていうかね void func(T&) と void func(T) の違いなんよ。ポインタとか関係ないんよ。
>>826 わかってるけどその説明じゃ分からない香具師がいるんだよ。頭の固い香具師が。
>>827 >頭の固い香具師が。
下らん質問にしか回答できない半端もんのくせに、
初心者に対してはびっくりするほど態度でかいな。お前。
>>828 >下らん質問にしか回答できない半端もんのくせに、
どうやって俺が下らん質問にしか回答してないとわかるんだ?エスパーか?
830 :
デフォルトの名無しさん :04/06/23 21:35
s/しか/も/
831 :
デフォルトの名無しさん :04/06/23 21:41
C++(プログラム)が早く身に付く方法はないですか?
検索エンジンとかで出てくる%83%82%83E%83_%83%81%83%7Cとかいったコードを デコードする良いアルゴリズムって無いですかね? 自分で作った奴じゃ遅くって。
>>829 恐らくエスパーではなく「こわがり」なのでしょう ;-)
>>831 プリンタで大きく「C++」と印刷した紙を糊で体に貼り付けろ。
836 :
デフォルトの名無しさん :04/06/23 22:11
>>831 パイロットに早くなれる方法はないかというのと同じくらい果てしない質問だ
837 :
デフォルトの名無しさん :04/06/23 22:11
給料はパイロットの5分の1くらいしか貰えんが
パイロットって月給手取り300万近いのか?
もらう奴はそれ以上。
840 :
デフォルトの名無しさん :04/06/23 22:32
Cからのステップアップに最も適した本は何ですか?
842 :
デフォルトの名無しさん :04/06/23 22:40
char *pp で ppは、*bbbのアドレスのコピーが入った入れ物で、 char *& rp はbbbその物自体と理解しました。
845 :
デフォルトの名無しさん :04/06/24 01:38
コンストラクタの初期化リストで配列を初期化することはできるの? やりたいことは、エラーでるけどこんな感じ。 class A { public: string s[]; A(): s[0]("0"),s[1]("1") {} };
誰かお知恵は有りませんか、、、 文字で変換で調べてるけど見つからず・・・。
>>847 JavaScriptなら変換関数あるから簡単だよ。
C++なら自分で作ればいいし。アルゴリズムも何も、先頭から順に見て%見つけたら変換するだけだしね。
>>848 いや、出来るというか出来てるんですが結構遅くて。
こういうものは結構昔から使われているだろうから
何か良いアルゴリズムは無いかなぁと思う次第です。
>>848 相手にすんな。
「自作だと遅い」とか言ってるが、C言語で遅く作る方が難しい。
本当は作ってもいないのに知恵を拝借したいだけだろう。
あるいは過去ログコピペ荒しかもしれない。
自作コードのパフォーマンスについて評価する術を知る者が、 この程度のアルゴリズムでつまづくはずがない。 よって、釣り確定。
>>849 その遅いコードとやらはどうせ8,9行だろ貼って見せろ。
851=852=853
これです。もっと良い方法あると思うんですけどね。 BOOL URLdecode(char *in, char* out) { char hex[3] = { 0 }; char *p; while (*in) { if (*in != '%') *out = *in; else { ++in; p = in; if (*p >= '0' && *p <= '9' || *p >= 'a' && *p <= 'f' || *p >= 'A' && *p <= 'Z') { hex[0] = *p; ++p; if (*p >= '0' && *p <= '9' || *p >= 'a' && *p <= 'f' || *p >= 'A' && *p <= 'Z') { hex[1] = *p; *out = strtol(hex, &p, 16); ++in; } } else return FALSE; } ++in; ++out; } *out = '\0'; return TRUE; }
url エンコード define でぐぐれ
url エンコード include のほうがよいかも
デコードだった
なんだ、真性だったか。
>>832 何と比較して遅いのかが知りたいところだな。
>>855 URLdecode って名前つけてるな
それで検索しなかったのか?
Cから始めて15年、strtol() なんて使ってるプログラムは初めて見た。 確かに遅そうなコードで、しかもバグがあるね。
>>856 幾つか見て見ましたが定石みたいな物は無いみたいですね。
それでも自分の作ったやつよりは速そうなのでそれを使ってみることにします。
てか、URLdecodeで調べれば一発だったんだ。
文字変換で調べまくってたのはあほだった。。。
関数名に同じの使ってるのもあるし、、、orz
>>855 ifの比較は遅すぎ。テーブル検索するように変更。
strtolは遅すぎ。自前で書き換え。
テーブル検索って何だ?
>>864 isdigit()などの実装しらんのか?
BOOL URLdecode(const char *in, char* out) { char hex[3] = { 0 }; int i = 0, j = 0; while (in[i]) { if (in[i] != '%') out[j++] = in[i++]; else { if ( isxdigit(in[i+1]) && isxdigit(in[i+2])) { hex[0] = in[i+1]; hex[1] = in[i+2]; out[j++] = strtol(hex, 0, 16); i += 3; } else { out[j++] = in[i++]; out[j++] = in[i++]; } } } out[j] = '\0'; return TRUE; } ほれ。ってもういいのか。
C++と関係ないじゃん。Cスレに逝ってくれよ! 夏厨の季節には少し早いはずなんだが。
>>865 isdigit()などの実装がひとつだとでも言うのか?
>>865 ひょっとして、char型の256個配列を用意するとか?
const char codetbl[] = "0123456789ABCDEF";
>>872 ( ´,_ゝ`)プッ
嘘つきはお前だよ
そんなの、CPUとメモリやキャッシュ速度によって如何様にも変わるから MSDNも872も正しくない
>>873 そんなの何の意味も無い。
VC6のランタイムだと、
#define isdigit(_c) (MB_CUR_MAX > 1 ? _isctype(_c,_DIGIT) : _pctype[_c] & _DIGIT)
こんな実装になってる。_isctypeもまたシンプルでない実装になってるし。
>>874 いいから試せ。
漏れは、GCCとVC6で逆転を確認している。VC7は試してない。
>>877 だから試してから書いてんだよ。激遅。CPUの違いぐらいで吸収できる差とは
思えん。
相変わらず、C++の領分から外れたり、話題の程度が低くなったりすると 俄然盛り上がるな。
低レベルな争い
関数内で宣言した変数ってスコープの関係で、関数から出ると使えなくなるんでしょ? その変数を返り値にした場合、呼び出し元で使っても大丈夫なの? 呼び出し元で返り値をすぐに変数に代入すれば安全が保証される? スコープなぞ
>>878 ちゃんとinline関数とかマクロにしたか?
漏れの環境だと、isdigit():自作コード=5:1だぞ(VC6)。
>>883 それぐらいちゃんとしてるっつーに。しつこいな。
>>884 俺がどのスレのどのレスで煽ってるかはどこにも書いてないのだが・・・・
またエスパーか?
>>878 コンパイル環境と所要時間の比ぐらい示したらどうか?
劇遅でも数値ぐらい示せるだろ。
こまかいけど訂正 isdigit()じゃなくて、isalpha()
>>881 ダメ。すぐもなにも元よりスコープ外の物に保障はない。
class cTemp{ ……… } class cAdv : public cTemp{ ……… } という感じでクラスを宣言して cTemp *Test = new cAdv(); delete Test; ↑のコードを実行するとcAdvのデストラクタは実行されないみたいなんですが、 まちがっていますか?継承元ポインタのポインタをdeleteすると 継承元のデストラクタしか実行されないのかっていうことなんですが
また、virtualに戻るのか…
>>889 isa1>isa2=isalpha
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
const int alpha = 1;
int table[256];
maketable()
{ int i;
for (i = 'A'; i <= 'Z'; i++) table[i] |= alpha;
for (i = 'a'; i <= 'z'; i++) table[i] |= alpha;
}
int isa1(int c)
{ return table[c] & alpha; }
int isa2(int c)
{ return ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')); }
int measure(int(*f)(int), int times)
{ char s[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
int i, j, t = clock();
for (i = 0; i < times; i++) for (j = 0; j < sizeof(s) - 1; j++) assert( f(s[j]) );
return clock() - t;
}
main()
{ maketable();
printf("%dms.\n%dms.\n%dms.\n", measure(isa1, 1000000), measure(isa2, 1000000), measure(isalpha, 1000000));
}
>>880 >低レベルな争い
そうだ。
低レベルで、かつ、ループの中で何千・何万回も行うかもしれない重要な処理だ。
スレ違いなのは認めるが、if構文や自作コードが遅いかどうかは極めて重要だろ?
>>895 センスが無いのか読解力がないのか微妙な1~2行目はともかく、
> スレ違いなのは認めるが
わかっているようなので終了ですね ;-)
>>894 は、
>>878 .
>>885 とは別人かな?
inline関数やマクロを使ってないみたいだし。
それはそうと、
>>894 のコードを自環境(VC6)でやってみた。
(一部コンパイルが通らない部分やassert()除外などの修正した。)
297ms.
360ms.
343ms.
自環境ではテーブル検索型が最も速かった(isa2>isalpha>isa1)。
述語関数的な用途だと確かに標準ライブラリ関数が威力を発揮する。
自分が
>>883 で使ったソースでも非インライン・非マクロの場合、
標準のisalpha()に惜敗だった。差は5~10%ほど。
いずれにせよ、
>>878 が触れたような【CPUの違いぐらいで吸収できない格差】が得られなかった。
>>878 の劇遅に関するレポートが見たいところだな。
VC6なら-Ob2かな、これでインライン展開されたはず。 isa1 140ms isa2 190ms isalpha 670ms くらいになった
>>898 なぬ?
関数アドレス渡しでもinline処理が使えるとは知らなかった。・・・orz
0ms.
0ms.
265ms.
・・・アレ?スマソ。ソース修正の仕方が悪く余計な最適化されてしまってたみたい。
そんなわけで余計な最適化されないように修正した。
~最終結果~
●非インライン・非マクロ(Ob2なし)
281ms.
375ms.
359ms.
>>897 とほとんど同じ。
●インライン(Ob2あり)
78ms.
141ms.
500ms.
これも、テーブル検索型が最速だ。
興味深いのは、Ob2指定でisalpha()がかえって遅くなっているところだ。 不思議だが、この辺はコンパイラ依存が強そうだ。 VC7やgccでまた違った結果になる悪寒。
cygwin + gcc3.4.0 (-O3)だとこうなった。 453ms. 500ms. 547ms.
俺もやってみた。 Borland-C++5.6.4 -Od(最適化なし) 454ms. 578ms. 765ms. -Ox(最大限最適化) 422ms. 516ms. 703ms. Pen4 2.8G + WindowsXPSP1 腐った某ランドのコンパイラでもテーブルが最速である事が判明。
漏れは以前、このスレに、「車輪の再発明はよくない」とか書き込んた者なのだが、 コンテナの再発明と、グローバル関数の開発は別だと思っている。 このスレを独壇場にしてスマンかった。 ムシャクシャしてやった。今は反省している。
車輪を再発明する必要はないが、出来の悪い車輪を改善する必要は時としてある。
まあ、今回のケースはisxdigitを迂回する必要があるかどうか疑問だけどな
907 :
デフォルトの名無しさん :04/06/24 16:59
例外規則って何かに使われてるんですか? 書いても何も得しないんでしょうか? void Process() const throw(); のthrow()の部分。
デザインパターンのStateパターンって、 継承で実装するよりも、templateと特殊化で実装 した方が楽な気がしますが、何か問題あるでしょうか?
isalphaはロケールを見て適したテーブルを引く、ということをVCはやってたから (間違ってたらゴメン) ASCIIコードのみを考えるなら、自作のほうが早くなるのかも寝。
*BaseState に代入できませんな…orz コーディングは繰り返しが出てくるくせに…
912 :
デフォルトの名無しさん :04/06/24 20:21
>>910 テストしてみたけど、isalphaだけだとうまくいかない。
(下記の後者のどこがいけないのでしょうか?)
setlocale(LC_CTYPE,"japanese");
//これはOK
for(int i=0;i<=0xFF;i++){
if( !( isa2(i) == ( (isascii(i & 0xFF) != 0) ? (isalpha(i & 0xFF) != 0 ) : (false) ) ) )
printf("isa2(%d)=%d,isalpha(i)=%d\n",i,isa2(i),i,isalpha(i));
}
//これだとなぜかうまくいかない
for(int i=0;i<=0xFF;i++){
if( !( isa2(i) == (isalpha(i & 0xFF) != 0 ) ) )
printf("isa2(%d)=%d,isalpha(i)=%d\n",i,isa2(i),i,isalpha(i));
}
なんで戻り値を比較してるんだ?
>>890 じゃあ、どうやって戻り値を利用するの?
ローカル変数のコピーを返せばいい
>>912 つうか、プログラムもうちょっとちゃんと書け
ifの条件をすっきりさせて、printfの引数の数を数えなおせ
>>915 関数の引数に変数を渡したらコピーされるのは知ってるけど、
returnの場合もコピーされた変数が戻る?
>>916 ほんとだね。全然見てなかった...orz
setlocale(LC_CTYPE,"japanese");//これがないときは両方うまくいく
//これはOK
//asciiか判断してからalphaかを確認
for(int i=0;i<=0xFF;i++){
if( isa2(i) != ( (isascii(i) != 0) ? (isalpha(i) != 0 ) : (false) ) )//一致しないとき
printf("isa2(%d)=%d,isalpha(%d)=%d\n",i,isa2(i),i,isalpha(i));
}
//これだとlocale変えてるときに一致しないときがある
//alphaかだけを確認
for(int i=0;i<=0xFF;i++){
if( isa2(i) != (isalpha(i) != 0 ) )//一致しないとき
printf("isa2(%d)=%d,isalpha(%d)=%d\n",i,isa2(i),i,isalpha(i));
}
921 :
デフォルトの名無しさん :04/06/24 21:46
ctype.hのisalphaとlocaleのisalphaは別物だぞ。 ctype.hのisalphaはマクロだから遅くないけど、 localeのisalphaは複雑なコードだから遅い。
922 :
デフォルトの名無しさん :04/06/24 21:46
つまりC++はCより遅い
ついでに俺も正直者という事にしておいてください。
>>919 一致しない範囲は半角カナなんだってば。
この辺?
> _ismbcalpha
> 英字 c がシングルバイト ASCII 英字(0x41<=c<=0x5A または 0x61<=c<=0x7A)
> または半角カタカナ文字(0xA6<=c<=0xDF)の場合だけ真を返します。
>>918 もどらない。戻り値は使わないようにすべき
927 :
デフォルトの名無しさん :04/06/25 07:40
すみません、質問があります 今96×96で14枚つづりのアニメーションをしよう(画像は96×1334)と思っているのですが アニメーションなんてやったことないので正直わかりません やり方を教えていただけないでしょうか? また画像をまとめる際は横長や縦長にするより正方形や長方形にしたほうがいいのでしょうか? よろしくお願いします
はい次の質問どうぞ
"C++"を二文字動かして"C#"にしろといわれましたがよく分かりません。 すっきりとした回答をお願いします。
931 :
デフォルトの名無しさん :04/06/25 09:20
>>930 二文字動かすの部分がわかりません。出力例をください
VC++つかってるんですが Debug warning! Detected memory leaks といわれてしまいます なぜですか?
933 :
デフォルトの名無しさん :04/06/25 09:32
>>932 文字通りメモリリークしている。
たぶんdelete忘れ。
VCスレで発見方法教えてもらえ。
( 'ー' )イイ!
938 :
デフォルトの名無しさん :04/06/25 18:51
質問でございます class A{ class B{ public: int x; } B y; } こんな感じでクラスの中で宣言したものをその上のクラスで宣言して使う時 gccではコンパイルできるんですがBorland C++では出来ません。 なにかオプションとかつけたら出来るようになるんでしょうか?
939 :
デフォルトの名無しさん :04/06/25 20:26
>>928 ISO/IEC 14882:2003,Information Technology―Programming languages―C++
では、アニメーションについて規定していない。
よって、このスレのスコープ外である。
処理系別のスレで質問されるがよい。
>>938 できるだろ。もしかして
int x;
} ←ここに ; が抜けてるだけ、とかいうオチじゃないだろうな?
今晩は厨房いないのかツマラン
↑初登場
944 :
デフォルトの名無しさん :04/06/26 00:38
iostreamについて質問です。 int main(int argc,char *argv[]) { FILE *fin = stdin; if(argc>1) fin = fopen(argv[1],"r"); ・・・ } このように引数が与えられない場合は標準入力を使用し、引数が与えられた 場合にはファイルオープンをするような処理をiostreamを使って簡潔に記述する 方法をご教授ください。
istream* pistr; ifstream istr; pstr = &cout; pstr = &istr; (*pistr) >> i;
(argc > 1)って常に真だと思うが。
訂正。 pstr = &cout; ↓ pstr = &cin;
>>946 マジで言ってるんだとしたら、相当痛い。もう寝とけ。
>>944 こんなところで。
#include <iostream>
#include <fstream>
int mainfunc(std::istream & stream){
int i;
stream >> i;
std::cout << i;
}
int main(int argc,char *argv[]){
if(argc>1){
std::ifstream stream(argv[1]);
mainfunc(stream);
}else{
mainfunc(std::cin);
}
return 0;
}
さらに訂正。 pstrを、pistrに修正。 ま、雰囲気で分かるとは思うが。
>>945 ,949
なるほど・・・理解しました!
ありがとうございました。
クラスのプライベートで、 char *dogs[4] = {"Afghan Hound", "Beagle", "Border Collie", "Dalmation"}; のような文字列の配列を定義するにはどうすればいいんだろ。。。 class name{ private: char *dogs[4] = {"Afghan Hound", "Beagle", "Border Collie", "Dalmation"}; }; こうするとエラーでるし。
>>952 これでいいか
class name{
private:
static char *dogs[];
};
char *name::dogs[] = {"Afghan Hound", "Beagle", "Border Collie", "Dalmation"};
954 :
デフォルトの名無しさん :04/06/26 11:01
>>952 class name{
private:
char *dogs[4];
public:
name()
{
dogs[0] = "Afghan Hound";
dogs[1] = "Beagle";
dogs[2] = "Border Collie";
dogs[3] = "Dalmation";
}
};
>>953 これだと結局はグローバルで初期化することになるよね?
できればコンストラクタ内で初期化したいんだよ。
>>954 それは俺も考えたんだけど、そんな面倒くさいことしないといけないの?
本当に使おうと思ってる配列の数は28個なんだけど。。。。
956 :
デフォルトの名無しさん :04/06/26 11:16
>>955 class name{
private:
char *dogs[4];
public:
name()
{
ifstream f("dogs.txt");
for(int i = 0; i < 4; i++) {
//ma, ganbareya...
}
}
};
class name { private: static const char * * dogs; public: name() { static const char * const tmpDogs[] = { "AH", "B", "BC", "D", }; dogs = tmpDogs; };
>>955 > できればコンストラクタ内で初期化したいんだよ。
ならコンストラクタの中に書けばいいじゃないか。
>>955 >そんな面倒くさいことしないといけないの?
古今稀に見るワガママ君だな、キミ(w
クラス関係ないじゃん。
>>955 コンストラクタ内で初期化したいということは、インスタンス毎に配列を
持っていたいということ?そうだとしたら、そもそも
>>953 の方法は適さない。
その配列を書き換えるつもりが無いのなら、staticなメンバとして宣言して、
クラス定義の外で一度だけ初期化するの(つまり、
>>953 の方法)が自然だと思う。
その配列の用途が判らないことには答えようがないよ。
>>961 >インスタンス変数とクラス変数
お前の造語か?( ´,_ゝ`)
わかったとしてもわがまま言うだろうから、ここは素直に「できない仕様」と言って放置しよう。
965 :
デフォルトの名無しさん :04/06/26 13:22
>>963 まずググってから発言するべきだったな
( ´,_ゝ`)スゲーバカハッケンシマスタ!
>>966 まあ、クラス変数作るのにstaticなんてキーワード使うC++系言語が悪いといえば悪いんだけど。
ググってから発言すべきってのには同意。
グローバル変数、メンバ変数と言ってくれなきゃわからん。
そして誰も相手しなくなった・・・
>>968 それもクラス変数、インスタンス変数とは微妙に違う。
C++では、両方とも「メンバ変数」で、static付いてるのが「静的メンバ変数」だ。
稲垣メンバ変数
Javaの用語をC++スレで言われてもなぁ・・・・・
じゃあ変数の呼び方で1000目指します。
それじゃおまえら女性にはちんちんのこと何て呼んで欲しいよ。 俺は恥かしそうに「おちんちん」て言ってほしい。
個人的にはインスタンス変数って言葉が何となく気持ち悪い。
俺もおちんちん派
インスタンスおちんちん
じゃあ非staticメンバ変数をおちんちん変数と呼ぼう。
Visualおちんちん++
おちんちん++; は、つまり勃起することを意味する。
違うだろ++はイテレータだ。隣のマムコに移動するんだよ。
++は必ずプラプラと発音する様に
C++の相談を・・・・ すみません、部屋間違えました
>>986 におちんちんをいじってる姿を見られた感じがするんだが
>>984 型が違うから同じコンテナに入れて走査できないだろ?
∧∧ ミ _ ドスッ ( ,,)┌─┴┴──────┐ / つ. 相談室は夏期休暇中 │ ~′ /´ └─┬┬──────┘ ∪ ∪ ││ _ε3
ぬルポに決まってるだろうが!
ちんぽいんたー
あとは次スレ立てて現スレ埋めるだけだから、 ここでおちんちんの呼び方がきっかけで起こった俺のちょっとHな体験談を 書かせてもらおうか。 あれはバイトをしてた頃の話だ。 当時俺はファミレスでバイトをしていた。 ある日バイトの休憩時間にウエイトレスの女の子と休憩室で二人きりになったんだ。 女の子と言っても俺より2歳年上で、バイトの先輩でもあった。
ツヅキマダー?
埋め
で、どういう流れでそうなったのかは忘れたが、 男性器のことを何と呼ぶかという話になった。 彼女はさっきも書いたとおり年上で、 けっこう活発で面倒見も良い頼れる先輩って感じなんだけど、 その話の時はなんだか耳が赤くなってるのが俺にはわかって、ちょっと可愛く見えた。 その時は彼女は「ちんちん」と呼ぶと言っていた。 いつもの先輩としての彼女とは違って、少し恥かしがってる言い方がちょっと新鮮だった。 休憩時間はそんな話で終わったんだけど、 その日のバイトは俺も彼女も閉店時間までだったので、 バイトが終わってからまた休憩室で一緒になった。
産め
梅
埋め
生め
1000 :
デフォルトの名無しさん :04/06/26 15:52
1000おちんちん ぬるぽ
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。