STLつかうと一気に実行ファイルサイズが10倍に?! 環境によるだろ。 俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力 ランタイムを使用するようにして使っているが、例えばstd::vectorを 使っても使わない時と比べ10Kほどしか増えない すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。 C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。 とかいうエラーが出るんだけどこれってどうすればいいの? #include <stdafx.h> 後死ね。 言葉が悪いな。それで教えているつもりか。 まぁヒントぐらいにはなったな。 うむごくろう。
乙
まぁ新スレぐらいにはなったな。 うむごくろう。
大域識別子の宣言・定義について教えてください。 通常、 extern int i; のようにすると、それは宣言と見なされてインスタンスは作成されませんよね。 ところが extern int i = 1; のように書くと、インスタンスが作成され1で初期化されます。 ということで、externが付いても初期化がされているものは、externが 無視されるのだろうと、かってに自分を納得させていました。ところが int i; extern int i = 1; という定義の重複と思われるコードをコンパイルしてみると、エラーは出ず 実行したらiが1で初期化されていました。はて?と思い、今度は前後を変えて extern int i = 1; int i; でコンパイルしてみると、iの再定義ということでコンパイルエラーになりました。 これらの現象から帰納すると、どういうことになるんでしょうか。 単にコンパイラがおかしいのでしょうか。ちなみにVC++ 2008 Expressです。
>>8 C だと int i; が仮定義 (tentative definition) とかいう扱いになって、
コンパイル〜リンクできるはず。
C++ だと、 extern が付いてない int i; も、初期化子が付いてる extern int i = 1; も
両方とも(仮ではない)定義とみなされる(規格の 3.1 Declarations and definitions p2 )ので、
定義が重複していることになり、 ODR 違反で未定義動作になる。(規格の 3.2 One definition rule )
g++ 3.4.4 では、並べて書くと redefinition of `int i' というエラーになった。別々の
ファイルに分けて書けばリンクエラーになると思う。 VC は、 C と同じ動作になってる
・・・と思ったけど順番変えてエラーになるのは意味が分からんな。
まぁ未定義動作なんてこんなもんだろ。
>>10 ありがとうございます。
なんかコンパイラのクセみたいな感じですかね。
そんなことで悩むのはこれまでとします。
v(^・^)v
入力した値が偶数か奇数か調べるプログラムを作りたいのですが 偶数(2n)と奇数(2n-1)の部分の表現の仕方がわかりません。 #include <iostream> using namespace std; int main() { int num; int sum = num cout << "整数を入力してください\n"; cin >> num; if (num == 偶数) { cout << "偶数です\n"; } else if (num == 奇数) { cout << "奇数です\n"; } return 0; }
>>13 num % 2 == 0
num % 2 == 1
>>13 2で割り切れたら偶数、割り切れなかったら奇数だ。
やはりプログラムは応用力ですね・・・・。 修行に出てきます。
if( num & 1) 奇数 else 偶数 情報処理の基礎的にはこっちじゃない?
>>19 ビット単位の論理演算子ですか?
自分はこういう風にコードを書いてみました。
#include <iostream>
using namespace std;
int main()
{
int num;
cout << "整数を入力してください\n";
cin >> num;
if (num % 2 == 0) {
cout << "偶数です\n";
}
if (num % 2 != 0) {
cout << "奇数です\n";
}
return 0;
}
num % 2 == 0が偽だった場合は奇数確定なんだから、num % 2 != 0は不要だろ。
>>21 大変申し訳ございません 修正しました
if {cout << "奇数です\n";}
本当にコンパイルと実行して試してるの?
>>22 訂正
else {cout << "奇数です\n";}
連投すいません;;
これからドリトル先生の祝賀会に行くので落ちます。 お疲れ様でした
ちゃんと理解できていれば応用もへったくれもないだろ。 定義に遡って定義どおりに書くだけだ。 cout << (num % 2 == 0) ? "偶数" : "奇数"; ビット演算を持ち出す必要は全くないな。
ビット演算の方が速いじゃない
29 :
デフォルトの名無しさん :2008/07/26(土) 13:54:06
いまどきビット演算にこだわるおとこの人って…(笑)
条件演算子を持ち出す必要も全く無いけどな。
どうせ "num % 2" の演算は最適化されるだろうから わざわざビット演算で書いてわかりにくくする必要はない 本当に "num % 2" が割り算を発生させていて、 かつその部分のコードが実行速度のボトルネックになってない限り ビット演算を使う必要はないんじゃないの (premature optimization ってやつだ)
おれはビット演算が当たり前になってるからMod演算は逆に読みにくいし if( num % 2 ) だけならともかく”==0”が付くことで式が増えて解釈が二度手間になる。
>>33 if ( num % 2 )
{ /*奇数*/ }
else
{ /*偶数*/ }
ビット演算が当たり前になってる奴のコードって読みづらい
そんな低脳ぶりをアピールされても困る
僕が質問したばかりに言い争いが始まってしまって申し訳ない。 反省と言っては何ですが、30分間冷房を28度にします。常時19度・風速急
切れよw
えるしっているか びっとえんざんは かんきょうの えいきょうを うけやすい
c++の課題でgets()を使い文字列を取得、Ctlr+Zが入力されたら処理を中断するというものが出たのですが、Ctrl+zの入力で難航しています。 gets()はEOFが入ったらnull文字に置き換えるのですよね? char strBuff[256]; printf("文字を入力して下さい。(Ctrl+Zで終了)\n"); gets(strBuff); if(strBuff[0] != '\n'){ printf("%s\n", strBuff); }else{ printf("Ctrl+Zが認識されました。\n"); } これを実行するとCtrl+Zを押しても認識してくれないのですが、どのような判定式にすればいいのでしょうか
41 :
デフォルトの名無しさん :2008/07/26(土) 17:51:28
getsでEOF判定するの? ほんとに問題文にそう書いてあんのか?
>>41 問題文には、
○入力は、gets関数を使うこと
○CTRL+Zで入力を終了し、処理をすること
とありました。
もしかしてgetsではCTRL+Zを判別することは出来ないのですか?
name>vi t.c #include <stdio.h> int main(void){ char c[256]; printf(">"); gets(c); //fgets(c,256,stdin); printf("%s",c); return 0; } name>gcc t.c /tmp/cc4hr3hR.o: In function `main': t.c:(.text+0x1d): warning: the `gets' function is dangerous and should not be used. name>./a.out >(ctrl+z) 中断 name>fg ./a.out a a name> c++じゃないけど。 ctrl+zの制御って、結構深いところまで潜らないと奪えなかったりしないのかなぁ、知らない。
>>42 これで一応いいんじゃないかな
gets()でCtrl+Zはもとの文字列に何もしないということなので、
int main()
{
char strBuff[256] = "";
printf("文字を入力して下さい。(Ctrl+Zで終了)\n");
gets(strBuff);
if(strBuff[0] != '\n' && strBuff[0] != '\0' ){
printf("%s\n", strBuff);
}else{
printf("Ctrl+Zが認識されました。\n");
}
return 0;
}
そもそもgets()を使わせる時点で唾棄すべき課題だ。 おまけにCtrlZなんて環境依存な入力を要求する辺り、出題者の非学非才が窺える。
>>43 ,44
ありがとうございます、なんとか出来そうです。
もとの文字列に手を加えないのですね。そして初期化してなかったから出来なかったと・・・
>>45 まぁ初心者だったころの気持ちを忘れてるんだろうね
学ばせる順番からいったら最初はgetsがでてきても不思議ではない
おまじないとしてfgetsを使うように言えと?w
そもそも、C++で、だぞ。
はいはいお前らここはC++相談室ですよ
安全なgetsを作ればいいんですねわかります。
template<std::size_t n>
inline char* gets(char (&buf)[n])
{
return fgets(buf, n, stdin);
}
ここまで書いてMSDNライブラリ見たら、
VC++には本当にこういうプロトタイプのgetsがあるらしいと知った。
>>40-44 getsもfgetsもEOF入れたら戻り値はヌルだから、それで判定すればいい。
Safe CRT標準入りしてくれないかなー
一生しねーよwww
53 :
デフォルトの名無しさん :2008/07/26(土) 23:33:16
すみません、このスレの人たちはVBは使えるのですか?
使わない
55 :
デフォルトの名無しさん :2008/07/26(土) 23:54:35
×使わない ○使えない
VB厨見たの数年ぶりだ
57 :
デフォルトの名無しさん :2008/07/27(日) 00:14:05
すみません、このスレの人たちはRubyは使えるのですか?
それはC++に関係のあることか?
59 :
デフォルトの名無しさん :2008/07/27(日) 00:17:43
すみません、関係なかったです。もう書きません
<p>
61 :
60 :2008/07/27(日) 00:19:50
HTMLのruby要素だとボケかまそうとしたら途中で書き込んでしまった。 もう寝る。
キモイ
auto_ptrの実装の例を読んだのですが、auto_ptr_ref型みたいな補助型が あって、それと言語仕様の微妙なからくりを使って、なにやらを実現してる ようですが、結局constなauto_ptrオブジェクトの所有権を変更できないように するためのものなんでしょうか? このからくりを説明できる物好きで暇な人いますか?
>>63 auto_ptrを関数の戻り地の型にしたいだろ?
でも関数の戻り値はrvalueだから、普通にauto_ptrを実装したのでは、所有権を移せない。
かといって、コンストラクタでconstなauto_ptrをコピーするようにした場合、auto_ptrの意味がなくなってしまう。
どうにかならんかってんで、「言語仕様の微妙なからくり」を使っているわけだ。
Move Semanticsがあらまほしけれ。
66 :
63 :2008/07/27(日) 12:50:45
レスどうもです。auto_ptrを普通に実装したのではまずいということはわかりました。 どうやって問題を解決しているのか、そのからくりを誰か語り倒してもらえませんか。
67 :
63 :2008/07/27(日) 12:52:59
今から実装の例を書き込みます。
68 :
63 :2008/07/27(日) 13:05:23
この機構は、コピーコンストラクタとコピー代入演算子に適用されているようですが 話をコピーコンストラクタに集中するとします。たいていはstd名前空間に次のように 定義されているようです。 template<class Y> struct auto_ptr_ref{ Y* yp; auto_ptr_ref(Y* rhs):yp(rhs){} }; template<class T> class auto_ptr{ T* ap; public: //コンストラクタ auto_ptr(auto_ptr& rhs):ap(rhs.release()){} auto_ptr(auto_ptr_ref<T> rhs):ap(rhs.yp){} //型変換演算子 template<class Y> operator auto_ptr_ref<Y>(){ return auto_ptr_ref<Y>(release()); } template<class Y> operator auto_ptr<Y>(){ return auto_ptr<Y>(release()); } //...他メンバ省略 }; こんな感じのようです。型変換演算子も駆使してるようですが、わけわかめです。
69 :
63 :2008/07/27(日) 13:22:43
あれ・・・なんかわかってきたようなw
70 :
63 :2008/07/27(日) 13:38:12
auto_ptr<T>型のコンストラクタに右辺値が渡された場合…… 1.auto_ptr(auto_ptr_ref<T> rhs)がコールされ 2.operator auto_ptr_ref<T>()により、実引数の右辺値であるauto_ptr<T>オブジェクトが 動的資源の所有権を失い、変わりにその動的資源へのポインタを持った auto_ptr_ref<T>型に変換され1.の仮引数となる 3.仮引数のauto_ptr_ref<T>オブジェクトがメンバとしてもってるポインタypで *thisオブジェクトのメンバapを初期化 こんな感じかな?
直接ポインタにすると色々問題が起きる事があるから クラス挟んでるだけじゃない?
explicit が抜けてるぞ。 これがないと全く無意味になる。
73 :
63 :2008/07/27(日) 13:56:24
explicitが必要なのは、生ポインタを受け取るコンストラクタでは?
g++ には auto_ptr_ref のコンストラクタに explicit がついてるぜ
75 :
63 :2008/07/27(日) 14:00:12
auto_ptr_ref型は、ユーザーが直接扱うことは想定してないので explicit付けても付けなくてもどっちでもいいやって感じ?
explicit無くても大丈夫だよ。
テキストファイルを読み込んで、std::stringに格納する効率良い方法はないですか? ifstreamでファイルを開いて、read関数でchar*型のバッファにコピーして、 char*型のバッファをstringのコンストラクタに渡す方法でとりあえず書きましたが、 ifstream→char*型のバッファ→stringと2回コピーが発生して効率悪そうです。
>>77 std::ifstream ifs;
std::string str;
getline(ifs, str);
>>78 全ての行に対して何かの処理f()をするとき
while (1) {
getline(ifs, str);
if (ifs.eof() || !ifs()) break;
f(str);
};
と書いてたんだが、もっといい書き方ってない?
(for_eachとか iterator使うのとは別の観点で)
if文を真ん中に入れてbreakするのがどうもダサく見えてしまう
eof以外にエラー判定もしておかないと、無限ループになることがある
あと、改行の無い巨大ファイルを読んだときは、
std::bad_allocが投げられるのかな?
その場合 try catch で囲っておけば、抜けた後 strのメモリは開放されて、
普通に処理を続行できる?
例えば、「ファイルが不正です」と表示してメインループに戻るとか
while (getline(ifs,line)) { ほげほげ }
サンクスコ ちなみに、改行なし巨大ファイルを読んだら例外出さずに抜けました
例外が欲しければ、予めifs.exceptions()で指定しておけばいいはず。
auto_ptr_refの話題からの派生だけど VC++コンパイラは、非const参照型で一時オブジェクト受け取れちゃうんだね。 VC++ってウンコ?とも思ったけど、C++0xでも受け取れるようになるとかって 本当なのかね? 参照で受け取っても、一時オブジェクトだけに、すぐ消えちゃうんじゃないのかな。
>>85 「プロジェクト」→「〜のプロパティ」→「構成プロパティ」
→「C/C++」→「言語」→「言語拡張を無効にする」
たしか右辺値参照とかいうやつだっけ>C++0x 新しい構文になるみたいだから従来の参照と混同はせんだろう 特別使いたい場合にだけ注意して使うようにしてればいいんじゃないか
そうか…言語拡張機能だったのか。拡張ってまぎらわしいね。 標準がいいよ。
警告出るだろ?
警告も最高レベル(W4)に変更しないと出なかったりする。
このコードの※のところがエラーになるのですがなぜでしょうか? テンプレートコピーコンストラクタなるものを試してみたのですが。 コンパイラは「コンパイルされたクラスの テンプレート のインスタンス化 'C<T>::C<int>(const C<int> &)' の参照を確認してください」 と言ってきます。 template<class T> class C{ T m; public: C(T _m = T()):m(_m){} template<class Otr> C(const C<Otr> &c){ m = c.m; } }; int main() { C<int> Ci; C<double> Cd(Ci); // ……※ }
>>92 コンパイラ何?
gcc 3.4 だとこうなる。
> : In constructor `C<T>::C(const C<Otr>&) [with Otr = int, T = double]':
> :13: instantiated from here
> :3: error: `int C<int>::m' is private
> :7: error: within this context
んで m を public にしたら通る。
レスありがとうございます。 コンパイラはVC++2008です。 確かにmがパブリックなら通りますね。 もしかして、テンプレートメンバ関数って、privateなメンバにアクセスできない ということですかね…なんじゃそら
C<int>とC<double>は別のクラス
あ、当然ですね、そういえば。 C<int>とC<double>はまったく別の型だから、privateなメンバを相互参照 できませんね!
スクロールしたら上の方にありました^^;まだ慣れて無くて
質問です 環境はVC 6.0 、OS : Xp です メンバ関数ポインタについてですが(ソースコードは次のレスで書きます) main関数内のメンバ関数ポインタ(CSample::*pFunc)から呼び出す(@) メンバ関数(CSample::func1)から、メンバ変数であるメンバ関数ポインタ(CSample::*mpFunc)を使って呼び出す(A) はできるのですが、 main関数内で、メンバ関数ポインタ(CSample::*mpFunc)を使って呼び出す(B) がいろいろ試してみましたができません そういうことはできないのでしょうか
#include <iostream> using namespace std; class CSample { public: void func(){cout << "CSample::func()" << endl;}; void (CSample::*mpFunc)(); CSample(){mpFunc = func;}; void func1(){(this->*mpFunc)();} }; int main() { void (CSample::*pFunc)() = &CSample::func; CSample obj; (obj.*pFunc)(); // @ obj.func1(); // A (obj.*mpFunc)(); // B return 0; }
すみません、素朴な疑問なのですが ostringstreamというのは関数の戻り値には指定できないのでしょうか? ostringstream function(); こういったシグニチャのメソッドを作成したかったのですが、 どうも出来ないようで…。 不可能であるなら、その理由も教えて頂けると助かります。 よろしくお願いします。
class X{ int m; }; とあった場合、 &X::mと&(X::m)は同じ意味?それとも別の意味?それともどちらかは無意味?
どちらもエラー
>>102 ::名前空間を解決することしかしないので、前者と後者は同じ意味になる。
括弧をつけることに意味を見出せないとすれば、後者は無意味。
>>101 ostringstreamはコピーできないのでエラーになる。
とりあえずはnewしてポインタでも返すようにすればいい。
ちなみに、将来的には中身を移し替える手法で戻り値にできるようになる。
C++0xに乞う御期待。
>>101 #include <memory>
stdd::auto_ptr<ostringstream> function(); にしなさい。
× stdd:: ○ std::
>>99 (obj.*obj.mpFunc)();
>>109 99じゃないけどやっぱりobj2個いるのか。
いるよ
まずメンバ関数ポインタを取得するのに一個。 次にそのポインタをインスタンスにマッチングするのにもう一個。
113 :
>>99 :2008/07/29(火) 22:51:32
>>109 ありがとうございます
助かりました
できれば理屈も教えていただけるとありがたいのですが、一応
114 :
>>113 :2008/07/29(火) 22:52:33
>>112 ニアミスでした
ありがとうございました
CSample(){mpFunc = func;}; ←ここでもエラー出るんですが
多分後ろのセミコロン取るんでしょう 何故かVC6ではエラー出なかった
セミコロン取ってもエラーが出ます コンパイラはBCC5.9.3です エラーは エラー E2235 member1.cpp 21: メンバー関数は呼び出すかそのアドレスをとらなければならない(関数 CSample::CSample() ) と出ます
CSample(){mpFunc = &CSample::func;}
120 :
デフォルトの名無しさん :2008/07/30(水) 23:04:01
とりあえず、びよよんの禿っぷりは一流だと思った
×一流 ○超一流
禿、プログラミング言語C++第4版の執筆作業に戻るんだ!
その前にヒゲを伸ばしてくれ
>>120 コメントにもあるけど、引用された英文の邦訳が筆者の認識混じりの意訳になってるな。
あやうく見落とすところだった。
元の英文は、メールでのやりとりなのかな?
>>2 のISO規格の日本語訳を見ようと思ったのですが、リンク先がnot foundになっていたので、
トップページからX3014を検索して開いたのですが、「ダウンロードしての閲覧は禁止されています。」というエラーが出て見ることができません。
どうすれば見れますか?
ダウンロードしての閲覧は禁止されています。
>>128 リンクを左クリックしただけです。
ダウンロードしないで閲覧する方法がわかりません。
>>130 ファイルが見つかりません。
File not found.
って出ます。
っ Adobe Reader をインストール
>>131 直接アクセス禁止か、クッキーか何かによる制限をしてるのかもしれない。
一度、トップページへ行って検索してみては?
>>132 の言う通り、
Adobe Readerのバージョンが古くて読み込めないのかもしれないね。
>>132-134 インストールしたら見れるようになりました。
バージョンが古かったのかもしれません。
お騒がせしましたorz
逆に、Adobe ReaderなどPDFビューアの類が全くインストールされていない状況だと、 ダウンロードのダイアログが出てうわ何をするくぁswdfgh
||つ[IEキャッシュ] ||≡3
C++では、大域のconstオブジェクトにstatic付けても意味ないよね? つまり、staticつけなくても外部リンケージはもともと持ってないってことでOK?
ん? staticがついてなきゃ外部から参照できるんじゃね?
>>139 名前空間スコープで const 付きのオブジェクトはデフォルトで内部リンケージ。
これは C++ と C との違いのひとつ。
名前空間スコープって、グローバルスコープも含まれるの?
142 :
デフォルトの名無しさん :2008/08/02(土) 16:20:38
やってみれ
いや、一般的な話でさ。 グローバルスコープも何らかの名前空間の1つとして分類されるのかなと。 でも無名名前空間もあるし、どういう位置づけなんだろ。
>>143 「グローバル名前空間」ってことになってる。
3.3.5p6 より
"The outermost declarative region of a translation unit is also a namespace, called the global namespace.
A name declared in the global namespace has global namespace scope (also called global scope)."
知らんとODR違反とかで困らないか?
std::vector< int > vint; vint.push_back( 1 ); int *p = vint[0]; //1のアドレス vint.push_back( 2 ); vint.push_back( 3 ); ・・・ とvintに追加していったとき、pのアドレスは正しいアドレスを保持 できるんでしょうか? 出来なさそうではあるけど・・
>出来なさそう 正解
>>147 reserveしとけば? 推奨はしないけど。
>>146 グローバルのconstオブジェクトが外部リンケージ持たないのと
ODR違反ってどう関係あるんだ?
152 :
147 :2008/08/02(土) 18:28:26
>>148 >>150 やっぱり確実じゃないですよね。
規則性のないバグになるのは困るのでやめときます。
誰もつっこんでないが >int *p = vint[0]; //1のアドレス これ、アドレスじゃなくて、要素の値を代入しちゃってる
たんなるタイプミスだろそれは。 問題はそこじゃねーよ。
__、 ,r´⌒ヽ,⌒ヽ,ヽ (⌒)、 .人 λ\、 ._____ \. \ 、 ヽ./ ー ー\ |\ \ ヽ./ ( ●) ( ●) | \ \ / (__人__) \ はい、どーもすみませんでした |. \ | ` ⌒´ | . |. |.\_ノ\ / . |. | | \______/ . | ) .| . . ̄ ̄ . | | .| | |.| .| . | | .| .| / / / ヽ, (__ノ ヽ、__つ
>>152 「確実じゃない」というのがどの範囲まで指した言葉なのかによりますけれど,
コンテナ内への参照が無効化されるのを reserve で阻止するのは
きちんと扱うならば規格の保証の範囲内ですよ
STLのstringについて質問です void main() { _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF); std::string str("tekito"); str.append("namojiretu"); exit(-1); } 上記のコードがメモリリークになるのですが、どうやって解決すればいいのでしょうか? eraseやclearを使っても解決できません。 また条件が特定できなかったので明記しませんが、使う場所によっては文字列中に改行文字があったときだけ メモリリークするような現象も起こりました。 解説よろしくお願いします
C++ではexitを使わないこと。
んじゃあ何で終了するんですか?
mainから素直に抜けて下さい。 むしろ、int mainにしてreturnして下さい。
exit(-1)の中でプログラムが終了・リークチェックが走る strはスコープを抜けてないのでデストラクタが走らない。
>>160 >Visual Studio .NET 以前のバージョンの標準テンプレート ライブラリは _CrtDumpMemoryLeaks が誤検出を報告する原因となっていましたが、最新リリースでは修正されています。
これ今現在は大丈夫ということなんじゃないんですか?
ちなみに使っているのはVS2005です。
>>162 >>163 そうするしかないのかー
サブ関数とかで階層が深くなってるとmainまで戻してくのが面倒だったのでexit使ってたんですが…
うーん、直すしかないのか
プログラム終了用の例外作って代わりにすればよくね? main関数でcatchすること前提にすればギリギリ有りな気が。 struct exit_class{}; void exit_cpp(){ throw exit_class(); }
>>166 すんません、アホでした
例外投げるという方法をすっかり忘れていました
ありがとうございました
俺は何の躊躇もなくexit使ってるぜ。 組込みじゃないんだから、プログラム終了時のメモリリークなんてOSがなんとかしてくれるさー
それでもリソースリークのリスクは依然としてある。
そのexitがエラー時の終了じゃなく、通常の終了処理なら それはプログラミングの怠慢だろ スパゲティ風味がするぞ
今さら人には聞けないシリーズなんですが、vectorとdequeってどう発音してますか? vector:ベクトル?ベクタ? deque:デック?ディーク?デキュー?
>>170 俺のスパゲティはおいしいんだい!
リソース解放はatexit()で解放ルーチン登録してるからいいもん!
>>171 ベクターとデキューって心の中で発音してます。
173 :
デフォルトの名無しさん :2008/08/03(日) 16:37:38
>>171 俺はデキューと読んでいるが、確かデックが正しい発音のハズ。
174 :
ひみつの検閲さん :2024/12/23(月) 06:13:28 ID:MarkedRes
>>174 それもう飽きた。
>>172 exit()を使いたいがために登録し捲くるの?
個数制限もあるのに?
int main try{ } catch(...){ } これ最強じゃね?
実際、メモリーリークなんてプログラムが終了すれば、全部解放されるんでしょ? Windowsなら。
終了時に解放しないのは、低レベルなリソースだけでみれば、Windowsでは問題ないが、 しかしデストラクタが走らないので、 例えばデストラクタでファイルへの書き込みを行うだとか、 そういうことをしているとまずい。
Windowsは、プログラム終了時に入出力チャンネルのクローズも やってくれんでしょ?
class hoge{ …… void write_all_data(void); void clear_all_resources(void); ~hoge(void); } hoge::~hoge(void){ write_all_data(); clear_all_resources(); } こういう形だとまずいってことじゃないの?
>>175 まあ俺がそんなにファイルとか扱うプログラムを書かないだけだったりするけどな。
>>180 >>179 が言っているように、デストラクタ内でログの書きだしとか、ロックファイルの削除とか、
そういった処理を行うとするなら
デストラクタの呼び出しを伴わない終わり方(exitとかSIGKILL)をすると
いろいろと面倒だよねって話。
うーん、exit派なんだけど、ちょっと心が揺らいできた。
throwしよっかな。
でもめんどくさいw
>>182 悪いことは言わん、exit も throw もやめとけ。
どちらもあくまで緊急脱出手段だ。
デストラクタの役割がメモリ解放だけだと思ってるうちは初心者
185 :
デフォルトの名無しさん :2008/08/03(日) 20:43:10
>>180 入出力チャンネルって何?
ハンドルなら自動的にクローズされるけど
exitなんて使ったら、名前付きパイプとかWindowsフックみたいな プロセスを越えるリソースが開きっぱなしでリークするな。 他にもメモリキャッシュ実装しててflushされないとか、 キャッシュファイルが削除されないとか、 Excelみたいなファイル内に共有ロック情報書いてる場合にアンロックされないとか リソースリーク/終了処理が正常に行われないケースは山ほどある。
されねーよ。 どのプロセスがどのnamed pipeを開いているかぐらい余裕で把握している。 すべてのプロセスが解放したら消させる。 フックも把握していないといずれ面倒なことになる。 それにVistaからは、フック関数側のCallNextHookEx呼び出しに頼らず、 Windows側がひとつひとつ呼んでいるってのをどこかで呼んだ気がするが。
exit使ったって正常に動くプログラムは書けるが そんなプログラムを書く奴は人に信用されない 無学に見られるから止めておくほうがよろし
191 :
デフォルトの名無しさん :2008/08/03(日) 21:39:43
>>188 言いたいことはよくわかるが
exit なんぞ平気で使う奴には通じない話だ
190に補足すると 作成者が注意力を発揮すれば exit 使う正しいプログラムは書けるが ちょっとした改造の度にそんなところに注意力を使わなければならない時点で 稚拙な設計だ 優秀なプログラムは、無駄なバグ混入リスクを取らないよう書かれている で、ホントに必要なときに限りテクを使う
ところで、デストラクタでリソース解放するのって優秀なの?
エラー処理できないのでダメダメ
>>193 他の方法ではまともに例外安全なコードが書けない
auto_ptrやsmart_ptrをダメダメだと言い捨てるとは、勇者だな。 んじゃ教えてくれ。 リソースの解放でエラーが発生したら、一体どうすりゃええんだ。
すみませんが、助けていただけないでしょうか。
ttp://www.geocities.jp/menopem/ こちらのDirectXウィンドウ化ツールで使用する補助DLLとして、
「窓化起動したアプリケーションを再びフルスクリーン化する」
というものを制作したいのですが、C++の経験が無いために苦しんでいます。
補助DLLの仕様についてはツール内にtxtで含まれているのですが・・・。
用途としてはどうしても色化けしてしまう古い(256色専用)ゲームをパレットエミュレートで正常に動かすことが目的なのですが、
窓化した場合、窓の描画領域の0.0をディスプレイの0.0に合わせないと、画面描画や文字描画がその分ずれてしまう現象に見舞われてしまったので、その簡易な修正のためです。
問題のゲームは下のデザートタイム夢幻の迷宮とファントムナイト夢幻の迷宮Uです。
ttp://www.parsley.gr.jp/ps_top1.html (リンク先18禁)
>197続き 一応書いてみたコード。ウィンドウハンドルとか判りませんorz #include <windows.h> #include <stdio.h> BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { static TCHAR processName[MAX_PATH]; switch(ul_reason_for_call) { case DLL_PROCESS_ATTACH: GetModuleFileName(0, processName, MAX_PATH); processName[MAX_PATH-1] = '\0'; OutputDebugString("補助DLLロード確認"); MessageBox(0, processName, "補助DLLロード確認", MB_OK); SetWindowLong(HANDLE, GWL_STYLE, WS_POPUP | WS_MINIMIZEBOX | WS_VISIBLE); SetMenu(HANDLE, NULL); SetWindowPos(HANDLE, HWND_TOP, 0,0,1400,1052, SWP_FRAMECHANGED | SWP_NOCOPYBITS); break; case DLL_PROCESS_DETACH: OutputDebugString("補助DLLアンロード確認"); MessageBox(0, processName, "補助DLLアンロード確認", MB_OK); break; } return TRUE; }
DirectXスレに行って下さい
200 :
199 :2008/08/03(日) 22:05:18
訂正、Win32APIスレへ ClientToScreen、GetWindowRectなど
>>194 例外安全でエラー処理出来る方法を、世界中で多くの人が求めています。
教えてあげて下さい。
>>196 releaseとかcloseのような名前の解放用メンバ関数を用意しておいて、
エラー処理が必要ならそれを明示的に呼び、要らなければデストラクタに任せるとかいう話を聞いたことがある。
>>202 //RAIIなコード
void fn1(){
File fR;
File fW;
fR.open("read.txt");
fW.open("write.txt");
fn3(fR, fW);
}
//デストラクタに頼らずリソースを解放するコード
void fn2(){
File fR;
File fW;
fR.open("read.txt");
fW.open("write.txt");
try{ fn3(fR, fW); }
catch(...){
try{ if(fW.opend()){fW.close();} }
catch(...){
if(fR.opend()){fR.close();}
throw;
}
if(fR.opend()){fR.close();}
throw;
}
try{ if(fW.opend()){fW.close();} }
catch(...){
if(fR.opend()){fR.close();}
throw;
}
if(fR.opend()){fR.close();}
}
RAII様様 GCよりよっぽど使えるわ
それは言いすぎな気がするけど、だからこそC++を使う気になるのは俺もそう。
RAIIのほうは解放に失敗したらハンドルリークするから駄目だね
ついでにGCがあるjavaとC#も。 リソースのcloseに関してはjavaがもっともカス。 //java void fn2(){ InputStream ist = new FileInputStream("a"); try{ OutputStream ost = new FileOutputStream("b"); try{ fn3(ist, ost); } finally{ try{ ost.close(); }catch(Throwable t){} } //(*1) } finally{ try{ ist.close(); }catch(Throwable t){} } } //(*1) catchで止めないとより重要なfn3内の例外が消される //C# void fn2(){ using(StreamReader r = new StreamReader("a")) using(StreamWriter w = new StreamWriter("b")) { fn3(r, w); } }
>>208 >ハンドルリークするから
しません。それただのバグ。
>>208 解放処理が失敗してどうやって解放するの?
プロセスを終了してOSに任せるくらいしか俺には分からない。
もし、デストラクタが例外投げた場合の話であれば、そもそもそれが間違いだよな。
デストラクタは何があろうと例外を投げちゃまずいよ。
Dはまだscoped_ptrなRAIIがあるからいいけど,それすらない C#,Javaだとリソースの解放マンドイよな
>>210 > しません。それただのバグ。
失敗はするでしょ。
成功するまでループするの?
>>213 しません、は「リークする」にかかってるんでしょ。
解放失敗すればリークするだろ
解放に失敗するリソースをどうやって解放するんだ もはやリークは避けられない運命としか
>>215 >>208 の人は「RAIIのほうは」って言ってるんだし、
解放失敗すればリークってのはRAII関係無いだろ。
脈絡の無いレスは止めておいた方がいい。
明日死ぬかもしれないだろ
>>215 では、RAIIを使用せずに開放メンバ関数を手動で呼べばリークしないんですね
>>211 >>204 って解放に失敗したらデストラクタから例外投げるよって意味じゃないの?
そうでなければ、
try{ fn3(fR, fW); } catch(...) { }
try{ if ( fW.opend() ) { fW.close(); } } catch (...) { }
try{ if ( fR.opend() ) { fR.close(); } } catch (...) { }
とかいう暴挙に出てもいいのかな。
>>222 fn3の例外は潰したら駄目。
他はまぁアリかな。
>>166 の"ギリギリ"ってプログラムに拠るって意味かね?
それとも、クライアントプログラムでもサーバープログラムでも、
1年かかって計算するようなプログラムでも、"本当に不可避な場合"だけを指してるのかな?
おれは前2者しかやったことないから、それ以外がよく分からないんだけど、
クライアント側ならOKと判断してたし、サーバー側も月一回程度の再起動はゆるされたんで、
"ギリギリ"がよく分からない。 よかったら教えて欲しい。
>>183 throwもやめとけって、じゃあどうするの?
>>225 異常系はかまわんけど、正常系で throw で抜けるはよせ。
return で main() まで帰れ。
>>226 異常系って言うと、メモリが足りないとか、電力が足りないとか?
頭が足りないとか。
>>227 throw の使い方は派閥があるみたいだけど、俺は寛容派なんでファイル
オープンに失敗した程度のエラーや、ユーザーがキャンセル操作を行った
程度のことでも throw を使っていいと思う。
230 :
デフォルトの名無しさん :2008/08/04(月) 00:49:30
テンプレートクラス内テンプレートクラスの演算子オーバーロードをしたいのですが、 どのように記述すればよいでしょうか? 例えば、 template< int m > struct foo{ template< int n > struct bar{}; }; に対して、operator*( int, foo<m>::bar<n> )を定義したいのですが、 fooのクラス内静的関数として定義すると怒られますし、 グローバルな領域で template< int m, int n > foobar operator*( int, foo<m>::bar<n> ) とやってもやはりコンパイルが通りません。
>>229 プロジェクト内で一貫した方針で使ってる分にはいいんじゃないかと思う。
232 :
224 :2008/08/04(月) 01:07:07
無視されてるのか勘違いされてるのか、よくわからないけど、
とりあえずあいまいな質問だったし、
>>229 が答えのような気がするので、
お礼いってたいさんします。 さんくす。
233 :
デフォルトの名無しさん :2008/08/04(月) 01:09:08
煽ってたわけじゃなくて、本気で聞いてたのか……
234 :
232 :2008/08/04(月) 01:38:27
235 :
230 :2008/08/04(月) 02:24:03
template< int m, int n > foobar operator*( int, typename foo<m>::template bar<n> ) でとりあえず自己解決したような気がします、すいません。 それにしてもこんなところにtemplateをつける用法があるんですね。
RAIIだとハンドルリークする について、まともな反論は結局なかったな なんであんな誤った手法がまかり通ってるんだろうな
>>236 RAIIだとハンドルリークする
について、まともな主張は結局なかったな
>>236 俺の誤解でなければ、
>>208 と同じ人or意見ということだよな?
そもそも
>>208 自体が説明出来ていないので、
反論以前に、まともな主張になっていないわけだけど。
釣りかな?
CloseHandleが失敗したらハンドルリークするんですが、どうすればいいんですか><
>>239 何事も完璧を求めると大変です。
どうやっても閉じれないハンドルなど捨ておきなさい。
close失敗したハンドルって普通リークしたって言わないよね
CloseHandleが失敗する原因を突き止めてください。
普通はログ吐くよね 吐けな(ry
グローバル変数やグローバル関数に一律で大域識別子::を付けるというのは C++では当たり前ですか?確かに名前の衝突は起きにくくなりますが いちいち付けるのもなぁとも。やっぱり大規模なプログラムなんかだと そうやっといたほうが良いのですかねぇ。
必要なら付けろ。 不要なら付けるな。 よほど変なルールじゃなければ従え。
RAII使っても使わなくてもCloseHandleに失敗したときの対応はニタリヨッタリじゃない? RAIIの欠点としては弱いのでわ?RAII使うメリットを考えるとRAIIダメとは思わないなあ。
何を言ってるんだ。
248 :
デフォルトの名無しさん :2008/08/04(月) 21:23:45
RAIIってリソース破棄の順序も制御できるのかな。 ファイル書き出し → アンマウント みたいに。
>>249 RAII≒デストラクタ
後はもう自明だろう
>>249 アンマウントに失敗したらリークどころじゃなくなるからRAII方式はやめとけ
キチガイが沸いているようですね
APIの戻り値はチェックして当然だよな。 class HandleWrapper { HandleT handle; public: //... ~HandleWrapper() { while ( CloseHandle(handle) != SUCCEEDED ) { ; } } };
ループするならユーザー通知くらいは。 struct NoRetry{ bool userRetryWait(HandleT handle){return false;} }; template<typename T=NoRetry> class HandleWrapper{ HandleT handle; T rt; public: //... ~HandleWrapper(){ while (CloseHandle(handle) != SUCCEEDED){ if(!rt.userRetryWait(handle)){break;} } } };
auto_ptr見てたら演算子のオーバーロードがよくわからなくなってきました。 struct st { int Int; }; class test { st Data; public: st *operator->() { return &Data; }; st *Get() { return &Data; }; }; test obj; int i = obj->Int; これが出来るなら int i = obj.Get()Int; これも出来そうな気がしたけど出来ない。 そもそも->演算子ってどんなものなんでしょうか?
>>255 それやるなら、obj.Get()->Int
多重定義された->演算子は変わりもので、それを呼び出してその戻り値に再び->演算子を適用するようになっている。
つまり、obj->Intはobj.operator ->()->Intと解釈される。
>>256 >obj->Intはobj.operator ->()->Int
こんな解釈されるんでしたか・・。
ありがとう。勉強になった。
例外処理についての質問です try内部でエラーが発生してcatchに移行する場合など、若干動作が遅いという話を耳にしました それは納得なのですが、例外が発生しない場合はどれだけtry catchを繰り返したりネストしても 例外が発生しない限り処理速度は低下しないのでしょうか?
登録と解除のオーバーヘッドはある
まーほぼすべての処理系では、 tryのブロックに入るたびに、例外のために必要なものスタック上に構築するので tryブロックに出入りするたびにコストがかかる。 だから、これは問題ない try { for(;;){/**/} } 問題あり for (;;) { try { /**/} }
即レスどうもです。 と言うことは例えばmainの最初にtry、最後にcatchして内部でどれだけ処理したとしても try catchしない場合と比べてオーバーヘッドは略ゼロに等しいということですね。 これで安心して例外処理ベースで組めそうです。ありがとう。
struct{ float _11, _12, _13, _14; float _21, _22, _23, _24; float _31, _32, _33, _34; float _41, _42, _43, _44; }; 上記のようなマトリックスのクラスで、 >m[1][2]のようにアクセスできるように演算子[]を多重定義せよ という課題があるのですが可能なのでしょうか?いくら検索しても やり方のヒントも出てこないのですが…
つunion
具体的にはこう union{ struct{ float _11, _12, _13, _14; float _21, _22, _23, _24; float _31, _32, _33, _34; float _41, _42, _43, _44; }; float m[4][4]; } 何でそれで出来るかは考えてね
どこで演算子をオーバーロードしてるのか問い詰めたい。小一時間問い詰めたい。
オーバーロードしてませんすみませんorz
反省して真面目に考えた float* operator [](int n) { return &((&_11)[n*4]); } [0][0]で_11 [1][2]で_23 になるんじゃないかな 行と列を逆にしようとするとめんどいな・・・
switch手書きの手間なんか惜しむな #include <stdexcept> struct hoge; struct proxy{ hoge&o; int i; proxy(hoge&o,int i):o(o),i(i){} float operator[](int); }; struct hoge{ /*略*/ proxy operator[](int i){return proxy(*this,i);} }; float proxy::operator[](int j){ switch(i){ case 1:switch(j){ case 1:return o._11; case 2:return o._12; case 3:return o._13; case 4:return o._14; default:throw std::invalid_argument("damepo"); } /*略したのは「改行が多すぎます」といわれたからであって、決してサボろうとした訳では(ry*/ default:throw std::invalid_argument("damepo"); } }
変数の定義が可能な位置について教えてください。 if(...){ int a; } これはだめですよね。ただ for(;;){ int a; } これってg++では定義できないスコープということでエラーがでますが、 Effective C++のサンプルコードでfor文のスコープでオブジェクトを 定義していたのですが、Effective C++が間違ってるのでしょうか?
>>269 C++の話なら変数の宣言の位置にそのような制約はない。
>>269 C言語でも無問題。
どうして
> これはだめですよね。
と思ったのかkwsk
272 :
269 :2008/08/07(木) 17:39:54
あ、すいません、自分の勘違いでした^^;
273 :
269 :2008/08/07(木) 18:13:46
いろいろ試して遊んでたら switch(i){ case 1: int a = 1; case 2: int b = 2; } こんなんダメみたいですね。caseラベルによって初期化が飛ばされるとかで。 case 1: int a; case 2: int b; これならいいみたいですけど。
>>267 >>268 返答有難うございます。その方法で試してみます。
ちなみに検索しても見つからなかったのは、[][]なんで
float* operator [][](int a,int b)
のようにするのかと勘違いしてたからでしたorz
275 :
269 :2008/08/07(木) 18:28:42
switch(i){ case 1: int a; case 2: int b = 2; } これだと問題ないみたい。 switch(i){ case 1: int a; case 2: int b; case 3: int c = 3; } これも問題なし。 つまり最後のラベルの位置でのみ初期化指定子が書ける模様。 なんでだろ。
フォールスルーするからに決まってるだろ
277 :
269 :2008/08/07(木) 18:34:28
それが switch(i){ case 1: int a; break; case 2: int b; break; case 3: int c = 3; } これも問題ないんですよね。
>>275 それより後ろに飛ばないから
つまり初期化をスキップしない
黙って { } つけれ
280 :
269 :2008/08/07(木) 21:09:38
switch(i){ case 1: int a; break; case 2: int b; break; case 3: int c = 3; } このコードでcase 3に飛んだ場合、aやbのインスタンスは確保されないって ことでいいの?
最適化されたらされないかもしれません。きっとcも確保されないでしょう。
>>280 これがコンパイルできない理由を考えれば
事態が把握できますか?
struct X { X(){} };
void f(int a)
{
switch (a) {
case 1: X x; break;
case 2: X y;
}
質問です。 HogeA と HogeB の2つのクラスがあり HogeA と HogeB が互いに所持しあうような場合 ファイルを分けるとしたらどのようにすればいいのでしょうか 以下のような書き方だとエラーになってしまいます ********************************* FILE_A.h ********************************* #ifndef HOGEA #define HOGEA #include "FILE_B.h" class HogeA { HogeB* m_pHogeB; public: HogeA() { m_pHogeB = new HogeB() } } #endif ********************************* FILE_B.h ********************************* #ifndef HOGEA #define HOGEA #include "FILE_A.h" class HogeB { HogeA* m_pHogeA; public: HogeB() { m_pHogeA = new HogeA() } } #endif
まちがえました。 FILE_B.hの最初の2行は #ifndef HOGEB #define HOGEB です
仮にコンパイル通したとしてもメモリ食いつぶすかスタックオーバーフローで落ちると予想 設計がおかしいぞ
>>283 そういうのは普通、所持しあうとは言わないと思うよ。
オブジェクトを作りあう……とか?
それはそうと、コンパイルを通すには、メンバ関数の定義を外に出せ。
// FILE_A.h
...
class HogeA{
...
HogeA();
}
// FILE_A.cpp
#include "FILE_A.h"
HogeA::HogeA() { m_pHogeB = new HogeB() }
// Bも同様
まあ、もちろんこれで通っても
>>286 の通りだが。
ある意味再帰的だな
>>259-260 try ブロックの出入りでオーバーヘッドが発生する処理系は、今はもうだいぶ
減ってきてると思うよ。 Windows では長らくオーバーヘッドがある実装ばかりだった
けど、今は VC++ も「同期例外」とかいうオプションで選択できるようになってたと思う。
>>285-288 ありがとうございました
コンストラクタでnewしてるのは単純な例として書いたつもりでしたが
確かにメモリを食いつぶすかループしてしまいそうですね
291 :
269 :2008/08/08(金) 07:57:24
>>282 う〜ん、デフォルトコンストラクタも初期化子と同等と考えれば
コンパイルできないのも組み込み型のときと同じと考えられますが…
switch (a) {
case 1: break;
case 2: X y;
}
これならコンパイルできますね。
要は、インスタンスの確保や初期化は、その位置に制御が来たときにだけ
されるのかどうか?ということです。もしそうなら、一番下のラベルの所だけ
初期化が許されるというのは解せないというか。けっきょく一番下のラベルも
実行時に飛ばされる場合もあるわけだし…他の上の方のラベルと同等と考え
られそうな気も…。
>>292 だから、宣言部をスルーして有効な範囲に飛び込んじゃダメなの。
要は、
{
goto foo;
int x;
foo:
}
はNGで
{
goto foo;
int x;
}
foo:
はOK。
いけね、レス番ずれた。 { int x; goto foo; } foo: がOKなのは言うまでもないし。
294 :
269 :2008/08/08(金) 09:53:56
NGというパターン { goto foo; int x; foo: 0; } は、問題ないみたいですよ。 ただ、 { goto foo; int x = 1; foo: 0; } はダメでした。 つまり、定義ではなく、初期化を飛び越すのがダメみたいですね。 初期化子やコンストラクタ呼び出しが該当するようです。 つまり、飛び越された場合、初期化はされてないけど、同じスコープだから そのインスタンスは使用可能。こういう状況を避けたいがための、エラー なのかもしれませんね。なんか納得できたかもしれません。
295 :
デフォルトの名無しさん :2008/08/09(土) 20:05:08
前者も NG であるべき
296 :
293 :2008/08/09(土) 20:43:32
すまん、>292の前者だと警告だけなんだ。
>>292 の前者だと、foo:ラベルの後に何の式もなくブロックが終わってる
ことに対して、エラーになるけど、
>>294 みたいに0;とか追加すれば
エラーも警告も出ないけどなぁ、VC++でもg++でも。
gotoで変数定義を飛び越えるのはなんら規格に反していない
規約には反しているかも知れない。
300 :
デフォルトの名無しさん :2008/08/09(土) 22:11:52
規格で認められてるからいいんだだの、gcc が警告しないからいいんだだの、そんな判断基準にしがみついていたければ勝手にしれ
じゃあお前の判断基準は何だよw
302 :
デフォルトの名無しさん :2008/08/09(土) 22:19:23
おまえに言ってもわからなそうだが、設計哲学ってやつだ
お前の様なバカがいるからポーティングに苦労すんだよ
設計哲学なんて、主観の問題じゃねぇかw 人に押しつけるもんでもない。 規格で許されてるかどうかの話してるところへ 哲学がどうとか、頭沸いてるんじゃねぇか?w
306 :
デフォルトの名無しさん :2008/08/09(土) 22:39:08
設計哲学、大切だろ・・・。 好き勝手にみんなで俺様オナニーコード書いてたら 現場は困るだろ。 まあ、お前らは自分の身を守れるのかもしれんがな。
>>306 哲学うんぬんはいいとして
俺様オナニーコードでも無駄がなくて仕様どおりなら特に困らないよ
>哲学うんぬんはいいとして は良いと思ってるんじゃなくてどうでもいいってことね
設計の良し悪しを考えずに作られたプログラムは 再現率の低い組み合わせ入力や、異常な入力に弱いことが多いからダメ 検査時に再現させられるパタンなんて限られているからね
「設計哲学」と「好き勝手にみんなで俺様オナニーコード」が違うと言うなら、 設計哲学ってのが何を指しているのかを明らかにしないと。
boostに嵌るとついついオナニーコード書いてしまうよね でも楽しくて仕方ないんだ
コードレビューなし前提の話ばかりだ みなさんダメプロジェクトにいるんですね
コードレビューやりたいって言ったんだがする気配はない 正直最低限の規約も守れない奴ばっかなのでちゃんと勉強して欲しいんだけどねぇ
>>313 他のメンバーがコミットしたコードを勝手にレビューすればいいんだ
で、最初は簡単で明白な改善を提案していけば良いんじゃない?
達人プログラマーの石のスープパターンだ
インクリメンタルなイテレーション とか書いてある本をいくら読んでもどうしたらいいのかわかりません。 横文字多すぎだよ。
incrementalなiterationの方が読みやすいということですね、わかります 俺も割とそう思う
C/C++でコードレビューは必須だろ 「C/C++できます」 の「できます」の意味が広すぎる 少なくとも一回は見ないとそいつがどの程度がわからないし 俺よりすごい人ならそいつにレビューお願いできるし
EffectiveC++も読んでない奴とは仕事したくない、ってのはさすがに我侭だろうか
Effective C++に書かれていることを独学で理解しているなら読んでなくてもいい。 読んでても理解してない奴もいるし。
Effective C++は正直言って微妙。 Exceptional C++に書いてある事を理解しててくれたら十分
例外安全て説明すんの意外と面倒なんだよな・・
例外安全ってなんだっけ・・・ 例外が発生したとき、オブジェクトの状態はその関数の呼び出し前の状態から変更されていない?
>>323 //例外安全でない、f()がthrowしたらnew A()がdeleteされない\(^o^)/
void f(){
A* a = new A();
f(a);
delete a;
}
//例外安全、f()がthrowしてもdeleteされる
void f(){
auto_ptr<A> a(new A());
f(a.get());
}
>>323 そんな感じ。
しかし例外に限らず戻り値でのエラー通知でも同様の安全性は
考えるべきだから、これはエラー安全性と言うべきだ。
http://www.gotw.ca/sands2.htm Error-Safe C++: More Than Just Exception Safety (Bjarne Stroustrup & Herb Sutter)
> But we'll also cover error safety in all cases, because the main difficulty
> in writing exception-safe code has little to do with exceptions in particular,
> but with error handling in general
326 :
324 :2008/08/10(日) 15:08:47
ごめん、f2(a);、f2(a.get());、f2()がthrowしたら、に読み替えて
簡単に言うと、デストラクタ以外の どんな関数・暗黙の呼び出しから例外が出てもリークしないようにする、ってこと
レースコンディションの親戚みたいな
それはさすがにちがうだろ
>>328 が「基本保証」。
ある処理で例外が発生してその処理を抜けたとき、副作用が起きない
(またはその処理による副作用が起きる前の状態に復元される)ことの保証が「強い保証」。
どのような状況でも例外が発生しないことの保証が「投げない保証」。
実際にみんなはどの程度例外実装してる? 結局後回しになって基本保証程度になってしまう
>>333 例外保証の実装
とりあえず例外処理の流れと簡単な処理は組み込むけどしっかりした実装はデバッグ工程でつめていく感じ
といってもデバッグ期間がほとんどないスケジュール組まれるので大抵時間なくなるという話
DB使ってるから、全部ではないけど大体は強い保証になってる。
とりあえず強い保証程度はできる限りやってる
>しっかりした実装はデバッグ工程 それ設計じゃね?
例外安全について指摘してくれる静的解析ツールとかあればいいんだけどな
>>334 最初からちゃんと書けばいいだけじゃないの?
後付けで基本保証から強い保証に上げたりするのは困難だろ。 小手先の話じゃないんだから。
計算量が O(1) から O(N) になることもあるからね 実装自体は小手先の話だけど
連想コンテナの定義って何? てっきり、常に整列されてるコンテナのことかと思ったけど、 ハッシュテーブルも連想コンテナの一種らしいね。 ハッシュって整列されてないやろ?
整列されてるかどうかじゃなくて、 任意の型(文字列とか)をキーに一意に値を求められるもの と俺は思ってたけど
>>343 それは連想配列という認識だったけど、もしかして連想コンテナと
連想配列って同義語?
連想コンテナならハッシュかニ分木。 連想配列なら多分ハッシュに限定。
mapも連想配列って言うらしい。 配列のインデックスに値だけじゃなくて、文字列などの自由な型が使えるものを 連想配列と言うらしい。 連想コンテナの例:set, multiset, map, multimap, hash 連想配列の例:map, hash こうか?連想コンテナの定義が浮かばないけど。
一般的に配列はコンテナに含まれるし、全部まとめて連想コンテナでいいのかな
Cではコンテナは配列しかなかったから、 コンテナ全部配列と呼んでたような理由かな。
組み込み型にはデフォルトコンストラクタという概念はないのでしょうか。 int(), double()などは0を返すので、論理的にはデフォルトコンストラクタを 持ってるのかと思いきや class hoge{ int i }; このhogeクラスをデフォルトコンストラクタで生成しても、iは0で初期化 されない(intのデフォルトコンストラクタが呼ばれない?!)あたり、 やはり組み込み型には論理的にもデフォルトコンストラクタは持っていない ということですか?
class hoge { int i; hoge() : i() {} };
いや、なんていうか、クラスのメンバオブジェクトに対してはそれぞれ 自動でデフォルトコンストラクタが呼ばれるのに、何で組み込み型は デフォルトコンストラクタ(存在するなら)が呼ばれないのかなと。
歴史的な事情(Cとの互換)と効率かと
もしかしてC言語の構造体との互換性のため、組み込み型は自動では 初期化しないってことなのかな?
かぶった…どうも 納得しました。
>>355 未初期化だったものを初期化するように変更しても、行儀のいいソースなら動作は変わらないはずだから
互換性の問題というわけではないと思う。
C++の思想として効率的なコードがかける必要性があるからでは?
う〜む、やはりそっちの理由ですか…
テンプレートでクラスと同じ表記ができるようにするため
続き するためにint()という表記ができるようにしたが、デフォルトコンストラクタではないし、 わざわざCと違う動作をするように変更する必要がないためじゃないかな。 357の言うように効率面もあるだろうし。
>>359 論点がずれてる
論点は
struct X {
int i, j;
X() : i() {}
};
で、i はゼロで初期化されるのに j は初期化されない理由
jが初期化されるとなると、イニシャライザの実装とかめんどくないですか?
357に書かれているように、Cとの互換よりも、効率でしょう 実際、性能重視の用途で勝手に初期化処理されて CプログラムをC++に移植したら遅くなりましたではかなわない 例外ですら迷惑なのに
365 :
デフォルトの名無しさん :2008/08/11(月) 22:01:28
すいません、糞社長にVBで書いたコードをCで書き直したら何%速くなるか 計算しろって言われたんですがどうすればいいですか? 10%だと書き直す必要はないからするな、50%速くなるなら書き直せ計算できるだろ! って言われて困ってます カメラの監視ソフトで画像を処理する感じのプログラムなんですが
僕には無理ですでいいよもう
367 :
デフォルトの名無しさん :2008/08/11(月) 22:04:26
>>366 おまえがやれ!って言ってやればいいですか?
>>365 肝の部分を単純化したものをVBとCで書いて速度を比較する
で、「肝の部分を単純化して比較するとこうなりました」と報告すればいい
大して工数は掛からず嘘もなし
369 :
デフォルトの名無しさん :2008/08/11(月) 22:09:27
書き直しの工数を含めると10%以下になりますで良いだろ。
>>369 >C書いたことないんですが
これは笑うことが期待されているのでしょうか?
373 :
デフォルトの名無しさん :2008/08/11(月) 22:13:35
とりあえず中間の30パーセントぐらいだったっていっときゃいーんだよwww
>>369 C書いたことないんなら、書き直しても大して速くならないうえに
バグが50%増しになってオワルだけだろ
長時間起動なんだろ?ついでにメモリリークも起こして使い物にならなくなるんじゃね
377 :
デフォルトの名無しさん :2008/08/11(月) 23:25:19
C#だとむしろ遅くなるんでしょうか? メモリリークはなくなりますが
変換前と変換後の言語の両方でちゃんと書ける奴以外がやることじゃない
379 :
デフォルトの名無しさん :2008/08/11(月) 23:49:06
みなさんどうもありがとうございました。ご意見を参考にさせていただいて 適当に回答しておきます。 話は変わりますが、その社長なんか変なんですよ。社員に内緒で、一番できる 技術者に占い(?)みたいなソフト作らせてるみたいなんですが 生年月日を入力するとオーラの量とかが測定できるみたいなんです。 どのようなアルゴリズムに基づいているのか本当に不思議です あと、この前社長の机拭いてたら「ノストラダムスの大予言」って本が置いてあって いくらなんでも季節外れでしょ。って思ったもんです。 その監視ソフトで業務中監視されてるみたいだし辞めた方がいいですかね?
その社長に一生ついていくべきだYO
そーいう話はプログラマ板でやれ ここはプログラ「ム」板だ
プログラマは凄腕の上級者になると Wizard と呼ばれるからな 間に占い師くらいいてもいいんじゃないかw
383 :
デフォルトの名無しさん :2008/08/12(火) 15:17:26
クラスのメソッドを名前で呼び出したくて以下を作ってみましたが、 Type2Typeで型毎にわけてif文を構築するのが面倒です どう実装すれば、この型毎にわけずに、以下の実装のようにgetだけで値をとれるようになるのか 教えてもらえないですか。 template <typename T> struct Type2Type { typedef T OriginalType; }; class hoge { private: int _int1v; int _int2v; char _charv; long _longv; public: hoge() : _int1v(0), _int2v(0), _charv(0), _longv(0) {} void getInt1(int& v) {v = _int1v;}; void getInt2(int& v) {v = _int2v;}; void getChar(char& v) {v = _charv;}; void getLong(long& v) {v = _longv;}; template <typename T> void get(const string& name, T& t, Type2Type<int>) { if (name.compare("getInt1") == 0) getInt1(t); else if (name.compare("getInt2") == 0) getInt2(t); } template <typename T> void get(const string& name, T& t, Type2Type<char>) { if (name.compare("getChar") == 0) getChar(t); } template <typename T> void get(const string& name, T& t, Type2Type<long>) { if (name.compare("getLong") == 0) getLong(t); } template <typename T> void get(const string& name, T& t) { get(name, t, Type2Type<T>()); } }; void main() { hoge h; int int1v; int int2v; char charv; long longv; h.get("getInt1", int1v); h.get("getInt2", int2v); h.get("getChar", charv); h.get("getLong", longv); }
384 :
383 :2008/08/12(火) 15:22:57
ほんとはこんなかんじで1つのメソッドにまとめたいけど、コンパイルエラーになります template <typename T> void get(const string& name, T& t) { if (name.compare("getInt1") == 0) getInt1(t); else if (name.compare("getInt2") == 0) getInt2(t); else if (name.compare("getChar") == 0) getChar(t); else if (name.compare("getLong") == 0) getLong(t); } 'hoge::getChar' : 1 番目の引数を 'int' から 'char &' に変換できません。 上記のエラーがいろいろでますが、コンパイラがif文をみてくれるわけでないので、 型が一致しないのはそうだと思い、Type2Typeで分けてみたけど、 型毎にメソッドを分けないといけないのが面倒です。
>>384 こういうのでどう
template <typename T> void getInt1(T& v) { v = static_cast<T>(_int1v); };
template <typename T> void getInt2(T& v) { v = static_cast<T>(_int2v); };
template <typename T> void getChar(T& v) { v = static_cast<T>(_charv); };
template <typename T> void getLong(T& v) { v = static_cast<T>(_longv); };
こうとかな template<class T> T get(std::string name) { if (name.compare("i1") == 0) return static_cast<T>(i1); else if (name.compare("i2") == 0) return static_cast<T>(i2); else if (name.compare("f1") == 0) return static_cast<T>(f1); else if (name.compare("f2") == 0) return static_cast<T>(f2); return T(); } まあ同じことだが
実装はできたとして、設計上はそれでいいのか? どういう使い方するのかよく分からないけどさ
388 :
383 :2008/08/12(火) 16:36:33
>>385 , 386
おしえてくれてありがとうございます。例が悪かったです。すいません。
この方法って、structか、classをメンバにしたときとかにしたとき、コンパイルエラーになってしまいます。
struct XXX {};
template <typename T> void getString(T& v) { v = static_cast<T>(_strv); };
template <typename T> void getXXX(T& v) { v = static_cast<T>(_xxxv); };
389 :
383 :2008/08/12(火) 16:40:26
>>387 はい、xml等、なんらかの定義からC++のクラスをツールで作成して使おうと思っています。
その時に、名前でgetterとsetterを実装しておきたいという感じです。
なので、問題ないと思っています。
お勧めしないが最終奥儀 if (name.compare("i1") == 0) v = *((T*)(&i1)); else if (name.compare("i2") == 0) v = *((T*)(&i2)); else if (name.compare("f1") == 0) v = *((T*)(&f1)); else if (name.compare("f2") == 0) v = *((T*)(&f2)); これでなんにでも変換できるが、get<int>("f1")とかでもエラーがでないのが問題 もっとスマートな方法ないかな・・・
boost::anyみたいなことやるしかないだろう それか全部stringにしてboost::lexical_cast
boost::serializeで一度調べてみると幸せになれるかも
393 :
383 :2008/08/12(火) 16:54:37
>>391 どーも、どーも、boost::anyを考えた時は、void get(const string& name, any v) にしてみたんですが、
値をどうやって返してもらうんだ?、で、やめました。
内部クラスのholderのメンバが、ValueType held と値になっているから、値渡しでは無理なのかなぁと思っています。
>>392 ありがとう。boost::serializeにちょっくら行ってきます。
394 :
383 :2008/08/12(火) 17:49:58
>>392 まずはBoostC++Libraries第2版のserialization 4.4〜4.5を読んでみたけど、
幸せになれなかったです。どの辺を考慮してみるべきか教えてもらえないですか。
395 :
383 :2008/08/12(火) 19:19:52
>>391 anyでできました レスクレタカタアリガトウ CAnyハ自分用デス。
struct xxx {
xxx() : _strval("xxx") {}
string _strval;
};
class hoge {
private:
int _int1v; int _int2v; char _charv; long _longv; string _strv; xxx _xxxv;
public:
hoge() : _int1v(0x01), _int2v(0x02), _charv(0x03), _longv(0x04), _strv("boge"), _xxxv() {}
void getInt1(int& v) {v = _int1v;}; void getInt2(int& v) {v = _int2v;};
void getChar(char& v) {v = _charv;}; void getLong(long& v) {v = _longv;};
void getString(string& v) {v = _strv;}; void getXXX(xxx& v) {v = _xxxv;};
void getInt1(CAny& v) {v.Swap(CAny(_int1v));}; void getInt2(CAny& v) {v.Swap(CAny(_int2v));};
void getChar(CAny& v) {v.Swap(CAny(_charv));}; void getLong(CAny& v) {v.Swap(CAny(_longv));};
void getString(CAny& v) {v.Swap(CAny(_strv));}; void getXXX(CAny& v) {v.Swap(CAny(_xxxv));};
template <typename T> void get(const string& name, T& t) {
if (name.compare("getInt1") == 0) {CAny a(t);getInt1(a);t = any_cast<T>(a);}
else if (name.compare("getInt2") == 0) {CAny a(t);getInt2(a);t = any_cast<T>(a);}
else if (name.compare("getChar") == 0) {CAny a(t);getChar(a);t = any_cast<T>(a);}
else if (name.compare("getLong") == 0) {CAny a(t);getLong(a);t = any_cast<T>(a);}
else if (name.compare("getString") == 0) {CAny a(t);getString(a);t = any_cast<T>(a);}
else if (name.compare("getXXX") == 0) {CAny a(t);getXXX(a);t = any_cast<T>(a);}
}
};
hoge h; int int1v; int int2v; char charv; long longv; string aaav; xxx xxxv;
h.get("getInt1", int1v); h.get("getInt2", int2v);
h.get("getChar", charv); h.get("getLong", longv);
h.get("getString", aaav); h.get("getXXX", xxxv);
多次元配列クラス作ってたんだけどoperator[](読み方分からん)の実装が悩む。 boostと違って、次元数も要素数も自由自在だから、ある程度再帰的な機構が必要なんだよね。 とりあえず配列クラスと要素クラスを作ってそれぞれに要素クラスを返すoperator[]と 配列タイプTの参照を返すキャスト演算子を作ってできたんだけど、printfみたいな 引数の型が分からない場合にわざわざキャストしてあげないといけなくて めんどいんだけど何とかならんかね
streamやってみたけど〜と〜が曖昧みたいなこといわれて通らんかった。 あきらめてT* operator->を定義して妥協した。
例外発生時にログを残したいんだが、throw履歴みたいのって参照できないの? 最悪デバッグ時でもいいんだが、そっちはスレチか・・・ ちなみにVisualStudio2008
>>399 判然としないがあれか、例外発生時にどんな関数がどんな順番で呼ばれてたわかるようなやつか?
本当に『わかればいい』ならDebugビルドで例外をcatchせずにmainの外まで放り出せば
デバッガは例外throw時点まで巻き戻して止まるからデバッガの呼び出し履歴ウィンドウを見ればいい。
プログラム側から呼び出し履歴を見る方法があるのかは知らん。 少なくとも言語仕様ではない。
レスさんくす! そういうこと。本当はリリース版でも正確なログを残したいんだよね^^; デバッグ時に例外をキャッチしない方法があるか調べてみますわ
自分が投げる例外だけ記録すればいいなら例外クラスのコンストラクタにでもログ記録用のコード書けば?
>>398 struct Hage {
int n;
Hage():n(){}
Hage(int an):n(an){}
};
std::ostream& operator<<(std::ostream& ost, const Hage& o){
ost << o.n;
return ost;
}
std::istream& operator>>(std::istream& ist, Hage& o){
int n;
ist >> n;
o = Hage(n);
return ist;
}
void f(){
Hage a(10),b;
std::stringstream ss;
ss << a;
ss >> b;
std::cout << b << std::endl; // "10"
}
bad_allocとかbad_castとかの発生場所も知りたいんだよね^^; 最悪リリース時は自分のログだけでも残すようにしてみるよ
>>403 ありがとう。でも問題はそれだけじゃないから。、やっぱりアロー演算子で何とかするぜ。
ていうか、見てくれる人がいるならソース上げたいんだけど、ダメだろうか?
407 :
405 :2008/08/13(水) 19:07:33
STLを勉強していて思ったのだが、ずいぶんと関数名や引数に一貫性が ないところが見受けられるよな。範囲に対して範囲で検索するアルゴリズムの 場合で言うと、最初の範囲を検索するのsearchに対して、最後の範囲を 検索するのがfind_endとか。まぁごっちゃに開発したのを統合したから こうなったんだと思うが、こういうのって一度標準として決まっちゃうと 改善されないのかね。互換性は失うけど、後々までこういう不手際が 残るのも問題だと思うが。そのへんて、C++0xで整理されないのかな。
creat頑張れ。
>>408 我々から見ると単に一貫性を欠いてるだけに見えるけど
英語ネイティブな人たちにとってはあれで自然なのかも
なんじゃそりゃ・・・
413 :
デフォルトの名無しさん :2008/08/14(木) 10:12:03
typedef void (*set)(int); class AAA { public: void setHoge(int a){}; }; class BBB { public: void setFugo(int a){}; }; set hoge = &AAA::setHoge; set fugo = &BBB:setFugo; ↑ この2行がエラーになります。 intの引数を取る関数ポインタとしてAAAとBBBのsetHogeとsetFugoを扱いたいのですが、どうすればいいでしょうか。 AAAとBBBは親子関係や親クラスが一緒とかないです。共通の親クラスの関数をオーバーライドしないとできないと思っています。 typedef void (OYA::*set)(int); class OYA { public: virtual void setOYA(int g) = 0; }; class AAA : public OYA { public: void setOYA(int g) {} }; class BBB : public OYA { publc: void setOYA(int g){} }; set hoge = &AAA::setOYA; set fugo = &BBB:setOYA; ↑ これだといけるけど、親クラスを作って名前を合わせないといけない。
class AAA { public: static void setHoge(int a){}; }; class BBB { public: static void setFugo(int a){}; };
search_nの二項叙述関数を受け取る形式 search_n(beg, end, count, value, binary_predicate) これも、ミスらしいね。二項叙述関数受け取るくせに、その叙述関数の2番目の 引数はvalueで固定。この場合、STLの一貫性に従うなら単項叙述関数を受け取るように して、二項にしたい場合はbind2dなどを使うようにするべきだった。 これなら単項でも二項でも二項のどちらの引数としてでも働く。
416 :
デフォルトの名無しさん :2008/08/14(木) 10:22:21
>>414 ごめん、クラス内でインスタンス毎の変数をさわりたいから、staticはだめなんす。
親クラスを作って名前を合わせる以外に方法はない
>>416 そのインスタンスはset hoge = …の時点で分かってるの?
それとも呼び出すまで分からない?
前者ならboost::bind+boost::functionでなんとかなる
419 :
デフォルトの名無しさん :2008/08/14(木) 12:39:50
>>417 残念。ありがとう。
>>418 set hoge=・・・の時点ですでにわかっています。関連のないクラスの引数、戻り値が一緒なだけのメソッドを、
どこかに保存しておいてあとでまとめて呼び出したいんです。
というわけで、boost::bindとboost::functionを見てみます。ありがとう。
#include <iostream> using namespace std; //関数宣言 float *lineIntersect(float *L1Point, float L1Slope, float *L2Point, float L2Slope); int main() { float tmp[2]; float sl1 = 1/2; float sl2 = 1/4; float pt1[2] = {10, 20}; float pt2[2] = {20, 10}; *tmp = *lineIntersect(pt1, sl1, pt2, sl2); cout << tmp[0] << "___" << tmp[1]; return 0; } float *lineIntersect(float *L1Point, float L1Slope, float *L2Point, float L2Slope) { float ans[2] = {0, 0}; ans[0] = (L1Slope * L1Point[0] - L2Slope * L2Point[0] + L2Point[1] - L1Point[1]) / (L1Slope - L2Slope); ans[1] = L1Slope(ans[0] - L1Point[0]) + L1Point[1]; return ans; } cpp(26) : error C2064: 1 引数を取り込む関数には評価されません。 cpp(28) : warning C4172: ローカル変数またはテンポラリのアドレスを返します 2つの直線が与えられたときその交点を返す関数を記述してみたのですがエラーが2個出てなおせません;; 誰か御助けお願いします
まずエラーと警告をよく読んで意味を考えてみよう。
>>420 ・26行目のエラーはケアレスミス。このくらい、自分で見つけろ。
・28行目の警告は初心者にありがちなミス。配列を返すことはできないので、2変数返すには工夫が必要。
・そもそも、配列についてまともに理解できていない。勉強しなおすことをお勧め。
・実数を扱うなら、特にそうする理由がないならfloatではなくdoubleを使うべき。
・1/2は整数演算しか行なわれないので、0になる。
以下省略。
出直すなら、初心者スレへどうぞ。
419です。
>>417 , 418
結局、関数ポインタを内包するクラスをつくって、templateで解決しました。
boost::bindとboost::functionを見てクラスにすればいいのか、という感じで解決しました。ありがとうございます。
419です。教えてくれた方、ありがとうございます。こんなかんじでつくりました。 最終形はCCCはvectorに入れたかったので、 boost::anyみたいに内部クラスでテンプレートを使うようにして入れるようにしました。 template <typename T> class CCC { public: typedef void (T::* set)(int); private: T& _t; set _func; public: CCC(set func, T& t) : _func(func), _t(t) {} void invoke(int v) {(_t.*_func)(v);} }; class AAA { public: void setHoge(int a){printf("AAA %d\n", a);} }; class BBB { public: void setFugo(int a){printf("BBB %d\n", a);} }; void main() { AAA aaa; BBB bbb; CCC<AAA> cccA(&AAA::setHoge, aaa); CCC<BBB> cccB(&BBB::setFugo, bbb); cccA.invoke(1); cccB.invoke(2); }
swapを実装しといた方が便利だし実装も楽だよとか?
確かにそうですね。copyとかも付けます。 特になさそうなので、ありがとうございました。
単品でnewしたものをdeleteで開放するのはわかるんですけが、例えば int *p = new int[10]; delete [] p; のような場合、ソース上だとdeleteするときサイズがわからないけど配列分 開放されているのですよね?ということは実際にはどこかにサイズが保持 されているってことなんでしょうか? それなら[]無しのdeleteでもきちんと消すことが出来るんじゃないかとか考え ていたんですけど、仕様云々なんだろうか。 興味本位の質問ですが、アセンブラわからないのでお手柔らかに教えて いただきたい。
仕様
>>429 その考えでいくと、単品の new でもサイズが 1 であることをどこかに保存しないといけない
ことになる。これはゼロオーバーヘッドの原則に反する。だから仕様。
区別したくないんだったら常に new int[1] として全部 delete [] で解放すればいいんじゃね?
まじめな話、動的配列には常に std::vector や boost あるいは tr1 の array を使うのがおすすめ。
これで自分で使う new/delete は単品だけになる。さらに各種スマートポインタを使えば delete を
直接使うことも無くなる。
よく継承するクラスはデストラクタをvirtualにしろってあるけど、 基底クラスを直接deleteしない場合は問題ないよな? 効率的にあんまりvirtual使いたくないんだ。 あと、基底クラスでvirtualな関数を、派生クラスで virtual外すことに意味ってある?結局virtualになる気がするが・・・
基底クラスを直接deleteしないなら、基底クラスのデストラクタはprotectedにしとくといいかもしんない virtualは、書いても書かなくても同じなら、わざわざ書かなくていいんじゃない
書いても書かなくても同じなのかがよく分からん。リークしなけりゃいいが デストラクタをpublic以外に置くのはいいかもな
基底の関数がvirtualなら、そのクラスの全派生クラスの、同名の関数は virtualと書かなくても仮想関数になる(仮想関数テーブルを上書きし、そこから呼ばれる)。 もちデストラクタも。これは単にオーバーライドのルール。 あとデストラクタをprotectedにするのは、(わかってそうだけど一応)基底クラスのポインタを deleteするときに外部から基底クラスのデストラクタを呼べなくする。 つまり派生クラスのpublicなデストラクタを外から呼び、派生が基底のデストラクタを 呼ぶことでのみdeleteできる(=基底のポインタからはdelete不可)。 んだが、基底のデストラクタをprivateにしちゃうと、↑と似た理由で 継承も禁止しちゃうので注意。継承禁止の意味で使えるけど。
了解!サンクス!
437 :
429 :2008/08/19(火) 16:00:47
う〜ん、仕様ということですか。ありがとう。 例えでnew[]を[]無しのdeleteと書いたけど、もしdelete[]でどこかの サイズを参照して開放しているならばポインタから確保されたサイズ を得る方法があるんじゃないかと思ったまでです。
>>437 もちろんサイズは保持しているよ。
[] 無しでも領域は開放されるけど、個々のデストラクタは呼ばれない。
先頭アドレスのひとつ前に保存してる実装があると聞いた事あるけど 普通は自分じゃ弄ること無いからな。
コンパイラ依存だった気がする
((int*)ptr)[-1] だっけ?VCならいけるんじゃない?
いや、デストラクタの無い int だとそこには入ってないと思うよ。 自分でクラス定義してそれでやってみるとわかる。
あー、そうじゃなくてptrはデストラクタのあるクラスへのポインタね。 要素数は確かintサイズだからこうなるよね?違ったっけ?
>>437 だから []なしの delete が要素数を参照するようにすると
常に、[]なしのnewしたときにも要素数が必要になるということを
>>431 が言っている
ここで質問していいのか分かりませんが・・・ プリコンパイル済みヘッダーにテンプレートやインラインが含まれている場合の 処理ってどうなるんでしょう。中間ファイル作ってリンクってできないですよね?
コンパイルの途中の状態をそのまま保存してるんだけど。
それぞれのソースファイルで関連のないヘッダーはインクルードしない方がいいと思うんだけど、 プリコンパイル用ヘッダーの中に何でもかんでも放り込むのはやっぱり良くないのかね?
>>448 名前汚染が怖くないなら(ちゃんとnamespaceで囲ってあったり冗長な名前を使っているなら)、
何でもかんでも放り込んでおくのはそんなに悪い考えというわけでもないと思う。
どうせ名前の数が増えたってコンパイラが名前の探索に必要な時間は高々O(logn)なんだし。
例えばboostとSTLのよく使うヘッダーをどばーっとPCHでインクルードしておいて、
(可読性とか念のために)本当に使うところでも#includeを書いておけば、インクルードガードのおかげで
結構速くコンパイルできるようになるんじゃないかな。
>>448 何でも入れるヘッダは良くない。
>>449 ひとつのソースのコンパイルにかかる時間は問題じゃないと思う。
再コンパイルの必要なソースがいくつ発生するかってところが問題でしょ。
>再コンパイルの必要な プリコンパイルヘッダの話でしょ? 標準ライブラリみたいな通常変わらないヘッダを入れるものだよ。 自分らが書くヘッダを入れちゃ駄目だから、再コンパイルについては逆に大丈夫。 むしろプリコンパイルヘッダに都度インクルード文を追加していくのも間違い。 その都度プリコンパイルヘッダ使ってるソース全部再コンパイル対象になるから。 先に使いそうなのを入れておく。
>>449 本当に使うところでインクルードするならpchでインクルードしなくていいと思うんだが。
本当に使うところでインクルードしなくても良くなるから中途半端でわ?
ソースファイルの独立性が低くなるから、自分はpchでインクルードしない。
やるとしても開発時のみにする。
>やるとしても開発時のみに 超同意。 コンパイル時間短縮だけが目的だしね。 俺の場合、一通り作り終わったらコメントアウトしてる。
pch使うとビルド時間が逆に短縮できる場合もあるのでは? ライブラリAを複数のソースからインクルードするとそれぞれのソースで 展開されて時間がかかる場合にpchつかうんじゃないの?
プリコンパイルドヘッダのインクルードをコメントアウトしても コンパイルできるように書いてはいるが、実際に外したことはない。
boostなんかを使うときはプリコンパイルの恩恵がよく分かる
ちょっと前まで、ディスクの空きがきつくなってくると *.pchをごっそり消してしのいだもんだw
そもそもコンパイルと言ってもmakeとか使って、変更された部分だけやるんだから、 プリコンパイル済みによるありがた味なんてそんなに出ない。 全体に影響が出るような変更はほいほい行うもんでもない。 てか、そんなに大きなプログラム作ってやるもんかっ うえっ、、、うえぅ、、、 作れないんじゃないぞっ 作らないんだからな うぇ、、うぇ、、
460 :
452 :2008/08/21(木) 17:36:45
452の前半は変なこと書いてたな。ごめん。
461 :
452 :2008/08/21(木) 17:48:18
>>449 >例えばboostとSTLのよく使うヘッダーをどばーっとPCHでインクルードしておいて、
>(可読性とか念のために)本当に使うところでも#includeを書いておけば、インクルードガードのおかげで
>結構速くコンパイルできるようになるんじゃないかな。
ちょうどboost使ってるソースがあったのでやってみたら、体感できる効果があった。
これからは開発時はそうしようっと。
gccなら.hと同じディレクトリに.gch置いておけば、 .hの代わりにプリコンパイル済みの方を優先して読み込んでくれてる(気がする。)
unsigned int i = 0; int j = i - 1; このようなコードがあったとき,jが-1になることは規格で保証されていますか?
int j = static_cast<int>(i) - 1; int j = satatic_cast<int>(i - 1);
>>463 負数の表現方法が決まってなかった気がするのでだめだと思う。
つかその前に符号なし整数が0より小さくなった時点で処理系定義かと。
466 :
デフォルトの名無しさん :2008/08/23(土) 00:07:49
符号なし整数はどんなに頑張っても0より小さくなることができないんだが
>>463 i - 1 が UINT_MAX になることは保証されているけど、それを int に入れようとしても
ほぼ確実に INT_MAX より大きいんで、値は処理系定義となってしまう。
>>463 i - 1 は (unsigned int) - (signed int) なので、
(unsigned int) - (unsigned int) に変換してから計算することになっている。
したがって、この式の型は (unsigned int) で、0u - 1u = MAX_UINT
結果として、MAX_UINTは多くの処理系で(signed int)で表せないので、
代入される値は処理系定義。
0u -1uがUINT_MAXになるのって規格書のどの辺に書いてあるの?
1の補数を使ってる処理系もあるから普通に考えたらアウトだろ
>>469 これかな?
3.9.1 Fundamental types p4
> Unsigned integers, declared unsigned, shall obey the laws of arithmetic modulo 2n where n is the number
> of bits in the value representation of that particular size of integer.41)
> 41) This implies that unsigned arithmetic does not overflow because a result that cannot be represented
> by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest
> value that can be represented by the resulting unsigned integer type.
463は代入のとき左辺の型に全部合わせてくれると思ってるんじゃないかな。 演算子の優先順位から、 int j = i - 1は、まず先にi - 1が先に評価されるわけで、jは関係しない。 減算演算子はその左の項から評価されるから、iの型に1が暗黙変換されて 当然その結果もunsignedになる。でその値がjの型にキャストされてjに代入される。
>>473 >>減算演算子はその左の項から評価されるから、iの型に1が暗黙変換されて
ちょっと違うんじゃないかな。
柴田ボウヨウの本によると、片方のオペランドがunsignedなら他方をunsignedにすると書いてある。
右か左かは関係ないんじゃないかな。
おまえら汎整数拡張は一応覚えておかないとたまにハマるぞ
476 :
デフォルトの名無しさん :2008/08/23(土) 13:24:41
unspecified behavior
絶対値が大きい奴に合わせて、char系だけ例外だと誰かがいってたようなきがするけど思い出せない
478 :
デフォルトの名無しさん :2008/08/23(土) 13:35:49
どこの気違いだよ、そんなこと言ってんのは
C99でまた微妙にルールが変わってるんだよな ほんとややこしい
C99はとりあえずC++では考えなくていいだろ
>>478 まさに汎整数拡張では?
short == intの環境なら、確かにchar系だけが対象になる。
482 :
デフォルトの名無しさん :2008/08/23(土) 21:57:57
日本語でおk
483 :
デフォルトの名無しさん :2008/08/23(土) 22:50:52
VB系しか経験ないんですがC++でいい本ありますか? 本屋にはロベールのC++教室とか独習C++とかありました。 そこそこ難度高くても1000ページ以内で無駄に紙面を使ってない本がいいです MFCとかWinAPIまではあまり触れてなくても構いません VB.NETである程度オブジェクト指向は理解してるつもりです
485 :
デフォルトの名無しさん :2008/08/23(土) 22:59:15
最近C/C++の基本的な部分をやっと習得し終えました。 (といっても独習C/C++知識を一通り理解したレベルですが・・) 知識が不十分なところがあり、効率は遅々としたものになるのはわかっているのですが C/C++によるWindowsアプリに挑戦したいと思っています。 そこで、Win32APIかMFCどちらかにまず挑戦したいと考えているのですが、どちらがお勧めでしょうか? また、それぞれの比較・メリットデメリットなど教えてもらえるとうれしいです よろしくお願いします
488 :
デフォルトの名無しさん :2008/08/24(日) 18:18:55
> Win32API: 低レベル、面倒 あれが面倒ね・・・ C++ 使いがそんなこと言ってるのは技量不足に他ならない # MFC はいわばクラシック C++
IT土方乙
>>485 どういう目的でC++やるのかによるかもしれないが、通常なら
断然WIN32APIからやった方がいいと思うよ。
MFCは当然API使っているから、後でMFC使う時も理解が深まる。
っていうか、API知らないとMFCでトラブった時に自力で解決できない。
MFCを使う場合は、VSがメソッドの追加とかをサポートしてくれる
楽な機能があるから、いい加減にソフト作るときは楽。でもそれなら
C#とか使えばいいし、正直いまさらやることもない気がする。
WTLはAPIの薄いラッパーみたいな感じなので、結構使いやすい。
APIがある程度わかってきたら、これで楽するといいかも。
491 :
デフォルトの名無しさん :2008/08/25(月) 20:33:26
X* p = 0; delete p; このコードは合法ですか? つまりdeleteに空ポインタを渡してもOKですか?
問題ない。
493 :
491 :2008/08/25(月) 20:42:06
でも0を使うのはお勧めしない。 C++0xにはnullptrも入ることだし。
ドラフトだけ読んで言ってもらっても。 ISO/IEC14882:2003では 0 を推奨しているので 0 でいい。
私は 0 推奨に一票
0非推奨の根拠って0を代入した整数型の変数をポインタに代入してもヌルポインタになる保証がないからだっけ?
ポインタやfloatのクリアにmemset使うなってだけのこと
>>499 そんなことやってコンパイル通る?
もちろんreinterpret_cast使ったら通るだろうけど
C++0xで0が推奨されない理由としては、ポインタではなく数値と解釈されうるせいで、
オーバーロードで自分の予想に反する関数が呼ばれたり、
変な型が型変換にかかってポインタとして扱われたり、
そういう理由だったからだと思う
もっとも、一般には現行のC++でそれを防ぐ術はないけど
もちろん、(void*)0をNULLと定義して(一般のC++ではNULL=0)、
NULL代入するたびにキャストかますのであれば防げるけどね
なんでC++じゃNULLを(void *)0って定義されてないか知ってる?
505 :
503 :2008/08/26(火) 06:12:20
typedefについて質問です typedef int myint;と宣言した場合、 int a; myint b; a=b; 等と行った場合、intにintを代入するよりオーバーヘッドはあるのでしょうか
オーバーヘッドはありません。typedefは単なる別名を定義する修飾子であり、myintとintは全く同じであります。
ありがとうございます! これで心おきなくtypedefできます
いろいろベンチマークとってたら 組み込み型変数はコンストラクタの初期化リストで初期化するより 代入の方が高速になったんだけど・・・これって普通?
511 :
503 :2008/08/26(火) 12:52:44
>>506 C++0xで0が非推奨になる理由=C++03で0を使うときに注意すべき事項だろう
というか最初にC++0xの話題振ったのは
>>494 だけど
>>510 そんなことになる理由はあんまり考えられないなぁ。
テストしたコンパイラ、とかベンチマークのコードとか挙げてもらわないとなんとも。
長くて悪い 呼び側 int i=100000000; int c=clock(); while(i) { fw::math::mat44 m; --i; } c=clock()-c; 10回の平均をとった inline mat44::mat44() : _11(1.0f),_12(0.0f),_13(0.0f),_14(0.0f),_21(0.0f),_22(1.0f),_23(0.0f),_24(0.0f),_31(0.0f),_32(0.0f),_33(1.0f),_34(0.0f),_41(0.0f),_42(0.0f),_43(0.0f),_44(1.0f) ----1.900s---- inline mat44::mat44(){ _11=_22=_33=_44=1.0f; _12=_13=_14=_21=_23=_24=_31=_32=_34=0.0f; } ----1.370s---- 最適化の有無、デバッグの有無で優劣は変わらず そんなはずないって言われると気になるな・・・
コンパイラの吐いたアセンブリソース読んで勝手に納得しろ
何でそんな言い方するの?
ご・・・ごめん///
代入順が違うから等価じゃない
マジだ、代入順同じにしたら同じになった! ここから先は514の言うようにアセンブラと闘わないと分かりそうにないな^^;
依存するクラスとはどういう意味ですか?今勉強してる本に書いてあったのですが解説がなかったので 調べてみたけど分からなかったので教えていただけませんか。 //============================================================= // Renderer.h // レンダラークラスの定義 //============================================================= #ifndef _Renderer_h_ #define _Renderer_h_ #include <d3d9.h> #include <d3dx9.h> #include "Common.h" //============================================================= // 依存するクラス //============================================================= class Scene; //============================================================= // Renderer // レンダラークラス //============================================================= class Renderer { public:
>>519 いそん 【依存】
(1)他のものにたよって成立・存在すること。
「食糧の大半を外国に―する」
要するに //============================================================= // 依存するクラス //============================================================= class Scene; を記述しないとコンパイルできないって事ですか ありがとうございます!
>>513 あー、初期化リストだとシーケンスポイントが挟まるから、最適化機がいろいろがんばらないと
同じ値の設定をまとめるような形にはならないのかもしれないね。
マトリョーシカ(ロシア語だったような)っていうコンパイラ持っていませんか? いい加減なコードもコンパイラを通るって有名なんですが?
訂正 マトリョーシカ(ロシア語だったような)っていうコンパイラ持っていませんか? いい加減なコードもコンパイラを通るって有名なんですが。
いい加減なコードが通るコンパイラがいいのか?
いい加減な動作をしそうな気がする
いい加減な人間が実行するから問題なし
>>523 そんなコンパイラ聞いたことないぞ
専門学生が卒業制作で作ったようなやつか?
インライン展開についての質問です あるクラスのオペレータのオーバーロードで __inline const hoge &hote::operator + () const; とするとインライン化されるのですが __inline const hoge hote::operator + () const; とするとインライン展開されずに関数呼び出しになります 内部処理は*thisを返しているだけです インライン展開できない条件を調べてみたところ、以下の条件が当てはまるのかと思うんですが 「コピー構築されたオブジェクトを値で受け取る関数を、-GX/EHs/EHa でコンパイルした場合。」 良く理解できず、解決方法が分かりません。どうすれば値渡しでインライン展開できるでしょうか
細かいことは気にするな。 それよりやるべきことはいっぱいある。
細かいミスは気にしないでください 空のデストラクタを定義していたんですが、それをやめたらうまくいきました。 値渡しだとデストラクタが走るのは分かるんですが、インラインできない理由はよく分かりません^^;
ということは、例外が投げられたときにデストラクタを呼ぶコードを吐かないといけないからだな。 529にあるコンパイラオプションはどれも例外処理を使用可能にするものばかりだ。
なるほど、そういうことでしたか。スッキリしました^^
マトリョーシカってプロトコルスタックに例えられることがあるよね。入れ子ってことで。
いや、ないよ
にじゃなくてがだろ
文字列リテラルってstring型に暗黙変換されますよね? しかし bitset<5> bs("10101"); //エラー bitset<5> bs(string("10101")); //OK という結果になるのですが、なぜ前者のケースでstring型に暗黙変換 されないのでしょうか?
引数がconstだから
暗黙変換されないって
string str = "abc"; が可能なので、const char* からstringへの暗黙変換は定義されてると 思うのですが。
ん、bitsetのbasic_stringを受け取るコンストラクタがテンプレートだからじゃないの? template<size_t N> class bitset { public: // こっちが本物:エラーになる template <class CharT, class Traits, class Allocator> explicit bitset(const basic_string<CharT, Traits, Allocator>&) {} // 確認用:こっちはOK explicit bitset(const string&) {} }; const char*からでは、basic_stringのテンプレートパラメータを推論できない ちなみにC++0xではconst char*を受け取るコンストラクタが追加される
>>542 ありがとうございます。
メンバテンプレートのコンストラクタだからですね。
クラス定義の末尾で ; を落としただけなのに 「istreamが再定義されています」とかわけの分からないエラーが出るのは悔しいです。 (クラス定義の次の行にstd::istreamを戻り値に持つ関数が定義されている) ちゃんと「クラス定義の末尾に ; を付け忘れてますよ。ふふふ。」と優しく教えてください。
>>544 大丈夫、そのうち自身の脳みそがそう指摘してくれるようになるから。
546 :
デフォルトの名無しさん :2008/08/29(金) 10:48:45
テンプレートについて質問があります。 以下の[Base.h]でDerivedを宣言した時にBase<T>の型は解決して [Base.cpp]ではBase<int>::funcがコンパイルされると思うのですが、 リンクエラー(Base<int>::funcがない)になります。 これはどう理解すればよいでしょうか? [Base.h] // ヘッダファイル template <typename T> struct Base { T func(void); }; // テンプレートクラス struct Derived : Base<int> {}; // 型の解決(?)したテンプレートクラスを継承したクラス [Base.cpp] // 実装 #include "Base.h" template<typename T> T Base<T>::func(void) { return 0; } [main.cpp] #include "Base.h" int main(void) { Derived d; d.func(); // リンクエラー return 0; }
テンプレート全般は、普通、宣言と実装を別けられない。 ヘッダにインラインで書くべき。 exportキーワードで別けられるコンパイラもあるが、gccもBCCもVCもダメ。
549 :
546 :2008/08/29(金) 11:26:32
>>547-548 どうも。
テンプレートでは宣言と実装を分けないという基本的な考え方は理解しているのですが、
それは結局はコンパイル時に型解決ができないからですよね。
>>546 のコードはどうして型解決ができていないのかというのが質問の趣旨です。
例えば[Base.cpp]内で
Base<int> dummy;
とダミー変数を用意してもダメでした。
コンパイラの気持ちになって考えればよく分かる
なんか基本が出来てないような気がするが・・・ 実装というのは関数の実装だ。 template<typename T> T Base<T>::func(void) { return 0; } ↑これがダメなの。 型を全部指定したらそれはもはやテンプレートではない。 struct Derived : Base<int> {.....のメンバ関数はcppに実装を書いても通る。
Base.cpp に template class Base<int>; って書くといいよ
だよな… それなら最初からint func(void)にしとけばいいじゃんってことになるからな
554 :
546 :2008/08/29(金) 11:48:58
# 結果を書いている途中で
>>551 以降のコメントが…。
# とりあえず載せます。
コンパイラの気持ちは結局わからなかったのですが、
結果は明らかになりました。
[Base.cpp]
#include "Base.h"
template<typename T> T Base<T>::func(void) { return 0; }
Base<int> dummy;
// ↑これだけだとアウト:オブジェクトファイルBase.oの中身は空っぽ
// ↓これを加えるとOK:Base.o
void func(void) { dummy0.func(); }
つまり、コンパイルされるのは用いられている関数のみでした。
クラスインスタンスを生成しても、使われなかった関数はコンパイルされない、というのは意外でした。
555 :
546 :2008/08/29(金) 11:50:54
クラスhogeにメンバa,b,cがあり、hoge h1,h2,h3を作ったとして、h1=h2+h3とやった際に h1.a=h2.a+h3.a h1.b=h2.b+h3.b h2.c=h2.c+h3.c と同等のパフォーマンスを出したく、調べていたらRVOと言う方法を見つけたんですが __inline hoge hoge::operator + ( const hoge &v ) const { return vec3(x+v.x,y+v.y,z+v.z); } とした場合、アセンブラ命令で15命令になってしまいました RVOではオブジェクトの作成&削除は避けれても値の複製事態は避けられないのでしょうか?
557 :
デフォルトの名無しさん :2008/08/29(金) 11:59:12
質問です。 関数ポインタについてなのですが void test(IHoge*(func)(const char*)); という関数に、 CHoge* hoge(const char*); を渡すことができず、エラーになってしまいました。 IHogeはCHogetの基底クラスのため、暗黙のアップキャストが行われるのを期待したのですが・・・ hoge関数の返り値を変更せずに解決する方法はありませんでしょうか?
funcの前に*
>>557 IHoge* hogeWrapper(const char* s) { return hoge(s); }
を渡せばいいんじゃない
>>558 うーん、足してみたけどダメでした
>>559 結構な数のラッパーを書くことになるので、避けたいところです
>>557 キャスト使うとか?
↓こんな感じ。
// 関数ポインタの型をtypedefしておく。
typedef IHoge*(*RetIHogeFun)(const char*);
// test関数に渡すときにキャストする。
test((RetIHogeFun)hoge);
>>561 できました!
なるほど、関数ポインタ型にキャストしてやる(書きやすいようにtypedefもしてやる)わけですね。
ありがとうございます。
たとえばvectorのメンバを持ったクラスを設計するとき ヘッダーでincludeせずcppの中でvectorをincludeする書き方 ってどんなものがあるでしょうか。 とりあえずメンバを*voidにしておくくらいしか思い浮かばない・・。
「pimplイディオム」でググれ
pimplイディオム
あれタルいよな
567 :
563 :2008/08/29(金) 16:39:25
pimplイディオム・・・なんとなくわかったようなわからないような。 もうちょっと学んでみるけど、これ使ってもポインタにするしかない? それtも書き方次第なのかな。
vectorに限らず、実体をメンバに持つには、vectorのサイズがわからないと無理。 サイズを知るには実装部を見せるしかない。 なお、ポインタの他に、関数の引数や返り値とする場合も サイズなしで宣言だけで可能。 でもメンバは無理。 (無茶するならExceptionalC++にchar[]で確保する方法が一応あったけど) で、おまいが欲しているのはvectorの実体か? void*を持たせて代わりにするなんてのは、vectorへのポインタ以外にあり得ないが。
569 :
563 :2008/08/29(金) 19:44:51
>>568 そう、cppでキャストして使う方法。
方法ということで*voidと書いたけど、もしpimplイディオムで実体持たせながら実現
できるならポインタがらみの問題も排除できるかな〜と。
簡単にはいかないようなので、ポインタがらみで問題を増やすなら素直にinclude
することにします。ありがとう。
pimplイディオムというものを知らなかったので勉強になりました。
570 :
デフォルトの名無しさん :2008/08/29(金) 20:21:48
先生お願いします Win32ではない標準のC/C++で他アプリを起動するには Cのexec system popen のどれかを使用すると調べましたが 他にどのような手段があるのかご教授頂きたく 検索してもWindowsAPI関連サイトが多すぎて歯がゆいっす
spawnとか? どれも最終的にはCreateProcessが呼ばれる 気にしてどーすんの
標準のC/C++にはsystem()しか無いだろ
エラー処理や完了待ちを考えると標準でがんばるのはつらい
574 :
デフォルトの名無しさん :2008/08/30(土) 04:00:20
いや、system() さえあれば何でもできるぞw
よく、「global変数はなるべく使うな」といわれますが、 つまり、std::coutは窓から投げ捨てろという事ですか?
gotoを躊躇無く使える結城がほしい 誤変換残しちゃえ
>>575 cout を使う関数よりは ostream を引数に取る関数のほうが汎用性が高く再利用しやすいということ。
>>575 実際のところ、その言葉の本質は「大きなスコープで、読み書きされる」ことにあります。
coutから値を取得して本処理に影響を与えるようなコードは問題が有ると言えます。
coutなどは変数なのは、抽象インターフェイスを持たせるためで、
状態を保持させるのが目的ではありません。
グローバルであっても、読むだけの変数(定数)/書くだけの変数(cout他)は、
一般的には許容されと思います。
Simple is best. に従うと、グローバル変数を使うのも一概には悪いとは言えない。 グローバル変数使うなって言うのはプログラムが規模が大きいときに そんなものが沢山あると収拾がつかなくなるからであって、1画面に 収まるようなショートプログラムなんかでは躊躇無く使って構わない。
580 :
デフォルトの名無しさん :2008/08/31(日) 00:29:41
std も、ある意味「グローバル変数」なんだが
>>578 >ショートプログラムなんかでは躊躇無く使って構わない。
そういう場合は害もほぼ無いので基本的には同意ですが、慣れも大事ですよ。
短いプログラム程、グローバル変数なんて無くても困りませんし、
困ってしまう人は、大きなプログラムでもグローバル変数を使ってしまうでしょうからね。
583 :
582 :2008/08/31(日) 00:43:01
>>171 金額もアレだけど、
それ以上にカードのみ+ドルだしな。
俺は買う気無いけど、あの売り方は流石にどうかと思う。
誤爆スマン
586 :
デフォルトの名無しさん :2008/08/31(日) 01:09:11
理解度 581 <= 578 ≪ 577
581 (←別の話→) 578,577 577の「ostreamを引数」 = 578の「抽象インターフェイス」 つまり 理解度 586 ≪ 577-581
588 :
デフォルトの名無しさん :2008/08/31(日) 02:53:08
ということは 581 は自分が何の話に参加しているのかさえ理解していないとまで言いきるのか なかなか辛辣だな
int& a = hogea, b = hogeb, c = hogec; と書いたらaもbもcも参照になりますか?
俺はそういう「ちょっとした疑問」は、とりあえず試して確認するようにしている。 int& a = hogea, b = 1; と書いてコンパイルが通るかとか。 もちろん、厳密には規格に従っているか確認しなければいけないがね。
型名のみの宣言で無い場合、&の修飾対象はaのみになるので aしか参照型のintにならない。
>>589 複数の変数を同時に宣言することについて。
メリット
・型を書く必要が無くなり、ソースの文字数を減らせる。
デメリット
・*や&を含む場合、その型名をスマートポインタや
テンプレート引数に変更すると壊れる。
・
>>591 の仕様を知らない人が、ソースを誤読する。
(知らない構文と思うのでなく、勘違いしたまま読み進めてしまう)
全ての修飾が除かれるわけではなく、例えば、
volatile int a=0;
volatile int* b[]={&a}, c=a;
のとき c は volatile int になる。
そういう面倒な仕様を考えると 基本的に複数行に分けて書いた方が良い
C++0xでいろいろ拡張されるようですが、既存のライブラリの問題点を 改良する動きってあるのでしょうか。一貫してない命名規則とかvalarray のような使い勝手の悪い設計とか。wiki見てもあんまりそのあたり書いて ないですよねぇ。
下位互換を取っ払うわけがない
基本的には互換性重視じゃない? 今は組み込み系にも広く使われてるんだから、勝手に変えられたら困るなあ
別に組み込みには従来のコンパイラ使えばいいだけだし。 互換性互換性言ってたらいつまでたっても汚いまんまではないの。
>>598 Cの標準化以前の時代からの互換性を引っ張りつづけてるんだから、
いまさら方向転換なんてできないよ。
そういうの嫌いなら一ヶ月ごとにコンパイル通らなくなるD使えばいい。
古い設計残しつつも、代替となる新しい優れた方法を同時に提供。 ゆくゆくは折りを見て古い設計がフェードアウト→廃止みたいな 感じで綺麗にしてくれないかな。HTMLみたいに。
valarrayは残したままnumericarrayとか新設すればいいだけの話
C++0xの拡張は、auto以外はほぼ下位互換です。 auto以外で私が知ってる下位互換じゃなくなる部分では SFINAEの仕様が明確化されるので今まで曖昧だった部分を使っていたら コンパイルエラーになるかもしれない、というとこです。 それ以外は基本的に"変更"というのはないです。今後もないでしょう。
C#みたいにObsoleteな要素つかったらコンパイラが教えてくれるとうれしい strstreamとか
604 :
デフォルトの名無しさん :2008/08/31(日) 18:57:39
重要なのは604が誰かということだ。
604のリンク先の「〜は僕です」って何なのよ 名乗りたいなら最初からトリップつけときゃいいのに・・・ つかこういうつまらん名乗りごっこがしたいならハテナに引きこもっていてほしい マジウザい
C++0xのまとめ関連でお世話になってます
>>601 auto_ptr非推奨でunique_ptr新設とかまさにそんな感じ。
>>606 その後のコメントで晒されたwって言ってるから、
604は本人じゃなさそう。
なんにせよ自分から名乗っておいて「晒された」はねえよな
名乗ったつってもTwitterだしな。アレもおよそ内輪コミュ系だよ。 貼られて困ること書いたら馬鹿だけど、一応晒されたとは言えると思う。
結果として内輪コミュになってるだけ 晒されて困るならプライベートモードにでもすりゃいいのに
615 :
613 :2008/08/31(日) 22:07:30
誤解を招きそうなんで補足。
>>602 が貼られて困ること書いたって意味では無くて、
誰でも見れる状態の内輪の会話みたいなものって意味ね。
616 :
613 :2008/08/31(日) 22:09:08
遅かったです(^q^)
誰でも見ていいのならどうして2chに晒されたのを大騒ぎするのか 理解に苦しむね
要は、604のリンク先の奴がそういう意識が低かっただけの話 そして、そういう奴がブログ炎上を引き起こす 今回はブログじゃなかったからダメージ少なくてよかったな いい教訓になったじゃん
見たところ痛いこと書いてるわけじゃないようだし ブログ炎上とは違うと思うけどな 批判レスならともかく、ただの粘着がくれば普通は嫌がるだろ
おまえらもっと有益な話をお願いします
スレ違いはそろそろ終わりにと書こうとしたら書かれてたw
>>603 同意。
なんかあったような気がしてググッたけど見つからなかった。
#errorの警告版みたいなの無かったっけ?
>>623 処理系依存じゃね?gccなら何か言ってくれそうだけど
#warning this is warning message. int main (void) { return 0; } GCCならこれでwarningが出る VCなら#pragma message()かね・・・
確かに処理系依存しかなさげ。 VC++なら#pragma messageでコンパイル時にメッセージ出せる。 メッセージなんで警告数は0になるけど。
VCの方も見つけた。 ディレクティブでなく、処理系拡張の修飾だった。 __declspec(deprecated("test")) void f(){} としておいて、これでf()を使うと、 warning C4996: 'f' が古い形式として宣言されました。 'f' の宣言を確認してください。 メッセージ: 'test' って警告が出る。 f()を使わなかったら警告は出ない。
crtdefs.hに #if _MSC_FULL_VER >= 140050320 #define _CRT_DEPRECATE_TEXT(_Text) __declspec(deprecated(_Text)) #else #define _CRT_DEPRECATE_TEXT(_Text) __declspec(deprecated) #endif って書いてあった。 この条件に、_MSC_VERでVC++限定にする#ifも含めて、 別途マクロを定義しておけば良さそう。 直接書いちゃうとVC++でしかコンパイル出来なくなるし。
>>603 というわけで、とりあえずVC++でのObsoluteみたいなもの。
gccの#warningも混ぜられそうだけど今手元にgcc無いので。
#if _MSC_VER >= 1300
#if _MSC_FULL_VER >= 140050320
#define OBSOLUTE(_Text) __declspec(deprecated(_Text))
#else
#define OBSOLUTE(_Text) __declspec(deprecated)
#endif
#else
#define OBSOLUTE(_Text)
#endif
OBSOLUTE("use f2()") void f(){ /*...*/ }
void f3(){
f(); //警告
}
GCCにも__attribute__((deprecated))みたいのがあったと思う 使えるバージョンは知らん
c++でなにか簡単なゲームを作れという課題があるのですが、どうにもネタが生まれません というか、クラスまでしかやっていないので、大したものは作れないのですが。 助けt
乱数あてゲーム! あなたはエスパーか
3並べでも作れよ 初歩的だが考えるルーチンはこれからのためになる
>>630 d
確認してないけど、これで良いかも。
>>629 の2個目の#elseの前に追記で。
#elif (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))
#define OBSOLUTE(_Text) __attribute__((deprecated))
>>633 俺も最初は3並べ作ったなあ。
盤と目をクラスとして設計するのもいい練習になるし。
class A { class B { void F(); }; }; と.hに宣言した場合、 .cppに実装を書く場合、 void A::B::F(){ ... } と書くと、A::Bは宣言されてないと怒られます。なんで? gcc バージョン 4.2.3 使用中。 インナークラスは宣言時に実装も書かないとダメ?
void A::B::F()の宣言が書かれている(ヘッダ)ファイルを void A::B::F()を定義する前にインクルードしていないとか
>>631 ほれ。
クイズゲーム作ってやったぞ
$ cat a.cc
#include <cstdio>
using namespace std;
int main()
{
int hoge;
printf("日本の首都は?");
printf("1.東京 2.京都 3.奈良");
scanf("%d", &hoge);
printf(hoge == 1 ? "正解" : "不正解");
return 0;
}
ああ、相当\nが抜けてたわwww
5点
5点満点だよな
オブジェクト指向で作りなさい
>>640 >#include <cstdio>
>using namespace std;
ワロタ
テンプレートクラスの前方宣言て、 template<class T> class hoge; こんな感じでおk?
そういえば、.hがつくC言語の古いタイプのヘッダと違って、頭にcを 付けて.hを付けない新しいタイプのC言語のヘッダって、std名前空間に C言語のモジュールを入れるためのヘッダじゃなかったっけ? でも実際はstd名前空間に入ってなくて、グローバル名前空間だよねぇ。 なんでだろ。
>>647 それはVC6くらいだ。今時のはちゃんとstd名前空間に入れてある。
が、どいつもこいつも中で<*.h>をインクルードしているので、
グローバル名前空間でも使えてしまうのは相変わらずだが。
じゃあ、std::を付けても付けなくてもC言語のモジュールが使えちゃうわけか。 なんだかなぁ。実装者の都合かな。
手抜き
しかしプログラマーとしてはどうすればいいんだ? std::付けなくてもコールできるけど、移植性を考えたらstdにあるつもりで プログラムしなきゃいけないんだよな。でもそんなことやる奴いるのか?
はあ??
規格書通りにしないと移植性が保証されないだろ
>>653 それはその通りだが真っ当なプログラマなら当然そのように書くだろ。
>>651 で何を言いたいのか分からない。
<cnanntoka>でグローバル空間にstd空間と同じものができるという保証はない。 よってstd名前空間を頭につける、という一択しかない。
そこで恐怖のsize_tとptrdiff_t
>>654 何が真っ当なプログラマだよ規格書も守らずに
もうやだこのスレ。 日本語通じない馬鹿がなんでこんなにいっぱいいるの?
>>658 逆だろ。
日本語が通じない馬鹿ではなくて、正しい日本語で相手に自分の
意志をうまく伝えられない自分の馬鹿さ加減を何とかしろ
まあ流しとけw
>>656 そこで泣く泣く#define SIZE_Tですよ
エスパーでない俺がエスパーしてみるてst
話題提起者(
>>651 =
>>653 =
>>657 )
>>651 「ちゃんとstd空間として扱ってる奴居るの?」
>>652 「std空間として扱うだろ常識的に考えて」
>>653 (652が文意を理解してないと考えて言い換える)
「std空間としてじゃないとまずいんだろ?」
>>654 「当然std空間として扱うだろ常識的に考えて」
>>655 「std空間一択」
>>656 「std::size_tが無い恐怖のEmbedded・・・」
>>657 (654が"だが"という言葉を使ったため、
"そのように"をグローバルの方だと認識)
「グローバルは真っ当じゃないだろ」
>>658 「勘違いしてるオワタ」
※ 結局全員 std空間として扱うのを推奨
エスパーならまかしておけ。
>>651 が言いたいのは、たいていのコンパイラは新しいC言語ヘッダ(c○○)
を使う場合、std::付けなくてもC言語の標準関数がコールできる。
ただし、std::付けないで組まれたプログラムは、律儀にstd::を付けないと
コールできないようにしているコンパイラ環境では、コンパイルできなく
なってしまう。そういう意味で、移植性を考えるなら、std::がいらない
状況でもstd::を付けてプログラミングするべきという話なんだろう。
エスパーじゃないけど俺も664の言うようにしか解釈できなかったよ。
代入演算子関数は非静的クラスメンバじゃなきゃダメよ(13.5.3)って言われてて 代入演算子とは=とか+=とかみたいなの全部(5.17)って書いてるのに VCとGCCの両方ともグローバルなoperator+=()作れちゃうんだけど これってどうなの グローバルな+=とか*=とか作っていーの?
規格の書き方の方が曖昧だったのね じゃ+=系は+や-と同じただの二項演算子として扱っちゃっていいのね ありがとう
教えてください。 C++の入出力処理は、ストリームバッファなるものを介して行われるようですが 出力時のバッファの役割はなんとなくわかるのですが、入力時のバッファの 役割ってどんな感じなのでしょうか。キーボードから入力してもバッファに ため込むだけで、実際にプログラムに入力されないみたいなことがあるのでしょうか? もっといえば、標準入力関数のreadとreadsomeの使い分けがわからないのです。
>>669 read()は実際にストリームバッファに文字が入力されるまで
そこで停止して待つが、readsome()はストリームバッファに文字
があろうとなかろうと読み取ろうとして停止しない。
もちろんどちらもfailbitやeofbitが設定される。
671 :
669 :2008/09/02(火) 07:31:36
>>670 ありがとうございます。
動作の違いは理解できました。
が、readsome()の使いどころって想像つきませんね。
まぁキーボードから入力するなどという単純なプログラム作ってるうちは
無理なんでしょうが。
>>671 readsome()はファイル入出力で生きてくる。
というかstd::cinに対してistream::readsome()が正しく実装されている
処理系は少ないと思う。
ヒント:リダイレクト
メッセージループみたいな働きをさせられるんじゃね?
min, maxがマクロで定義されていた場合, std::min とか std::max とか std::numeric_limits<T>::min() が置換されてしまうので, 呼び出すときに std::min BOOST_PREVENT_MACRO_SUBSTITUTION (x, y) などとしているのですが,長ったらしいので, (std::min)(x, y) と関数を括弧で囲みたいのですが,この書き方は規格的に合法でしょうか? それか他にもっと上手な回避方法はないでしょうか?
#undefでよくないか? あと、もし<windows.h>のだったらNOMINMAXで抑制できる。
679 :
デフォルトの名無しさん :2008/09/02(火) 14:08:22
実装が内部に持つコンテナのイテレータを返すメンバ関数をインタフェースに持ちたい場合, どうすればよいでしょうか? // インタフェース struct Hoge { virtual HogeIterator begin(void); }; // 実装 struct HogeImpl : Hoge { HogeIterator begin(void) { container_.begin(); } vector<int> container_; }; インタフェースで typedef vector<int>::iterator HogeIterator; とすると実装が見えてしまうし, インタフェース側で struct HogeIterator; と宣言だけしておいて実装部分で struct HogeIterator : public vector<int>::iterator { ・・・ }; とするのは大変そうな気がするのですが。
俺は実装が見えても気にしない派
>>679 ややこしい文章だなw
イテレータがテンプレートクラスだった場合、
どう足掻いても仮想化出来ないんだからラップすればいい。
※ コンパイルもしてない
struct VirtualIterator {
typedef VirtualIterator Myt;
virtual ~VirtualIterator(){}
VirtualIterator(const Myt& o){copy_from(o);}
Myt& operator++() {incr(); return (*this);}
virtual void incr() = 0;
virtual void copy_from(const Myt& o) = 0;
};
struct Hoge {
virtual VirtualIterator begin() = 0;
};
-- .cpp -----
struct IterImpl : VirtualIterator {
std::vector<int>::iterator it;
void incr(){ ++it; }
void copy_from(const VirtualIterator& o){
IterImpl* p = &o;
it = p->it;
}
};
682 :
681 :2008/09/02(火) 14:38:20
まあ言っても俺も
>>680 に同意。
virtual自体滅多に使わないし、
pImplなんて余程のこと。
テンプレートクラスでおk。
683 :
681 :2008/09/02(火) 14:41:41
なんか実装隠す話とvirtualが混ざったけどまぁいいか。
特定のクラス→自作クラスのキャストをオーバーロードはやり方が分かるのですが 自作のクラス→特定のクラスのキャストを自作クラス内部に記述するやり方ってないでしょうか? データの配置が同様なのでコピーを作成したくないんです・・・
685 :
679 :2008/09/02(火) 15:49:38
>>681 ややこしい文章だなw
同意。
>>680 >>682 これも実は同意で、これまでそういう実装をしていました。
急に気になり始めてしまって…。(麻疹みたいなものですか)
↓みたいにできればシンプルでハッピーなのですが、現状不可です。
class HogeIterator; // in "Hoge.h"
typedef vector<int>::iterator HogeIterator; // in "Hoge.cpp"
>>684 >コピーを作成したくない
Tokutei* a = new Jisaku(); ってこと?
これなら class Jisaku : public Tokutei{...}
と継承すれば良い。
それとも
Jisaku a;
Tokutei b = a;
ってこと?こっちは当然コピーってことになるけど。
>>685 >急に気になり始めてしまって
そんなふうに考えていた時期が(ry
>現状不可です。
>>681 で書いた通り、直接では仮想化出来ないよ。
原理的に。
>>684 >>686 の言うように継承を使うか、
operator Tokutei &() { return reinterpret_cast<Tokutei &>(*this); }
を実装する。
データの配置が同じと言うからreinterpret_castにしてるが、
本当にメモリレイアウトが同じなのか?
そうだとしても偶然や実装依存ではないのか?
ってことはよく考えるべし。
ファイルって入力用にオープンしたら、ストリームバッファにすべて 取り込まれていると考えていいの?
>>688 そりゃあ必要に応じて取り込むでしょ
すべてではなく
>>688 すべて取り込んでたら、
2GBの動画とかメモリ不足で再生出来なくなるだろ
ということは、どれほどのデータ量を一度にストリームバッファに取り込む かは、実装依存てこと?
そりゃそうでしょ
想像力ゼロの人間が何一つ試さないと、こうなる。
なんでこんなに叩かれるのか分かりませんがとりあえずありがとぐございました
他人を↓ることで相対的に自分を↑ようとする人が多いからね。気にしないこと。
なぜグローバルリンクw
2chは基本的にボケた的を射ていない質問をするとそれだけで 叩かれる傾向があるのさ。 だからちょっと敷居が高く感じるかもね。
初学者の、なんてことない質問にいちいちつっかかる
>>693-694 は
他所のスレで叩かれて八つ当たりしてるか、或いは生理不順なんだろう。
C++の質問ですらないから少なくともスレ違いだなw
ストリームバッファはC++じゃないの?
この疑問の答に必要なのは、PCの基礎知識と、ほんの少しの当たり前の思考だけ。 あるいは、「初学者」には絶対無くてはならない「自分で試す精神」で、ほんの数行のコードを書いて実験するだけ。 つまり、まともなら質問自体が発生しない話。 PCの基礎知識すら無いか、当たり前の思考力すら無いか、初学者に必須の精神すら無いか。 いずれにせよ、「初学者の、なんてことない質問」になっていないから突っ込まれるんだよね。
つまり燃料が欲しいだけだろ
スルーするのが大人の対応 一々突っ込むのは(笑)
ほんとに実装依存なんだろうか >>ストリームバッファ
すいません。初心者です。 ファイルを入力用にオープンしたら、ストリームバッファにすべて取り込まれてるかを 調べる 「ほんの数行のコード」 を教えてください。 streambuf::in_avail() を使えば いいと思い以下のコードを確認しました。 #include <iostream> #include <ostream> #include <fstream> int main() { std::ifstream ifs("tmp.bin"); std::cout << ifs.rdbuf()->in_avail() << std::endl; return 0; } 環境 cygwin + g++(3.4.4) で 100Mbyte のファイルで 確認したら ファイルサイズがそのまま返ってきました。 $ g++ -Wall -O2 -g tmp.cpp $ dd if=/dev/zero of=tmp.bin bs=1M count=100 $ ./a.exe 104857600 $ 200Mbyte のファイルで確認しても同じでした。 よろしくお願いします。
何を教えてほしいのかよく分からん コードは自分で書いてるじゃん
>>707 参考にならんかもしれんけどBCC5.9.3では0を返した
ロシアから輸入したに決まってるだろJK
最近、マトリョーシカの話題をあちこちでみかけるなw
> アメリカのMicrosoftは、Microsoft C/C++を最初に世に送り出したとき、一般の顧客はまともなC++プログラムを書けないことを発見した。
> これではC++コンパイラを売っても儲けにならない。
> Microsoftのプログラマたちはこの問題に立ち向かうべく、20年の歳月と120億ドルの開発費をかけて研究を重ねた。
> その結果ついに、タイプミスをしても関数の名前を忘れても、どんな状況下でも適切な補完候補を提示できるIDEを開発した!!
>
>一方ロシアはマトリョーシカ(
>>523 )を使った。
みたいな?
マトリョーシカってよくプロトコルスタックに例えられるよねって書いて、 逆だと突っ込まれたやつが来ましたよ。
>>712 むしろそこはIDEじゃなくてC#が当てはまる気がする。
でもSunに先を越されちゃいました^^;みたいな?
入出力がらみなんですが、sentryオブジェクトはそのコンストラクタや デストラクタで、ストリームの前処理と後処理を例外安全に行うRAII オブジェクトということのようですが、実際何をやるんでしょうか。 自前で入出力演算子などをオーバーロードするときに、どういう場合に 使えばいいのでしょうか。
>>716 C++標準ライブラリより。
sentryオブジェクトは入出力の途中で例外が生じても確実に
処理を終わらせるために設けられている。
出力演算子にsentryを使うには
std::ostream::sentry se(stream);
if (se) {出力を実行}
入力演算子に使うには
std::istream::sentry se(stream, true);
if (se) {入力を実行}
但し、basic_istreamやbasic_ostreamにsentryを使うと 不必要にコストが高くなるので、basic_streambufを使うべき、 と書かれている。
レスありがとうございます。 どうも、何をやるのかってのは、ブラックボックスなんでしょうかね。
リバースエンジニアリングして解析すれば何とかわかるんじゃね
char_traits<char>::eof()は、その文字型のeofを返しますが、 char_traits<char>::not_eof(c)は何をやる関数なのでしょうか。
>>721 iがEOF以外の値であればiを返す
iがEOFであれば処理系依存であるがEOF以外を返す
つまり絶対にEOFを返さないメンバ関数
コンストラクタのなかで (*this) = rhs; と自分自身のoperator=を呼び出すのは問題ないでしょうか?
問題ないよ。やめたほうがいいけど。
初期化子リスト書くの面倒だからな。やめた方がいいけど
operator=をcopy&swapで実装して、copy constructorは全部書くほうが好きだな。
すいません初心者です。 動的にTCHARの2次元配列を確保したいのですが、下のようなエラーがでます。 error C2440: '=' : 'TCHAR (*)[260]' から 'TCHAR' に変換できません。 こういった場合はどうすれば、いいんでしょうか? メンバーにszParam[_MAX_PATH]を持った構造体を作ったりするんでしょうか? TCHAR g_szParam; void Test(void){ int nCnt = 10; g_szParam = new TCHAR[nCnt][_MAX_PATH] //ここがエラー }
TCHAR (*g_szParam)[nCnt];
あれTCHAR (*g_szParam)[_MAX_PATHt]; だっけ? うろ覚えで答えたりしてすいません
731 :
728 :2008/09/04(木) 16:51:26
>>729 >>730 さん
有難うございました。1時間位悩んでたので助かりました。
TCHAR (*g_szParam)[_MAX_PATH];
void Test(void){
int nCnt = 10;
g_szParam = new TCHAR[nCnt][_MAX_PATH];
}
>>731 このタイプのnewをした場合でも、解放するときってdelete[]でいいんでしたっけ?
delete[][]なんてことはないですよねw
>>732 当たり前だろ。
勉強に3次元配列の確保と解放の仕方を書いてみなさい。
int (*p)[2][3]; p = new int[4][2][3]; delete [] p; こんなんでいいのかな?
,.,.,.,.,.,.,.,.,__ ,,;f::::::::::::::::::::::ヽ i::::::::/'" ̄ ̄ヾi |:::::::| ,,,,,_ ,,,,,,| |r-==( 。);( 。) ( ヽ :::__)..:: } ,____/ヽ ー== ; ほほう それでそれで? r'"ヽ t、 \___ ! / 、、i ヽ__,,/ / ヽノ j , j |ヽ |⌒`'、__ / / /r | {  ̄''ー-、,,_,ヘ^ | ゝ-,,,_____)--、j / \__ / | "'ー‐‐---''
>>735 ':, ', _____,,.. -‐ ''"´ ̄ ̄`"'' ー 、., /
':, ', >' ´ `ヽ. / し バ
':, / ヽ. ,' な カ
':, ,:' / / ,'´ ヽ. ':,/Ti i. い に
. \ ,' / / ,' ! ; ', ヽ__ /::::| | | で
\ / ,' ,'! /! ! ; /! i 「:::|'´::::::::| | .!. く
∠__,! / !メ、」_,,./| /! / ! ハ! |__」<:::::」」 |. れ
`"'' 、..,,_ ! / ,ァ7´, `iヽ| / |ヽ、」ニイ、 | ! |^ヽ、」」 |. る
i,/レイ i┘ i. レ' 'ア´!_」 ハヽ| | | ∠ ! ?
─-- / ! ゝ- ' ! ! ! | | `ヽ.
/ 7/l/l/ 、 `'ー‐ '_ノ! | i | ` ' ー---
,. -──-'、 ,人 `i`ァー-- 、 /l/l/l | !. | |
ヽ.ソ `: 、. レ' ', u ,/| | ! |
そ 知 i /ーナ= 、 '、 ノ ,.イ,カ ! | |
の っ .|ヘ./|/レへ`>-r =ニi´、.,_ | i ハ ! ,'
く て ! _,.イ´ヽ.7 / /:::| /レ' レ'レ'
ら る | /7:::::! ○O'´ /::::::レ'ヽ.
い .わ .| / /:::::::レ'/ムヽ. /::::::::/ ヽ.
! ! よ ! ./ ,':::::::::::!/ ハ:::::`´:::::::::::;' ',
けっきょく多次元配列なんて存在しないという結論でいいのかなw どうやっても1次元。
多次元配列は「〜配列へのポインタ」という形でしか存在しないんだな
typedef int (*PA)[5]; PA *p = new PA[3]; この動的確保をtypedef無しに生で書くと int (**p)[5] = new int (*[3])[5]; になると思ったのだが、コンパイル通らん。 どこが間違ってる?
int (*pp)[5] = new int (*)[3][5];
int (**p)[5] = new (int (*[3])[5]);
>>741 ありがとうございます。
でもこれってどういうことなんですかね。new演算子の優先順位が
問題なんでしょうが、new int (*[3])[5]; だとコンパイラは
どう解釈しにいってるんだろう。
740は間違いな。741で。 どうもカッコがないとうまくパースできないらしい。 この問題は関数ポインタの配列を確保しようとする時にも 同様に発生した。 詳しい方解説ヨロ
new int (*[3])をintのコンストラクタだと思って、 結果のint*に配列添え字演算子[5]を付けてると解釈する でもコンストラクタ引数の*[3]が理解できないからエラー だと思う多分
なるほどそういう事かサンクス どてもこのカッコが異質で慣れないもんだから時々悩んでしまうんだよな
結局typedefすればいいという結論
この場合のtypedefはした方がいいね いらない事で悩んで時間を無駄にするよりまし
この場合、というよりセマンティクスを優先することだな。 ただのバッファで無い限り、1要素に対して、 何か意味のある名前を与えることが出来るはずだ。
>>724 いや、レアケースではあるけど問題あるからw
代入子演算関数が自分自身のクラスの仮想関数を 呼び出している時とか?
あ、ごめん、逆の( operator=() から placement new を利用する )パターンと間違えた。忘れてくれ。
753 :
デフォルトの名無しさん :2008/09/05(金) 22:32:43
> いらない事で悩んで時間を無駄にするよりまし そういうノロマまは開発のテンポについていけないから、窓から飛び降りたほうがいい
std::vectorみたいに ・ランダムアクセス可能 ・コピーすると中身もコピーされる ・個数を記憶している けど、push_backとかで追加することはできないコンテナってある?
>>754 なにかを格納するって意味でのただのコンテナならいっぱいある
stlコンテナのことだったら、サイズ固定な時点で定義を外れるので存在しない
>>755 すまん書き忘れた。
コンパイル時点ではサイズが決まらないんだ。
std::vector<int> v(10);
みたいなかんじで使いたい。
>>756 そうか・・・
自作するしかないかな。
>>757 ならboost::multi_array
>>758 おお!
boost::multi_array<int, 1>ってことか!
ありがと!
VC使ってるならautoexp.datに boost::multi_array<*,1,*>{ children ( #array ( expr: $c.base_[$i], size : $c.allocated_elements_ ) ) preview ( #( "[", $c.extent_list_.elems[0], "](", #array ( expr : $c.base_[$i], size : $c.allocated_elements_ ), ")" ) ) } でも書いておくとデバッグ時に配列みたいに表示してくれる 上のはmulti_array<int, 1>の場合だけだけど
const std::vector<T>だと都合が悪いんだろうな。
>>760 すげぇ。
>>761 std::vectorだとメモリが倍々で確保されることが多いと聞いたので。
>>762 作った時点で大きさ決まってて、その後リサイズしないならメモリの問題はないでしょ。
そもそも倍々には確保されないと思うけどね。
1.5 倍がいいらしいよ。
大概倍々だよ push_backで容量こえたからって、一個増やして再確保とかははまずやらない
少なくとも要素数に比例させて再確保しないと償却定数時間の要件が満たせない。 単純に倍にするのが素直な実装。
VCは1.5倍だm9
どのVCだよ
普通2のn乗サイズじゃね
VC++2005で試してみた void f(){ std::vector<int> s; std::size_t c=0; for(int i=0; i<256; i++){ s.push_back(i); if(c!=s.capacity()){ c = s.capacity(); std::cout << "c=" << c << std::endl; } } } ------------------------- c=1 c=2 c=3 c=4 c=6 c=9 c=13 c=19 c=28 c=42 c=63 c=94 c=141 c=211 c=316
>>770 だから、0から順にpush_back()する場合は2倍にすると申し上げてますでしょう。
最初からサイズを指定していれば、2の冪乗になるとは限りませんってば。
773 :
771 :2008/09/06(土) 20:05:09
gcc3.4.6で試してみた c=1 c=2 c=4 c=8 c=16 c=32 c=64 c=128 c=256
mingw(gcc 4.1.2)の結果を貼ろうと思ったら
>>773 に先を越された
ちなみに同じ結果だったわ
775 :
771 :2008/09/06(土) 20:13:15
C# 2005の場合(System.Collections.Generic.List) c=4 c=8 c=16 c=32 c=64 c=128 c=256 ちなみにjava6(java.util.ArrayList)はVC++2005同様に1.5倍 実装者の好みって感じなんだろうかね
言語が違うとはいえ、 同じMS製のVC++とC#で違うのか・・・。
M$だし…
アンチもここまでくるとただのアホだな
たしかにM$をただ非難するプログラマーは思慮が足りないように思う 経済的な効率を考えるとM$の製品の品質は感慨深いものがある ユーザーとしてもう少し品質を高めて欲しい気もわからんでもないが
struct drawable { virtual void draw()=0; }; class charactor :public drawable { ... }; こういう風に継承することで特定のメンバ関数の実装を強制する小さいクラスって何て呼ぶんだっけ?
仮想クラス
インターフェースクラスとか?
抽象クラス
抽象基底クラス
785 :
780 :2008/09/06(土) 23:15:26
ポリシーみたいな特別な呼び名があったと思ったんだが勘違いだったみたいだな
一言で言うならインターフェイス コンセプトは別物です
C++なら抽象クラスと呼ぶこと多い気がするな 関数は純粋仮想関数 まぁ、Javaだと全てが仮想関数だしな・・・
抽象クラスってのは抽象関数(純粋仮想関数)を持っているクラスのことで、 インターフェイスは抽象クラスのうち全ての関数が抽象関数で実装を持たないクラスのこと、 だと思う。
インターフェースと呼ぶとオーバーヘッドなさそうに聞こえちゃうから C++の場合は純粋抽象クラスとでも呼んだ方がいいと思うけどな
プロトコルって言い方も何かね…
インタフェースってのはライブラリの公開関数やクラスの一群を指す事もあるから 抽象クラスの方が明確かな
792 :
デフォルトの名無しさん :2008/09/07(日) 12:50:12
行列計算に普段はmatlabを使っているのですが、loopが避けられない計算を C++で書き直して計算させようとしてるとこです。 行列が128*128の時はmatlabに比べて30倍ほど速いのですが、実際に扱い たい行列1024*1024の時はmatlabと比べて2倍程度にしか速くなりません。 行列の計算自体はドット積です。 大きな行列でもどうしたら速くできますでしょうか? CPUはインテルのクアドコア3.2GHz、メモリ8G、インテルコンパイラ、OpenMP、行列処理にBlitz++使ってます。
それはもはやC++の範囲を超えるんでねーの。 キャッシュに乗り切らないから遅いとか。
手動で計算すればいいんだよ
795 :
792 :2008/09/07(日) 13:12:51
キャッシュがやっぱり関係してるんですかね。 Blitz++と比べてIntel Math Kernel Library使ったら速くなりますか?
>>792 プロファイルとってみれば?
おそらく、ドット積を普通に計算すると行列全体に満遍なくアクセスするから
メモリキャッシュのヒット率さがってるんじゃないかな。
doubleとfloatならfloatのほうが高速
>>797 ある環境ではそうだったんだろうけど、環境が変われば結果も変わる可能性がある。
結局、速度は実測が基本。
799 :
792 :2008/09/07(日) 14:11:08
>>796 今目の前に居ないので分からないですが、行列のサイズを試しに512*512にしてみたところ一気にパフォーマンスが落ちたので、その通りだと思います。
floatでも試しに計算してみましたが、1024*1024ならdoubleとほとんどか
わり無しでした。
やはり2x6MBのメモリキャッシュがボトルネックみたいです。
大きなサイズの行列でキャッシュを有効に使う方法があれば教えていただける
とありがたいです。
両者の実装に比べキャッシュがふんだんにありFPUの処理にfloatもdoubleも差がなければどちらも同じ。
メモリのアクセス速度と実数演算速度が重要ならIntelのCoreより AthlonX2のようなメモリコントローラを内蔵したCPUでFPUも強い 奴を積んでる物の方が多分速いよ ベンチマークを取ってないからわからんけどクラスタサーバはCoreでは なくて大抵Opteronで組まれてるし 単に値段が安いだけからかもしれんけど
何の参考にもならんな
Core信者乙
ハードウェアの限界や特性はどうやったって越えられんわな
floatで速度が変わらないように見えるのは、恐らくは型変換が入ってdoubleで計算している所為だろう。 例えば、うっかり2で割る積もりでa * b / 2.0なんて書いたらa * bもdoubleで行なわれてしまう。
普通にdoubleの方が速いと思ってた俺
速いかどうかはともかく普通はdouble使っておけばいいぞ。 速度が気になる事態になってから初めてfloatと比べればいい。
floatってintと同じサイズでなんだっけ? double floatはintの倍サイズじゃなくて、floatの倍精度ってことだよな? すごいアホらしい話だが
>>808 1. floatとintの大きさが同じとは限らない。
2. doubleはfloatの倍という意味での命名だが、倍になっていなくても規格に適合する実装は可能。
ただIEEE 754がすっかり定着しているけど。
Blitzってマルチコア対応してくれるんだっけ
規格上はfloatが0〜255の整数しか表せなくても何ら問題ないし doubleがfloatより小さくても全く構わない だから何だという話だが
>>811 double が float より小さいのは明らかに規格違反。 (3.9.1 Fundamental types p8)
float の値の範囲については C の規格の FLT_MAX が 1E+37 以上でなければならないことに
なっていて、 C++ もそれに沿うことになる。
811じゃないが、ちゃんと範囲まで定義されているとは知らなかった。 仮数部に関しては定義はされているの?
>>813 numelic_limits の digits10 (Number of base 10 digits that can be represented without change) に
あたる FLT_DIG が 6 以上、 DBL_DIG が 10 以上じゃないといけないらしい。
http://www.open-std.org/jtc1/sc22/wg14/ "documents" > "Prei Santa Clara 2008 mailing" > "N1336"
5.2.4.2.2 Characteristics of floating types
へー一応決まってるのね char=1バイト以外は何も決まってなくてやりたい放題だと思ってた
INT_MAX >= 32767とか整数型もある程度の縛りはあるよ。
>>814 つーことは、符号もあわせると最低17bit必要ってことか。
普段、float型は使わない主義だから、そこまで考えたことないなー 必須になるのって画像処理とか円周率使うときくらいかな
まあ実際問題FPU使う99.9%の問題はdouble使っとけば問題ない。 よっぽどでかい配列使うとかSIMD視野に入れて最適化が必要な場合以外は。
820 :
デフォルトの名無しさん :2008/09/07(日) 22:24:41
いくら規格規格言っても「違反」な実装を使わないわけにもいかない
>>821 組み込みなんかだと浮動小数点とかいらなかったりしないか?
C言語 フリースタンディング でぐぐれ
>>822 そんなターゲットもあるだろうけど、だから何だというの?
コンパイラメーカーの決めることじゃないだろ。
>>822 コピーするときに浮動小数点レジスタ使うこともある
それはC++ではなく、アセンブラのテクでは?
827 :
デフォルトの名無しさん :2008/09/09(火) 23:03:15
実現したい機能がリフレクションを使わないと書けないかめんどくさい ・Type.getType()相当のプリミティブ ・Invoke()相当のプリミティブ があれば文字列をえっちらおっちらこさえれば.NET Frameworkのコードが呼べるはず。 これならスタック二段増えるだけなので手間じゃないはず。(文字列こさえるのはともかくとしてね……) 大本のプリミティブの下に積んでやれば下位互換性も保たれる。
C/C++はD言語に取って代わられるときがくるのでしょうか
テンプレートの書き方(宣言&実装)の質問です。 今までテンプレートを自分で書いたことがなかったので、試しに今までクラスで書いていた コードに手を加えてテンプレートクラス化してみて気づいたのですが、クラスと違って テンプレートの実装は宣言とは別に書くことってできないみたいですね。 (コンパイル時にテンプレートにはまる型が決まらないといけないのだと理解しました) というわけで宣言と実装をヘッダーでやればいんでしょうけど、そうすると関数の一覧が 見えにくいような気がするんですが.... そんなもんでしょうか? もしかして分けて書く方法もあったりします?
言葉のあやなんだろうけど、定義と宣言を分けること自体はできる 同じファイルでだが ファイルを分けてそれぞれコンパイル、という意味で分けるというのなら確かにできない 理由はあなたが言った通り
あぁ同じファイルってのは正しくないか・・・翻訳単位だっけ・・?
>>830 >言葉のあやなんだろうけど、定義と宣言を分けること自体はできる
あ、もしかして単純に一個のファイルになってたらいいですかね?
一つのファイルの前半が宣言、後半が実装みたいな。
だったらヘッダファイルの後半で #include "hogehoge.cpp"みたいにすればファイル分割
も一応可能、みたいな。
>>832 #includeでの埋め込みはコンパイル前なので確かにできます
でもそもそもクラス宣言があると関数一覧が見えにくいというのがよく解からんが
インラインだったらヘッダーから.inlファイルをインクルードってのはよく見るが テンプレートでも.inlファイルって使うのかな
>>833 >#includeでの埋め込みはコンパイル前なので確かにできます
確かに、試してみたらよさげです。
>でもそもそもクラス宣言があると関数一覧が見えにくいというのがよく解からんが
テンプレートに限らず普通にクラスを定義するとき、
メンバ関数の宣言と実装を一緒に書く方式(ってもしかして意味不明ですか? もっと標準
的な言い方があったら教えてください)で全部書くと、
そのファイルでメンバ関数の一覧だけ参照したいとき、見にくくないですか? という程度の
ことなんですが...
一緒に書くのが見にくいなら、分けて書けばいいだけじゃん ヘッダファイル内で分けて書いていけない理由はない
どっちでもいい。 俺はdoxygen用のコメントでうざくなるから分けて書くが
exportというキーワードで翻訳単位をコントロールできるコンパイラもあるみたいですね。
839 :
デフォルトの名無しさん :2008/09/10(水) 13:47:31
void f(const char* a[]){} に char *arr[30]; を渡すと 引数を 'char *[30]' から 'const char *[]' に変換できません。(新しい機能 ; ヘルプを参照) というエラーが出ます. char *からconst char*なら暗黙に変換してくれると思うんですがなぜでしょうか
840 :
839 :2008/09/10(水) 13:48:27
841 :
デフォルトの名無しさん :2008/09/10(水) 13:53:16
stringを使ってください。無駄な作業が減らせます。
constはどこにかかってると思う?
843 :
デフォルトの名無しさん :2008/09/10(水) 14:01:45
>>841 腑に落ちないもので...すみません
>>842 変更できない文字,へのポインタ,の配列
が仮引数だと思っていますがあっていますか?
説明するのも困難というのは考えものだな、いいかげんこの言語は消滅すればいいと思う void f(const char* a[]){} const char *arr[30]; f(arr); とするか char *arr[30]; void f(char* const a[]){} f(arr); とすると通るんだな、んでどこがconstかというとポインタという事なんだが、一応C++の規則どおりな訳ですが・・・ おれなんかはオーバーロードして void f(const char* a[]){} void f(char* a[]){} reinterpret_cast でやるか template を使ったりと
おっと、どこの const が自動キャストかというとポインタの事 const char は char の const 間違いを指摘したような文書になってしまった
846 :
839 :2008/09/10(水) 14:40:45
どうも混乱しているのですが f()はaを介して値が変更されない事を前提にしているので, 変更することのできるarrを受け取るわけにはいかない,ことは納得しました. スレ汚しすみません
847 :
839 :2008/09/10(水) 14:44:48
>>844 >>845 すれ違いになってしまいました.
なかなか頭に入ってこないのでゆっくり考えてみます.
typedef してみるとわかりやすいかもね typedef const char * cp_char; void f(cp_char a[]) {} cp_char arr[30]; f(arr); const が自動でついたり外れたりするのは、以下のの位置 void f(const cp_char a[]) {} const cp_char arr[30]; f(arr); んで、この const は元々どこだよというと void f(char * const a[]) {} char * const arr[30]; f(arr); 死ねるw
あぁ、そうそう、これも C プロトタイプの分かりにくい点の一つ const char と char const は、同じ型、最初の宣言は互換のためで、これだけ規則が例外だ!! const は左側を修飾するから、 char const * const a[] といった書き方にしたら見通しがいいかも知れない。
850 :
839 :2008/09/10(水) 15:07:55
ftp://sunsite.unc.edu/pub/Linux/devel/lang/c/ からcdeclとか言うプログラムを落として使ってみたところ,
宣言の違いはよく分かりました.
(1) const char *a[];
declare as array of pointer to const char;
(2) char * const a[];
declare as array of const pointer to char;
f()の中で
a[0] = ...;
という処理を行っているので2番目の書き方はできなさそうです.
元々
char arr[30];
const char arr[30];
のどちらでも引数とできる関数を作りたかったのですが,
仮引数は(1)も(2)も駄目で結局
void f(char*a[]){}
とするか
>>844 さんのようにオーバーロードするしかなさそうです.
>>849 さんのものはなじみが薄いのですが
char const * const a[];
declare as array of const pointer to char const;
と言う事なので恒久的に変化しない文字列配列に使用するのでしょうか.
851 :
839 :2008/09/10(水) 15:09:57
>>850 *が抜けていました
char *arr[30];
const char *arr[30];
char const * const p; const char * const p; // アドレスもデータも変更できない。 const char * p; // データは変更できないが、アドレスは変更できる。 char * const p; // アドレスは変更できないが、データは変更できる。 char * p; // アドレスもデータも変更できる。 Effective C++
どっかにcdeclのWindowsでも動く版ないかなぁ
>>828 DがGCを捨てると決意するまでは絶対にない
GCを持つ言語がC/C++に取って代わることは永遠にないよ
用途によって部分的に置き換わることはあっても
doubleの計算結果がNaNかどうかって、どうやって判別すればいいんでしたっけ? 移植性がある答えをおながいします
>>855 どの程度の移植性かが微妙だけど標準に沿えとかいうんじゃむり
ieee754なら直接ビット見れば判定できるよ
>>856 VCであれば_isnanを使えばいいようですが、
インテルコンパイラの場合どうするんでしたっけ。
858 :
デフォルトの名無しさん :2008/09/10(水) 21:41:23
class CHoge{ public: std::string m_str; CHoge(){m_str.empty();} void addText(std::string str){m_str+=str;} void print(){cout << m_str.c_str() << endl;} }; void SetStr(CHoge* hoge){ std::string bar= "ponyo"; hoge->addText(bar); } void main(){ CHoge* hoge = new CHoge; SetStr(hoge); hoge->print(); } これって正しいですか? SetStrの std::string bar = "ponyo"; のSetStrを出た後の生存期間とかで問題は起きませんか? 一応、この単純なプログラムは正常に動作している(ように見える)のですが 別のもっと複雑なアプリで同じような部分で問題がおきていて、 生存範囲の問題なのかなぁとか思って 上記のように単純に切り出して再現してみたところ上手くいってしまいまして・・・ でもたまたま上手くいってるという場合も考えられるので・・・ どうでしょうか。教えて下さい。 環境はVS2005です。
859 :
デフォルトの名無しさん :2008/09/10(水) 21:44:02
とりあえず。。。 CHoge(){m_str.empty();} は CHoge(){m_str.clear();} じゃないの?? emptyは空かどうかを調べるだけのメソッドだし。 正直stringクラスのデフォルトコンストラクタで空文字になるから、 m_str.clear()も入れる必要ないけど。
clearじゃなくてeraseだった
861 :
デフォルトの名無しさん :2008/09/10(水) 22:21:37
>>859-860 すいません、勘違いしておりました。
それで、、、本題の方はどうなんでしょうか?
>>854 でも、C++0xでもGCを実装しやすくするための機構が導入されるんでしょ?
864 :
858 :2008/09/10(水) 22:40:54
問題は全く別な場所でした・・・ すいません。ひとまずそこを直したら上手く動いたようです。
>864 一応補足しておくと addText は値渡し、つまりコピーして引数を渡しているので問題は発生しない。
>>862 DはGCを常に使うことが出来、C++0xはGCを使うことも出来る。
ゆえにDのライブラリは常にGC前提で書くことが出来、
C++のライブラリはGCを前提とすることと汎用性がトレードオフになってしまう。
しかし逆にDはGCのメリットと共にデメリットも常に持つことになり、
C++ではGCのメリットを十分に享受出来ないとしても、
デメリットを排除出来ることを重要視している。
まぁGCもかなり進歩してるし、設計思想の違いってところだろうけどな。
GCだけが理由じゃないだろうけど、その辺のために
Dが使われることが増えてきたとしても置き換わる事は無いだろう。
現実的には無い
NaN判定を(x!=x)で行えるのは実装依存?
extern "C"について質問があります。 リンクエラーを解消するために、 mainが書いてある*cppファイルのヘッダすべてにextern "C"をつけました。 ヘッダには、ほかの*.cファイルの関数の定義が書いてあります。 これでうまく動くとおもったんですが、まだリンクエラーが取れません。 *.libも全部リンクしてあるし、原因がわかりません。 他になにかこのエラーが出る原因ってありますか?
cppに定義がないとか普通のリンクエラーだったらextern "C"とか意味ないと思うが
872 :
デフォルトの名無しさん :2008/09/11(木) 08:59:42
エラー 46 error LNK2019: 未解決の外部シンボル _fatal_error が関数 _import_oxfd_features で参照されました。 imgfeatures.obj エラー 47 error LNK2001: 外部シンボル "_fatal_error" は未解決です。 dspfeat.obj エラー 48 error LNK2001: 外部シンボル "_fatal_error" は未解決です。 sift.obj エラー 49 error LNK2001: 外部シンボル "_fatal_error" は未解決です。 xform.obj エラー 50 error LNK2019: 未解決の外部シンボル _gsl_rng_free が関数 _ransac_xform で参照されました。 xform.obj こんなのがでてます…
リンクするライブラリが足りないんだろ
自分で作った関数がないって言われてるのか? リンクする前の.oをobjdumpしてちゃんとシンボル名が合ってるか確認してみ
ちょっとGSL探してきたが、すくなくともgsl_rng_free はgsl.libに入ってるな。
あと、fatal_errorは自前のものなんだろうけど、cppで定義してるのにextern "C"つけちゃってみつからないんじゃないのか? わけもわからずにやってるんじゃないか。
>875 関数は全部自分でつくったやつです。 mainの入ってるのが*.cppで のこりは全部*.cです。 いろいろと定義してあるヘッダファイルを*.cppの中で extern "C"{ } しています。 >876 objdumpというのは初めてききました。探してみます。 >877 間違ってるかもしれませんが、cppだとふyじこlp@関数名というふうに自動でリネームするので、 そうならないようにextern"C"をつけてcの関数を読み込むんだということを調べました。
>>878 だからよ、_fatal_errorのような、先頭がアンダースコアなのはextern "C"してるってことだが
fatal_errorの実体はextern "C"してないんじゃないかってことだ。
具体的には、fatal_errorというグローバル変数がどこかにあって、
ヘッダファイルで extern "C" 付きで extern宣言してるんじゃないかってこと。
880 :
878 :2008/09/11(木) 15:52:19
みなさん、レス下さってありがとうございます。 解決できました。 VisualStudioの設定でlibを追加したり***.hを*.cに書き込んだりしたら動きました。
最近 typeid なる機能の存在を知ったのですが、あまりこれを使ったソースを 見かけません。何か問題あるんでしょうか? それとも、たまたま私が遭遇してないだけ?
使い道がないだけ
デバッグ用にクラスの名前出力するのに使った事はあるな。
boost::anyあたりで使われてた気がする
そういうことか。ありがとー
メタプログラミングのデバッグにはとても便利だぞ。 ただ、gccのname()で返される文字列が、とてもhuman readableとは思えないが。 MSVCなら分かりやすい。
std::vector<double> valueList; の数値のリストがあって、 ある数 t が与えられたときに t が valueList の中で何番目に小さな数字か ってのを求めたいんだが、 エレガントにやるにはどうしたらいい? って相談されたんだがどうすればいい?
ググレカス
>>887 count_ifでtより小さい要素の数を数えるとか。
>>887 何したいかによるが場合によってはvectorじゃなくてmultisetとか使ったほうがいい気がする
valueListが最初に構築されたあと要素が変化しないなら、ソート済みvectorで二分探索もあるね。 tが何番目に小さいか、何回も求めるならこれが最速じゃないかな。
関数内 static 変数の初期化について struct Foo { Foo() { /* 初期化処理 */ } }; int hoge() { static Foo foo; // do something... return 0; } 関数 hoge() が初めて呼び出された直後に、別のスレッドからも hoge() が呼び出された場合、 クラス Foo のコンストラクタが一回しか実行されないことは保証されるのでしょうか? 初期化の実装が bool foo_is_constructed = false; int hoge() { if (foo_is_constructed == false) { foo_is_constructed = true; // Foo foo; のコンストラクタ呼び出し } return 0; } みたいになってたらまずいと思うのですが。。。 しかもアセンブリ吐かせて眺めた限りではそんな気がします。。。
マルチスレッド/コア絡みの安全性保証は、 コンパイラにオプションがあって、かつ、ユーザがそれを指定しない限り 全くされないと思ったほうがよい スレッド間の同期というのは、システムによっては数千クロック以上の ペナルティがかかることもあるぐらい、かなり重たい処理なのです コアが違うとキャッシュなんかも、からんできますからね だから、勝手にそんなことをされたら、性能が落ちるから、 原則止めましょうというのがC/C++系の思想と思います
Singletonパターンでぐぐるとその手の議論は山ほど出てくるよ
>>895 なるほど。マルチスレッド・マルチコアがらみはユーザ・ライブラリ側で調整するべきと言うことですね。
そもそも C++ にはスレッドという概念がありませんでした。。。
>>896 勉強になります。Java では二重チェックしてもうまく働かなかったりするらしいですね。おそろしや〜
せっかくなのでマクロを考えてみました (C99 と BOOST がごっちゃになってますが)
#define STATIC_VARIABLE(type, name, ...) \
static boost::shared_ptr<type> p_##name;\
if (!p_##name)\
{\
static long l = 0;\
if (BOOST_INTERLOCKED_INCREMENT(&l) == 1) p_##name.reset(new type(__VA_ARGS__));\
}\
type &name = *p_##name
いや、こりゃだめだ
めんどくさいから関数の頭でスピンロックでいいよもう
>>898 つまりこういうことですか
class SpinLock
{
public:
SpinLock() { while (locked || InterlockedExchange(&locked, 1)) { } }
~SpinLock() { InterlockedExchange(&locked, 0); }
private:
static long locked;
};
long SpinLock::locked = 0;
int foo()
{
SpinLock sl;
// do something
return 0;
}
while (...) { } のあたりがスピンです
やればできるじゃないか!
それスピンロックになってねーよ。 lockedのテストとInterlockedの呼び出しの間に別スレッドに簡単に割り込まれるじゃん。 何のためにInterlockedCompareExchangeがあると思ってるんだよ。
K主任ってどのスレだったっけ
スレッド生成する前に、static変数を使用して初期化すればいいんじゃないの
905 :
デフォルトの名無しさん :2008/09/14(日) 13:31:05
a
std::vector<double> data(1000000)というvectorがあったとき、各要素を一つずつ+=しながら 合計を出すのとは別の方法はありますか?オーバーフローは考えなくてかまいません。 ・シンプルなコード ・高速なコード のどちらかを期待しています。両方かなえばうれしいです。
誤差も考えなくて良いの?
std::accumulate
910 :
デフォルトの名無しさん :2008/09/14(日) 17:36:24
スレッドを使う。 もし、2桁増えて800Mぐらいだったら いったんHDDに保存しておいて10Mずつ位読み込んで足す。 HDD(仮想メモリ)に連続アクセスするより確実にメモリに乗っていた方が読み込みが速い
911 :
907 :2008/09/14(日) 18:00:13
>>909 素晴らしい。やはりこのようなものがあったのですね。
>>908 すみません、誤差も考えなくて良いです。
数値解析の元ネタにするもので、有効桁数6桁くらいで大丈夫です。
>>910 なるほど、スレッドですか。ちょっと試してみます。
すばやい回答、ありがとうございました。
メモリアクセスが最大のボトルネックだから、 複スレッド化しても必ずしも速くなるとは限らんよ。 プロセッサの得手不得手が出るところでもあるから、 あるプロセッサで測って最速なのが他でもそうだとも限らない。
913 :
デフォルトの名無しさん :2008/09/14(日) 18:17:59
このケースではstd::accumulateが一番だろうな
914 :
デフォルトの名無しさん :2008/09/14(日) 18:20:31
1ギガ近くの配列ならいちど解放した方が速いと思うよ。 うちのPCはメモリ512Mだから、1ギガ確保するとOSが不安定になって相当掛かる。
double*1000000なら8GBくらいじゃねえの。 そんなもんverctorで持つなよw
いやたかだか1000000個だぞ? doubleがどんだけでかいと思ってんだ?
917 :
907 :2008/09/14(日) 19:15:21
なんだか誤解を与えるような書き方になってしまったようですが、個数は例ではなくて実数でした。 一度に処理するのが100万個なんです。 GBレベルの処理を考えてくださった方は申し訳ありませんでした。
その位だったら迷わずstd::accumulate()一択。
100万個じゃ24bitのHD解像度の画像処理するよりも少ないよな。
誤爆
すみません、C -> Objective-C -> C++と経由して来た者ですが、C++で基底クラス のメンバ関数を参照するときにはどうすべきか悩んでいます。 例えば基底クラスBaseClassにfoo()という関数があったとしてこれを派生クラス DerivedClassのfoo()で拡張するとき、 DerivedClass::foo() { // まず基底クラスのfoo()を実行 --- (1) // 次に独自の処理を実行 -- (2) } としたいのですが(1)はどう呼ぶべきでしょうか。Objective-Cだとsuperという予約語で 基底クラスを参照できたのですが。C++でそれに該当するものはないようですね。 とりあえずBaseClass::foo()と、スコープ解決演算子(ですよね?)を書けばよさげなんで すが、ちょっと柔軟性に欠けるような気がしました(例えば基底クラスが変わったときとか、 クラスが何回層かになっている時とか)。
柔軟性の問題ならtypedefで解決かなあ そもそも関数名を同じにしなければ解決するんじゃない? class super { virtual void foo(){ bar(); } void bar(){ /* ... */ } }; class sub : super { void foo(){ bar(); /* ... */ } }; とか。 C++で基底クラスを示す方法がないのは、多重継承を認めてるから
あ、bar()のアクセス指定はもちろんprotectedかpublicね
多重継承の時にエラーにすればいいだけだと思うけど、なんで標準にないんだろうね。
cを hoge.so にしてpythonから呼んでるのですがsoをgdbでデバックするにはどうすればいいのでしょうか?
>>925 D&Eの13.6 にこの機能が標準化委員会に提案され、却下された経緯が書いてある。
特定のデータ型に対してテンプレート関数の挙動を変えたいとき、オーバーロードと特殊化のどちらを使うのが よいのでしょうか? // オーバーロード template <class T> void foo(const T &) { } void foo(const std::string &) { } // 特殊化 template <class T> void foo(const T &) { } template <> void foo<std::string>(const std::string &) { }
普通は特殊化な気がするが って言うかテンプレートのオーバーロードなんて考えたことなかったな
確かに特殊化が普通の気はするのですが、オーバーロードを使えば temlate <class T> void foo(const T &) { } void foo (int) { } // int では値で受け取る のような事ができるので、こちらも捨てがたいのです。 オーバーロードが一般的でないとすれば、何か理由があるのでしょうか?(部分特殊化の可否?)
オーバーロードだと、オーバーロードされるテンプレートの存在を見落としてしまう可能性があるね。 特殊化だと、汎用テンプレートがあるよっ!って教えてくれるから読みやすいよな。
>>931 確かに可読性という意味では、特殊化に分がありますね。
しかし
class Hoge { };
template <class T> void foo(const Hoge &, const T &) { }
template <class T> void foo(const T &, const Hoge &) { }
void bar() { foo(Hoge(), Hoge()); } // エラー! テンプレートの解決が曖昧
のような状況を考えれば(二項演算子をテンプレートにする場合など)、
オーバーロードも捨てられない気がします。
templateクラスの中でテンプレートパラメータが決定してから判明する定数をマクロで使うことってできないですか template<typename T> class Hoge{ #if sizeof(T)==1 char piyo(){ return (char)T; } #endif }; みたいな?
>>933 プリプロセスはテンプレートの実体化より前に行われるからできないでしょ。
ていうかマクロ使ってないし。
どうしてもやりたければ
#include <boost/static_assert.hpp>
template <typename T>
class Hoge
{
public:
char piyo()
{
BOOST_STATIC_ASSERT(sizeof(T) == 1);
return reinterpret_cast<char>(*this);
}
};
みたいなことをすればいい。
でももっといいやり方があると思うよ。
部分特殊化でいいんじゃないの? template<typename T, std::size_t Size = sizeof(T)> class Hoge { }; template<typename T> class Hoge<T, 1> { char piyo() { return xxx; } };
「 int 型のイテレート可能な型を引数に取る関数」って定義できる? 多重定義したいので、型を丸々 template で受け取るってのは無しで。
意味が分からん。
>>936 void hoge(int *first, int *last);
void hoge(std::vector<int>::iterator first, std::vector<int>::iterator last);
void hoge(std::list<int>::iterator first, std::list<int>::iterator last);
...これをネタにもう少し詳しく。意味が分からん。
言葉足らず過ぎでした。ごめんなさい。 void print( int i ) { cout << i; } template<class T> void print( const iterable<T>& xs ) { for( const T& x : xs ) { print( x ); } } この iterable のところを、 std::list なんかの具体的な方を書かずに実装できるのかな、という質問です。
template<template<class> class A, class B> void f(A<B> x); template<class T> class C {}; void g() { C<int> c; f(c); }
duck-typingでおk
>>928-932 いや、オーバーロードの方が一般的でしょう。
C++ Coding Standards 66項でも、
関数テンプレートの特殊化ではなく、
オーバーロードで解決する方が望ましいとしてる。
きっとこういうことだと予想。無駄にTR1使ってみた。あと、おそらくremove_cvも使ったほうがよい。 #include <iostream> #include <iterator> #include <type_traits> #include <array> #include <boost/utility/enable_if.hpp> template<typename Iter> struct is_int_iterator : std::tr1::is_same<typename std::iterator_traits<Iter>::value_type, int> {}; template<typename Iter> void f(Iter first, Iter last, typename boost::enable_if<typename is_int_iterator<Iter> >::type* = 0) { std::cout << "int" << std::endl; } template<typename Iter> void f(Iter first, Iter last, typename boost::disable_if<typename is_int_iterator<Iter> >::type* = 0) { std::cout << "not int" << std::endl; } int main() { int i[5]; std::tr1::array<long, 3> l; f(&i[0], &i[5]); f(l.begin(), l.end()); }
>>940 > template<template<class> class A, class B> void f(A<B> x);
の"template<class> class A"という書き方初めて見たけど、なんていうの?
>>939 ずばりそんな書き方でできると思うんだがなにか問題があったのか?
>>944 Template Template Parameter
まず使うことはないな。
これコンパイル通らないんですけどどうしてですか? operator<<が見つからないというエラーが出ます #include <iostream> template <template <class> class A, class B> void f(A<B> x) { std::cout << x << std::endl; } template <class T> class C { T i; public: C(T c = 123) : i(c) {} friend std::ostream& operator<<<T>(std::ostream& os, const C<T>& c); }; template <class T> std::ostream& operator<<<T>(std::ostream& os, const C<T>& c) { os << c.i; return os; } void g() { C<int> c; f(c); } int main() { g(); }
俺特製コンパイラなら通るけど?
済みませんいい忘れました。 コンパイラはMinGW (gcc 3.4.5) を使っています。
>>940 こんな構文があるんですね。知らなかった。でも一引数のテンプレートクラス = コンテナとするにはちょっと乱暴かな…。
>>943 boost::mpl とか、つい避けてきたんですが、便利ですね。
( type* = 0 というテクニックすら初めて知りました…)
コンテナを受け取る関数は
template<class T> void f( const T& xs, T::const_iterator* = 0 );
とりあえずはこのくらいでも十分かな。
>>945 えっと、具体的にはどう書けばいいんでしょうか。
>>950 おっしゃる意味がわかりません。
全角文字など使っていません。
>>952 投稿した奴には空白混ざってるよ
まぁ除いてもコンパイルは通らないけど
template <class T> class C { ... template<class U> friend std::ostream& operator<<(std::ostream&, const C<U>&); }; template <class T> std::ostream& operator<<(std::ostream& os, const C<T>& c) { ... } もしくは template<class T> class C { ... friend std::ostream& operator<<(std::ostream&, const C<T>&) { ... } }; 若干意味が違うけど。
>>953 そうですそのコンパイルが通らない理由を知りたいのです。
全角文字は投稿の際にもしかして混ざってしまったのかもしれませんが
ソースには入っておりません
>>954 ありがとうございます。無事コンパイルが通りました。
全角空白が元から入っていたのか、投稿時に紛れ込んだのかは 他の人には分からないよね。 そして、全角空白によってもコンパイルが通らないわけで。 だから、それに気が付いたすごく親切な人が親切に教えてくれたわけで。 一応、俺だったら礼はするな。
はいはい、お前さんは礼儀正しいですね
>>957 いちゃもん付けるな
それ位誰だってわかってるさ
エディタに全角空白は□が表示されるし
しかも質問者は<<が見つからないというエラーが
出ると言っているわけで、全角空白のエラーが
出ると言っているわけではないし
うるせーよ
頭悪そうな奴が一、二名いるな
>>954 BCC6.1.0ではコンパイラエラーになるな
これはBCCのバグだろう
template クラスの前方宣言はどのように記述すればいいのでしょう? たとえば、 template< class T > hoge{ }; を前方宣言する場合です。
template< class T > hoge;
両方 hoge の前の class を忘れてるけどね
できますた! どもです。
templare で値を指定出来る? 例えば、こんな感じ。 template<class TValue> class CHoge { int m_value; public: CHoge() : m_value(TValue) {} };
template<int TValue>
classってのは、そういう意味だったのね。ありがとう。
classよりもtypenameの方が意味がはっきりする でもclassの方がタイプ量が少ないせいか皆こちらを使うね
つかtypenameの導入の方が後だからじゃね
typenameは存在自体が恥ずかしい予約語だから必要ないときはあんまり使いたくない
どう恥ずかしいんだ?
975 :
デフォルトの名無しさん :2008/09/23(火) 18:02:03
BYTEからcharへ変換する方法ってどうやるんでしょうか? BYTE *dst; ConvertINetString( &mode, 51932, 932, buf1, &srcLen, dst, &dstLen); 上のdstをchar型に変換したいと思っています。
char *converted = reinterpret_cast<char*>(dst);
>>975 BYTE の(意味的な)定義がわからないと、なんとも。
978 :
デフォルトの名無しさん :2008/09/23(火) 19:09:04
>>974 C++は自力で型名を型名と判別できない言語だから必要な予約語であって
一人でパースすらできない欠陥言語であることの証明だから
そんな理由でなんでclassならいいんだよw
typename は解析を簡単にするために必要なんじゃないの?
typenameの読み方(訓読み)が恥ずかしいんじゃなかろうか
読み方って、ちぺなめ以外に何かあるのか?
なんてことをいうんだ 今後typenameを見るたびに恥ずかしい読み方を思い出すようになってしまったらどうしてくれるw
何処への誤爆かさっさと自白するなら、処遇の善処を考えないでもないぞ?
普通に浦島レスに見える
な、(ry
CloseHandleでエラーが出たらどうしてる? ログに残すくらいしか対策ないよな。
例外投げるとか どっちにしろ対処方はないんじゃね?
精々OutputDebugStringする程度か、無視だな。
enum{ ONE=1, TWO=2, THREE=4, FOUR=8 }; ってフラグ定数を宣言したい時いちいち=で設定しないでもenumと同じ使い心地の定数の宣言できないだろうか 勝手に2倍2倍にしてくれるenumみたいな
enum{ dumm0, ONE, TWO, dumm11, THREE, dumm101, dumm110, dumm111, FOUR };
プリプロセッサメタプログラミングが必要だぜ。
むしろ参照するときにマクロなり何なりで 1 << n する。
>>995 お前の発想にはいつも勃起させられているよ。まぁ、こっちこいよ。
999 :
デフォルトの名無しさん :2008/09/24(水) 19:13:16
1000 :
デフォルトの名無しさん :2008/09/24(水) 19:14:05
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。