【初心者歓迎】C/C++室 Ver.69【環境依存OK】
3 :
前スレ964 :2009/10/20(火) 16:45:59
> exit関数をつかったらデストラクタを呼び出せずにプログラムが終了してしまうので exit関数を使わなければよいことは分かってるんでしょう。 その上で、どうしてもexit関数を使いたいってことだろうから 余程の事情があるんだと思うよ。 好奇心からという可能性も。
>>3 exitを使わない方法を検討した方がいいよ
7 :
前スレ964 :2009/10/20(火) 18:18:10
>>3 exitすれば自動変数のデストラクタが呼ばれないから無理です。
だがちょっと待ってほしい。atexitで自動変数のクラスオブジェクトのデストラクタを呼ぶ というのはどうか。 hoge.~hoge();
>>9 スタックが全部破棄された後なんだからダメだろうよ。
ウィンドウズモバイルとか携帯用OSでC/C++ってできるの?
できるよ。
まじポン?
「できる」の意味がわからんが、使えないわけがないだろう。
visual c++とかも使えるのか
eMbedded Visual C++ 4.0
BREWとかもC++環境は一応あるな 制約が相当ひどいけど、少しずつマシにはなっている模様(例外が使えなかったのが 使えるようになったり)
どうすればいいんでしょうか?
何をどうしたいんでしょうか?
GetWindowRectがうまくつかえません、教えてください 左上100,100の座標にあるウインドウのサイズを取得したいのですが GetWindowRect関数でエラーが出てしまいます #include <iostream> #include <string> #include <windows.h> #include <WCHAR.H> using namespace std; int main(){ HWND bbb ; POINT aaa = {100,100}; bbb = WindowFromPoint(aaa);//左上のウィンドウを取得 LPRECT x ; //ウィンドウの座標値用変数 GetWindowRect( bbb, // ウィンドウのハンドル x // ウィンドウの座標値 ); cout<<x->top<<"\n"<<x->bottom<<"\n"<<x->left<<"\n"<<x->right<<"\n"; }
#include <iostream> #include <string> #include <windows.h> #include <WCHAR.H> using namespace std; int main(){ HDC hdc=NULL; HWND bbb=NULL ; POINT aaa = {100,100}; bbb = WindowFromPoint(aaa);//左上のウィンドウを取得 RECT x ; //ウィンドウの座標値用変数 GetWindowRect( bbb, // ウィンドウのハンドル &x // ウィンドウの座標値 ); /*omake*/ hdc = GetDC(NULL); MoveToEx(hdc,x.left,x.top,NULL); LineTo(hdc,x.left,x.bottom); LineTo(hdc,x.right,x.bottom); LineTo(hdc,x.right,x.top); LineTo(hdc,x.left,x.top); ReleaseDC(NULL,hdc); /**/ cout<<x.top<<"\n"<<x.bottom<<"\n"<<x.left<<"\n"<<x.right<<"\n"; return 0; }
C言語始めたばかりのものです。 ファイルを開いて、1レコードづつ読みこんでから各項目ごとに決められた バイト数で分けるのって、どうゆう関数を使えばいいんでしょうか
fopen(), fclose() fgets() sprintf()
ほかのプログラムの出力をメモリに読み込むにはどうすればいいの? たとえば適当な数列を並べて出力するプログラムがあったとして それを文字列としてstringに入れるといった感じで
>>26 大抵の環境なら、リダイレクトを使えばいい。
例えばWindowsなら
some.exe | other.exe
unix系なら
some | other
といった要領。
これなら前者は標準出力でいいし、後者は標準入力でいい。
必要なら、片方がもう片方をpopen()で起動してもいい。
双方向であったりパフォーマンスが要求されるなら事が足りないが、
先ずはこの辺りから始めては如何か。
28 :
デフォルトの名無しさん :2009/10/21(水) 15:08:32
ポップアップメニューを表示させたくて、下のコードを書いたんですが、セパレータが一つあるだけのポップアップメニューが表示されてしまいます。 本当は「v メニュー」というのが表示されて欲しいのですが。どこを直せばいいでしょう。 環境はVC++2008EEです。 HMENU menu = CreatePopupMenu(); MENUITEMINFO mii; memset(&mii, 0, sizeof(MENUITEMINFO)); mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA; mii.fType = MFT_STRING; mii.wID = 1; mii.fState = MFS_CHECKED; mii.dwItemData = (DWORD)"メニュー"; InsertMenuItem(menu, 0, true, &mii); POINT pt; GetCursorPos(&pt); TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, hwndView, NULL); DestroyMenu(menu);
メソッドの返り値を.演算子呼び出しのときと->演算子呼び出しのときで分岐することはできますか? struct widget {     xxx method(); }; widget w, *p = new widget; w.method(); // 参照を返したい p->method(); // ポインタを返したい // ↓のように使いたい w.method().method().method(); p->method()->method()->method(); // ↓のような形は統一感がないから避けたい p->method().method().method();
>>10 実験してみたら、スタックが全部破棄される前にatexitで登録した関数で
デストラクタを走らせることができたよ。
>>30 > w.method().method().method();
> p->method()->method()->method();
こっちのほうがよっぽど統一感がない。
そもそも.演算子はオーバーロードできない。
33 :
29 :2009/10/21(水) 16:15:48
mii.dwItemData = (DWORD)"メニュー"; のところを mii.dwTypeData = _T("メニュー"); mii.cch = wcslen(mii.dwTypeData); にしたら一応出るようになりました。失礼しました〜。
最近気がついたんだけど、メンバ変数を下のほうに書くスタイルだとclassよりstructのほうが楽だね
デフォルトプロテクションじゃね? しらんけど
総和を求めるプログラムです、いつも思うのですが、この template <typename T, class Iterator> という引数を template <class Iterator> Iterator だけにして、Iterator からT 型を推論できないでしょうか? 具体的に説明しますと std::vector<int> vec; std::vector<int>::iterator = vec.begin(); このvec.begin() からint 型を推論できないでしょうか? template <typename T, class Iterator> T Sum(Iterator& first, Iterator& last) { T sum = 0; while ( first != last ) { sum+=*first; ++first; } return sum; }
>>37 std::accumulateに何の不満があるのか
>>37 std::iterator_traits<Iterator>::value_type
>>38 ありがとうございます。
たしかに、acumulate で総和は求まるのですが、総和を求めるということは
今回、例えであって、疑問の本質はIterator からT 型が推論できるテクニックが知りたいのです、
言葉足らずですみません。
>>39 ありがとうございます
やっと、std::iterator_traits の意味が理解できました。
C++0xならもっと気楽になるね
質問の本質をちゃんと読めないコミュ力不足の回答者って困るよね 〜はどう実装してるの? つミboost::hogehoge ←こいつマジアホ
この質問内容だとaccumulateを提示されるのは当然じゃね
言葉足らずというか余計なこと言うからじゃね?
Boostならともかく標準だしなぁ
template <typename T, class Iterator> という引数を template <class Iterator> Iterator だけにして、Iterator からT 型を推論できないでしょうか? 総和を求めるプログラムを例として説明しますと という書き始めであればよかったと
>>47 これがベストかな。一応質問では推論できないか?というところが疑問文だから、
それに答えればいいのだろうけど。まあ、でも、誤解はしなかった。
>>31 スタックが破棄される前なのか後なのか、どうやって確認したんだ?
>>30 (*p).method().method().method() ですべて解決だ。
>>41 です。おかげさまで、
template <typename T, class Iterator>
という引数を
template <class Iterator>
Iterator だけにして、Iterator からT 型を推論できるようになりました。ありがとうございました。
さて、教えて頂いた知識をベースに標準偏差を求めるプログラムを作り、コードをここに貼りました
http://codepad.org/H2ZC4RSO (掲示しているcodepad のコンパイラではエラーが出ていますが、VS2005 ではコンパイル、実行できます)
StandardDeviation クラスに、下記の関数を組み入れたいのですが、上手くいきません、方法を教えて頂けないでしょうか。
/**
* @brief 平均値
* @param[in] Iterator first 配列の先頭
* @param[in] Iterator last 配列の末尾
* @return sum / cou 平均値
*/
template<class ResultType>
typename std::iterator_traits<ResultType>::value_type average(ResultType first, ResultType last)
{
typedef std::iterator_traits<ResultType>::value_type value_type;
value_type cou = last - first;
value_type sum = std::accumulate(first, last, value_type(0.0));
return sum / cou;
}
template<class ResultType> typename std::iterator_traits<ForwardIter>::value_type average(ForwardIter first, ForwardIter last) { typedef std::iterator_traits<ForwardIter>::value_type value_type; value_type cou = *last - *first; value_type sum = std::accumulate(first, last, value_type(0.0)); return sum / cou; }
>>52 std::iterator_traits<ResultType>::difference_type
あ、1行目もForwardIterね
>>52 イテレータの距離を求めるにはstd::distanceを使う。
57 :
53 :2009/10/21(水) 23:24:39
なんか俺意味わからないことやってるね。死のう
>>41 です
皆さんありがとうございます。これでいいのかな?そして、この平均値を求める関数を、クラスに組み入れるにはどうしたらいいのでしょうか?
わざわざ、クラスに組み入れなくてもいいじゃんという、意見も聞こえてきそうなのですが、教えて頂けないでしょうか。
template<class ForwardIter>
typename std::iterator_traits<ForwardIter>::value_type average(ForwardIter first, ForwardIter last)
{
typedef std::iterator_traits<ForwardIter>::value_type value_type;
value_type cou = std::distance(first, last);
value_type sum = std::accumulate(first, last, value_type(0.0));
return sum / cou;
}
class Hoge { template <・・・> ave(I f, I l) {・・・ } }; Hoge h; res = h.ave(f, l);
>>58 couの型はvalue_typeじゃないだろ。
>>58 です、下記の通りにしますと、こうなってしまうのですが?
error C2955: 'StandardDeviation' : クラス テンプレート を使用するには テンプレート 引数リストが必要です
error C2133: 'sd' : サイズが不明です。
error C2512: 'StandardDeviation' : クラス、構造体、共用体に既定のコンストラクタがありません。
error C2662: 'double StandardDeviation<ForwardIter>::average<std::_Vector_iterator<_Ty,_Alloc>>(ForwardIter,ForwardIter)' : 'StandardDeviation' から 'StandardDeviation<ForwardIter> &' へ 'this' ポインタを変換できません。
template <typename ForwardIter>
class StandardDeviation
{
ForwardIter val_;
public:
template<class ForwardIter>
typename std::iterator_traits<ForwardIter>::value_type average(ForwardIter first, ForwardIter last)
{
typedef std::iterator_traits<ForwardIter>::value_type value_type;
int cou = std::distance(first, last);
value_type sum = std::accumulate(first, last, value_type(0.0));
return sum / cou;
}
StandardDeviation( const ForwardIter& val ) : val_( val ){}
void operator()( ForwardIter& elem ) const
{
elem -= val_;
elem *= elem;
}
};
StandardDeviation sd;
AVE = sd.average(vec.begin(), vec.end());
なんでそこに入れるんだよ。アホか
あ、関係ないけど、
>>63 のfor_eachは移植性ないよ。
65 :
41 :2009/10/22(木) 01:48:56
size_t cou = abs( distance( first, last ) ); こう修正しないとだめだな。
>>66 std::accumulate使ってるんだからfirst<lastを仮定していいだろ
ふむ。確かに。では単純に size_t cou = distance( first, last ); // first と last の順番が逆 と修正。
>>50 別のクラスオブジェクトをmainの自動変数で作って、exit呼び出し時にデストラクタが走ってない
ことを確認した。
>>70 だからatexit()で走らせたんだろ。
このStandardDeviationって名前は気持ち悪いなぁ。 operator()()が返すのは単に(内部で持っている)平均値との差の平方じゃないか。 どうせなら、StandarDeviation(vec.begin(), vec.end())って関数にしてくれ(ぉぃ # まぁ、既に手元には平均やら標準偏差やらを返すメンバ関数を持つ、クラスがあるから要らないけど。
>>69 それがスタック破棄の前後と関係すると思ってるのなら勘違い。
>>73 なぜ? スタックの破棄はオブジェクトの破棄を終えてから行うのでは?
>>74 通常の関数脱出時の動作ではそうだけど、 exit() したときにはそもそも関数脱出の
動作は行われないのだから、関係ないでしょ。
規格を確認すると 3.6.1 p4 に exit() 呼び出し時の動作が書いてあった。
> Calling the function
> void exit(int);
> declared in <cstdlib> terminates the program without leaving the current block and hence without
> destroying any objects with automatic storage duration.
これに加えて 3.7.2 Automatic storage duration p1 から
> The storage for these objects lasts until the block in which they are created
> exits.
ということで、スタックは保持されたままなので atexit() で自動変数のデストラクタを
呼びだしても問題ないみたい。
ただし、 atexit() にその処理を正しく登録することがほとんど不可能なんじゃないかと思う。
>>75 なるほど。exit呼び出し時にはオブジェクトの破棄を行わないのだから、
>>69 では
確認になってないということね。だが、それでは、
>>10 の突っ込みがよく分からないが。
(
>>75 =
>>10 という意味ではない)
ただ、実験したのは
>>9 なので、君の言うとおり結局は問題ないでしょ。atexitに登録した
関数ではグローバル変数のポインタにmainでの自動変数のアドレスを代入して行った。
ほぼ無意味で、実用性のない手法だが、可能は可能ということで。
と言うか、スタック上のオブジェクトが破棄されないのであれば、
>>73 の指摘の
意味がよく分からない。スタック上のオブジェクトが破棄されないのだから、
mainでの自動変数のデストラクタより、atexitに登録した関数でmainでの自動変数の
デストラクタのほうが先に走るのは当たり前だから。
「よく分からない」
の使い方が変じゃないか?
>>10 はそれを勘違いしてたのだろうか
>>73 はスタックが保持されることを知らなかったのだろうか
とかでよくね
×
>>73 の指摘の意味がよく分からない
○
>>73 は俺と同じく、スタックが保持されることが確実であることを知らない人だったのかな
exitを呼び出した時点で自動変数のデストラクタを呼び出さないまま、その記憶域だけが 解放されてしまう可能性があると考えていたんだろう。で、実はその心配はないという話。
つーかそんな怪しいことするくらいなら例外投げればいいのに
>>82 だから、間違いなくatexit()で呼び出されるように登録することは難しいといいたいのだろ。
少なくとも、exit()を使わないと言う同程度で済むもっとスマートな方法があるのだから。
>>85 >>76 > atexitに登録した関数ではグローバル変数のポインタにmainでの自動変数のアドレスを代入して行った。
これでは駄目か?
> 少なくとも、exit()を使わないと言う同程度で済むもっとスマートな方法があるのだから。
例えば? 例外は話題にあったけど、それはパフォーマンスコストが高くなる可能性があると
いう意見があった。だが、例外でってこと?
分かりづらいかな。 つまり、main内で自動変数のオブジェクトのアドレスをグローバル変数のポインタに 代入し、atexitに登録した関数内でそのグローバル変数のポインタから逆参照して デストラクタを実行する処理を書いたということ。
ぶっちゃけatexitでどうにかしようとする方が遙かにコストは高いだろ つーか例外コストを異常に高く考えすぎ
>>86 正常系なら main まで return してくるのが望ましい。
異常系なら例外でおk。
>>87 そんな方法、ふつうにいくつか関数呼び出してそれぞれに自動変数があるってだけで破綻するだろ。
>>88 >>90 atexitで何とかするってのは元々ネタで、それが駄目とか言われたからやってみたって
流れなんじゃないの。
>>89 mainまでreturnしてくるってのは正しい手法ではあるが、普通であって、スマートではないな。
実際面倒だし。
cデータを1件ずつ読んで、商品番号をキーに金額を集計し商品番号が変わったらブレイクして 集計した金額を出力させたいのですがif文での作り方がわかりません。 誰か教えてください。
メインスレッドをサブスレッドから一時休止するためにHANDLEがほしいのですが、 メインスレッドのハンドルを取得する関数ってありますか?
>>94 環境依存。まぁ、サブスレッド起動時に渡しておけば?
>>91 > それが駄目とか言われたからやってみた
そんで、ほんとに出来たのかなあと思って突っ込んだらだんまりになっちゃったという流れ
できるかできないか以前の問題だと思うがな やれたところで糞設計すぎて全く話にならないのは確定なんだし
struct iface { virtual void method() = 0; }; class widget : public iface { virtual void method() { ・・・ } }; int main(void) { iface *p = new widget; p->method(); return 0; } こういう風に継承の過程で可視性を変えるのはありなんでしょうか?
>>96 できたのは事実だし、だんまりでもない。スレを読み返せ。
>>97 やりもしないでやった気でいるよりもましだと思うぜ。
環境依存のことを実験しても意味ないだろ
>>100 がどこらへんが環境依存なのか説明してくれるらしい。
>>101 実用的でないことは重々承知してやってるんだろ。何を勘違いしてんだ。
>>99 > やりもしないでやった気でいるよりもましだと思うぜ。
こんなのは、やらない方がマシの部類。
いい加減鬱陶しいのでチラシの裏にでも書いといてくれ
そんなバカコードは試す価値そのものが無いことにとっとと気付いて欲しい
>>103 それぐらいしか言えないか……。まあ、仕方ないよね。
>>105 突っ込んでる側でも勘違いしてるのがいたんだから、それなりに役に立ってるとは思う。
明らかに絶対やるべきじゃないに限りなく近いやり方を無駄に実験して 「やらない奴よりまし」は無い。やる奴がおかしいだけ。悪い意味で。
>>107 別に勘違いしたままでもいいんじゃね、真人間は一生こんなクソコード書かないだろうし
>>108 突っこみが間違ってると思ったからやったんじゃないか。実際間違っていたし。
スレをよく読めよ。思いこみだけで書かないでさ。
>>109 exit呼び出し後にスタックが破棄されると勘違いしてた奴にとっては別だろうな。
>>111 スタックは破棄されるだろ、デストラクタは走らないが
>>112 >>75 を読めよ。
> これに加えて 3.7.2 Automatic storage duration p1 から
> > The storage for these objects lasts until the block in which they are created
> > exits.
> ということで、スタックは保持されたままなので atexit() で自動変数のデストラクタを
> 呼びだしても問題ないみたい。
__cxa_atexit
全く役に立たない話をいつまで続けるの?
>>114 プログラム終了時にスタックが破棄されるのは当然だろ。atexitで登録した関数が
呼び出される前にスタックが破棄されるわけではないってことだろ。認識大丈夫?
つーか話の流れ的に、atexitでどうにかしようとするのはアホだろ、って話に対して
>>86 みたいなアホが粘るから、いい加減にしろ使い物にならねぇから、って話だろ
>>102 話が逸れてるな。
実用的じゃないことぐらいみんな理解してる。
出来た出来たと言っているが、関数内からのexit時についても出来たのか、それとも出来なかったのか。
>>118 何かずれてるぞ。
>>86 はatexitを使用するのは無意味だと認識してるだろ。
>>117 認識大丈夫?の前に日本語大丈夫?と問いたい。
話の流れで、
> exit呼び出し後にスタックが破棄されると勘違いしてた奴にとっては別だろうな。
exit呼び出し後にはもちろんスタックが破棄されるよ。
>atexitのタイミングでは、必ずしもスタックが保持されないと勘違いしてた奴にとっては別だろうな。
めんどくさい人だな全く。
>>75 を読んでも、exitしてからatexitに入るまでの間にスタックも静的記憶も
ヒープも決して破壊されない、という保証には見えない上に、そんな細かい
実用的にどうでもいい仕様は、仮に規格で規定されていたとしても処理系が
正しく準拠してくれることはほとんど期待できない。
あくまで仕様のテストとして(程度の低い曲芸だが)割り切るならまだしも、
実用にならないんだろうか、というような話を続けている奴が
>>86 のように
実際にいるから、いいかげんにしてくれ、って話になる。
>>119 できたから書いてるんだろう。そう読めるが。
今自分でもやったらできたよ。
・できても無意味だからやるな ・やるべきじゃないからもう実験も要らない
>>122 少なくとも自動変数が保持されるのは書いてるように見える。
実用上どうでもいいとまで言いきっちゃうのはどうかと思うが。
自分には
>>86 が実用にならないんだろうかなどという話をしてるようには読めない。
>>124 atexitに登録された関数の実行のタイミングぐらいは知っとけよ。
>>125 実用にならないんだろうか
→実用に耐えうる場面もあるのではないだろうか
>>122 つまり、ポインタは有効であることが保証されるが、free可能な領域を指していない可能性は大いにあると
茶々を入れるようだけどC++でatexit()のタイミング知らなくても何も困らない希ガス
Cでも困らな(ry
まぁ
>>86 は、スタックインスタンスへのポインタ?をいちいち全部静的記憶に
登録するというかっこいい超設計より、例外一発でmainまで脱出して終了する
方がコスト高いかもしれないと思ってることになるから、exitの実装より例外の
実装を勉強した方がいいとは思う
自分はデキると思ってる人たちの痛いレスだらけになってるよ いや、実際デキるのかもしれないけど状況はスルー力検定開催中だよ
>>132 そこまで誤読できるのもすごいわ。勝手にやってな。
勝手にやってなというわりに、 勝手に書き込みをしている人にいちいち噛み付くのはなぜなのかしら〜♪
誤読も何もそのまんまじゃん
訳:かまってほしいな
×相手しても無駄かな ○まともに反論できなくなってきちゃったから降りたいな
東方厨はホント低能だな。
煽りに完全に転じた人が現れたようです
訳:話題を逸らしてごまかしたいな
>>86 はatexitに登録する手法は無意味だと分かった上で、
>>85 > だから、間違いなくatexit()で呼び出されるように登録することは難しいといいたいのだろ。
間違いなくatexitに登録した関数が実行されるように登録するのは難しくないということを
言ってるんだろ。
atexit 厨が東方厨ってことじゃないの?
「atexitで実行する関数に破棄すべきスタックインスタンスを登録するのが」難しい って話だろ
例外の件は、正常系は例外を返すべきでないってことでしょ。
難しい、という言い方だと揚げ足を取られる可能性あり。 無駄に面倒、という言い方にすべき。
>>146 それは、勧められる話ではないが、グローバル変数を使えば難しくないだろ。
exitでいきなり終わらせる正常系とか無いだろ
うわ、本当に揚げ足取られたw
>>152 別に。
しかも実際に懸念通りの展開になってしまったようで。
>>153 揚げ足かどうかは認識の違いだな。元々ネタなんだし。
>>156 正常系でもプログラムをさっさと終わらせたいことだってある。
正常系じゃなきゃ例外使っちゃいけないという前提がおかしい。 変に乱用しなきゃいいだけ。
間違えた。正常系では例外を、だ。
>>158 自分もそう思うが、前スレで強く否定する人や正常系で例外を使うべきでないという
正論を言う人がいたりして、今は揺れているというのが実状。
>>161 atexitを駆使してまで例外での脱出を避けるのは、goto絶対禁止とかそういう部類を
思い出すが。まぁ例外はコストがわずかに掛かるが。
とは言っても、例外を完全に排除して例外非対応コンパイルでもしない限り、例外
をthrowかcatchしなきゃ(例外仕様は当然書かない)効率は変わらない訳で、実際
のところはやっぱり宗教論争としか。
>>162 いい加減何度も書くのもアレなんだが、元々ネタなんだよ。自分が担当者だったら、
C++でatexitなんて絶対使わない。(Cならデストラクタがない分、使えば便利なときも
あるかもしれない)
自分は元々さっさと終わりたいときは正常系で例外投げていたクチなんで、例外時に
予期しない重い処理が走る可能性があるとか、正常系で例外は投げるべきでないとか
言われると、ちょっとな。正論は強い。
自分が書いたコードで、「例外使っていて便利でしょ?」とか見せたとき、そんなことを
言われると、返す言葉もない。
そしてスルーされてる質問が
>>163 最初はともかく、いつの間にかネタじゃなくなってるようにしか見えない奴がいる
って話だろ
グローバル変数に設定されたスタックが有効なままexitされたかどうかの判断って面倒じゃない? 関数を抜けるときに必要分POPしたりすんの?
どうせ破棄が気になる時にexitなんか呼ばないんだからどうでもいいじゃんよ・・・
どうせやらないからどうでもいいんでそろそろやめろ ↓ 何もやらないで文句言う奴よりまし ↓ どうせやらないことをだらだら無駄に実験垂れ流す奴よりまし ↓ 取っ組み合い
>>167 元々atexitを使ってるプログラムのデバッグをさせられるなんて可能性は十分に
考えられるよ。規格、仕様なら隅々まで知っていて損はない。
>>170 そういうふうにしか捉えられなかったとしたらすまなかった。
徹底的に粘る人なんだなぁ こういう人は絶対に「お前の方が馬鹿だ」って態度を曲げないと思うけど、 まだ取っ組み合うの?
そのタイプが二人揃うとこうなる訳ですよ
>>172 馬鹿にはしてないよ。ちょっと深読みしすぎじゃないか。
自分の文章がどう見えるかが分からないタイプでもあるようだ
人格攻撃始まりました
そんなの受け取りかた次第でしょ。被害妄想かもしれないし。
◎◎◎ ◎◎◎ ◎◎◎
windowsでもunixでも、確実にテンポラリファイル作る方法ありますか DVDから起動したり、読み取りアクセスしかない場合はカレントディレクトリには出来ないのですが。
>>180 tmpfile()
が使えるかも知れない
>>180 環境変数で設定されているテンポラリフォルダに作る
サンクス tmpfile調べてみます 環境変数は、どの環境でも同じやり方で、確実にとれるんですか。
tmpfileはファイルのパスが特定できないみたいですね。 そのファイルをリネームしたりしたいんです。
思いっきり環境依存の問題を環境に依存せず、とな ファイルのリネームだって環境依存だろうに ディレクトリデリミタの問題だってある せめてgccとかビルド環境を限定しないと答えられんのでは 素直にその手の事を吸収するライブラリを使うか 個別に書いて切り分ける方がいいと思うけど
>>183-
>>184 まさかこんなレスが来るとは予想できなかった
対象とするunixは何?
codepad
ttp://codepad.org/xmwNfoSh Hogeクラスのデータメンバdataの型を
Hogeのコンストラクタの引数で決定したいと思っているのですが、
そうるすとdataの宣言の< >内が書けません。
どのようにすれば良いでしょうか?
>>187 継承を使うべきところをテンプレートにしてるのが間違いに見える
Dataクラスは不要でHogeではD*を持つように
そしてHogeのコンストラクタでD0/D1をnewするのが普通のやり方かと思う
newの失敗とデストラクタに注意しないといけないとは思うが
class Hoge
{
private:
D* pdata;
public:
Hoge(int flag){
//以下は例外を投げる可能性があるので注意
if(flag==0){
pdata = new D0();
}else{
pdata = new D1;
}
(以下略)
>>188 それだと Hoge() を2回呼び出しただけで死ねる。 auto_ptr ぐらい使おうぜ。
Hogeはコンストラクタだし 質問にはそこまで含まれてないんだからいいんじゃね
入力ファイルをプログラム引数として受け取るってどうゆう事ですか?
>>191 FILEポインタを食う関数か、
ファイルネームを食って関数内で展開する関数か、
または実行ファイルの引数で指定するか。
変数Aに1を代入 これをwhile(1)などでずっと繰り返しているとメモリがモリモリたまるのですが、 なぜでしょう? どこかでログを取っているんでしょうか またこれを防ぐ方法はありますか?
そんなことはない 貼り付けてみろ
>>194 すいません、なりませんでした。気のせいでした
>>192 上二つもプログラム引数って言ったりするもんなの?
プログラム引数なんて用語はない
ガチスレかと思った。
すみません。これらの文字列が 一つでも出現するか調べたいのですが速い方法ありますか。 調べる文字列がおおくなるほど、その個数分時間が増える方法しかわかりません。 = 一つ一つ調べる。 "HTML" "html" "?xml" "?XML" "<body" "<BODY"
>>199 正規表現(となるべく高速な正規表現エンジン)を使う。
正規表現は多機能な分だけ遅い気がしてます。あと、orで繋いだ文字列が長くなりすぎるとバグる、不安定になります、
>>199 互いの単語の相関からマップを作って無駄な検索をしないで済むアルゴリズムは存在するけど
名前を思い出せない
まともな正規表現エンジンは単純なORだとかなり最適化できるから自分で適当に組むよりは早くなるとおもうよ。
>>201 長くなりすぎるとバグる正規表現エンジンってどれ?
205 :
199 :2009/10/24(土) 02:39:58
ローリングハッシュ+ブルームフィルタと、鬼車で速度比較してみます。前者を今から作ってみます。 ここで複数同時検索見つけました。 ラビン-カープ文字列検索アルゴリズム - Wikipedia
>>204 秀丸と、Regrepに入ってる正規表現dllです。秀丸の場合、最大文字数制限があるんですが。
TR1の正規表現でいいだろ。
>>199 検索文字列がそれだけなら
適当に作ってみようか?
おねがいします
>>199 検索文字列が短いのでハッシュに用いる文字数を先頭4文字だけにした。 うーん我ながら酷いコードだ
#include<map>
#include<string>
#include<cstdio>
unsigned long get_hash(const unsigned char *p){
unsigned long hash=0;
for(int i=0;i<4;i++) hash=(hash<<8)|p[i];
return hash;
}
int main(void){
char *wordlist[]={"HTML","html","?XML","?xml","<BODY","<body",NULL};
unsigned long hash=0;
std::map<unsigned long, std::string> wordmap;
std::map<unsigned long, std::string>::iterator it;
FILE *fp;
if((fp=fopen("hoge.txt", "rb"))==NULL) return 1;
for(int i=0;wordlist[i];i++) wordmap[get_hash((unsigned char*)wordlist[i])]=wordlist[i];
fseek(fp, 0, SEEK_END);
size_t filesize=ftell(fp), pos=0;
fseek(fp, 0, SEEK_SET);
char buf[filesize+1];
fread(buf, 1, filesize, fp);
buf[filesize]='\0';
for(int i=0;i<filesize;i++){
hash=(hash<<8)|(unsigned char)(buf[i]);
if((it=wordmap.find(hash))!=wordmap.end()){
if(strncmp(buf+i-(4-1), it->second.c_str(), it->second.length())==0)
printf("%s found at pos %d.\n", it->second.c_str(), i-(4-1));
}
}
fclose(fp);
return 0;}
>>199 C言語で書き直してみた
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
unsigned long get_hash(const unsigned char *p){
unsigned long hash=0, i;
for(i=0;i<4;i++) hash=(hash<<8)|p[i];
return hash;
}
#define HASH_TABLE_SIZE 1031
int main(void){
unsigned char *buf, *p, *wordlist[]={"HTML","html","?XML","?xml","<BODY","<body",NULL};
unsigned char *hash_table[HASH_TABLE_SIZE]={NULL};
unsigned long filesize, i, j, flag, hash=0;
FILE *fp;
if((fp=fopen("hoge.txt", "rb"))==NULL) return 1;
for(i=0;wordlist[i];i++) hash_table[get_hash(wordlist[i])%HASH_TABLE_SIZE]=wordlist[i];
fseek(fp, 0, SEEK_END);
filesize=ftell(fp);
fseek(fp, 0, SEEK_SET);
buf=calloc(filesize+1, sizeof(*buf));
fread(buf, sizeof(*buf), filesize, fp);
for(i=0;i<filesize;i++){
hash=(hash<<8)|(buf[i]);
if((p=hash_table[hash%HASH_TABLE_SIZE])){
flag=(strncmp(buf+i-(4-1), p, strlen(p))==0); // 毎回 strlen するのは無駄なので工夫してね
for(j=0;!flag && (p=wordlist[j]);j++) flag|=(strncmp(buf+i-(4-1), p, strlen(p))==0); // 毎回 strlen するのは無駄なので工夫してね
if(flag) printf("%s found at pos %lu.\n", p, i-(4-1));
}
}
free(buf); fclose(fp); return 0;
}
サンクス。 自分でラビン-カープ文字列検索を作ってるけど、 文字列長が一定だといいけど 一文字や二文字程度が入ってくると、パフォーマンスが落ちるね。
先頭2バイト一致するか調べたら簡単で速い気がしてきた。 ヒットしたら完全一致調べる。 ラビン-カープ文字列検索は一回ごとのハッシュ計算に手間かかる。
先頭2バイトが登録されていたら完全一致調べる方法。 #include <iostream> #include <vector> #include <string> using namespace std; #define str2int(x) *(unsigned short int*)x int main(){ unsigned int n, k; vector<unsigned char> chk(1<<16, 0); vector<string> findstr; findstr.push_back("HTML");findstr.push_back("html");findstr.push_back("?xml");findstr.push_back("?XML");findstr.push_back("<body");findstr.push_back("<BODY"); for(n=0; n<findstr.size(); n++) chk[ str2int( &findstr[n][0] ) ]=1; string s = "nbtgfhsdfmrjgijmhimhtmljdtiohbjfguhndug" ; char findflg=0; for(k=0; k < s.size()-1; k++) if (chk[ str2int( &s[k] ) ] ==1 ) for(n=0; n < findstr.size(); n++ ) if( memcmp( &s[k], &findstr[n][0], findstr[n].size() )==0 ) { findflg=1; goto end; } end: if(findflg) cout<<k+1<<" moji me de hit\n"; else cout<< "not found\n"; }
いまからテキスト(html)で実測してみる
複数箇所にまたがって使う可能性のあるクラス(Factoryやその生成物、利用クラス)はポインタの形式を統一したほうがいいですよね? それとも早いのと賢いので細かく使い分けるべきですか?
219 :
199 :2009/10/24(土) 18:24:09
実測したよ。 tr1::regexは結果が間違えてるんだが。 211さんのはテストケースに書き換えるのが面倒で入れなかった。 215の方法 178秒 一つ一つstring::findで調べる方法 280秒 正規表現 鬼車 590秒 vc++2008 tr1::regex 868秒
ここまでboost::xpressive無し
strstrもなし。
正規表現なら鬼車がいいだろ Ruby(オリジナル版には入ってないかも)、桜エディタ、 Bregexp.dllの後継bregonig.dllに使われている。
インラインアセンブラもなし
215より速くできる方法あるの
vector<string>に複数の文字列を定義時に登録する方法ありますか?
C++0x対応コンパイラに乗り換える
static int fnc(); と int fnc();は何が変わるんですか。
自己解決 ひとつのファイル内のみで使用できるって事ですか。
仮想関数ってポインタアクセスしてるらしいし、つまりinlineしても無駄無駄ですよね?
インライン化できるならコンパイラが勝手にやるよ
これらって同じかと思ってミスりました。 memcmp( buf, "\x20\x45\x4D\x46", 4); memcmp( buf, "0x200x450x4D0x46", 4); memcmp( buf, "0x20454D46", 4);
KMP とか AC とかあるよ
KMP じゃなくて CW だった。
反復子の正しい初期化方法を教えてください。 演算子のオーバーロードで初期化できる反復子は問題ないのですが そうでない、反復子はどのように初期かするのがベストなのでしょうか? template<class Iterator> class Foo { private: Iterator lite_; //ok Iterator rite_; //ok Iterator it_; //? Iterator p_; //? public: Foo() : it_(0), p_(0){} //これがベストなのでしょうか? Foo( Iterator lite, Iterator rite ) : lite_(lite), rite_(rite){} };
>>234 一般的にコンテナのインスタンスに依存せずに要素を指さない有効なイテレータを作る方法はないし、
nullや0から変換できるとも限らない。
>>235 thxです
>nullや0から変換できるとも限らない。
なるほど、やはりそうですか自分もそんな気がしていました
なので、nullや0から変換する方法というのは、他に方法が無い場合仕方無しにやってます。
boost::optionalとかどう?
boost は何でもあるんですね、また驚きました、参考にさせてもらいます。
クラステンプレートでoperator() はオーバーライドすることが可能でしょうか? もしできるならば、簡単な雛形を教えてください それからSFINAE の使い方で、関数テンプレートの事例は検索すれば いくつか出てきますし、「C++テンプレートテクニック」という本を読んでやり方は分かるのですが クラステンプレートの事例が検索できません、もしかしてSFINAE はクラステンプレートには適用できないのでしょうか? ここで言うクラステンプレートとは template<class T> class Foo {}; このような形式のことを意図します。 コンパイラはvs2005です。
基底クラスがないのにオーバーライド?
>>239 です
>>241 さんありがとうございます、ファクトリー関数を検索したのですが、具体的にイメージができません
下記のFooクラスおHogeクラスの間で継承関係を持たせ、operator() を自在に呼び出せないでしょうか。
#include <algorithm>
#include <iostream>
#include <vector>
template<class T>
class Foo {
typedef typename std::iterator_traits<T>::value_type value_type;
public:
void operator()( const value_type& val )
{ std::cout << val << "\n"; }
};
template<class T>
class Hoge {
public:
typedef typename std::iterator_traits<T>::value_type value_type;
int operator()(const value_type& val)
{ return val; }
};
int main()
{
std::vector<int> lhs, rhs; lhs.push_back(1); lhs.push_back(2); lhs.push_back(3);
std::for_each(lhs.begin(), lhs.end(), Foo<std::vector<int>::iterator>());
std::transform(lhs.begin(), lhs.end(), std::back_inserter(rhs), Hoge<std::vector<int>::iterator>());
copy(rhs.begin(), rhs.end(), std::ostream_iterator<int>(std::cout, " "));
return 0;
}
どういう動作をしてほしいのかわかりません
>>243 継承により基底クラスのメンバー関数を使いたいのですが、今回の場合はどちらが基底クラスになってもかまいませんが
仮にFoo クラスに
int Widget();
というような関数が定義されて、基底クラスとした場合、Hoge クラスでそれを使えることはもとより
operator() も呼び出せるようにしたいのですが。
using Foo<T>::operator ();
>>245 それは何処に記述して、main() からどのように呼び出したらいいのでしょうか?
>>242 無理。その二つのoperatorはそもそも継承可能な同一性を持たないから。
そうですか、ありがとうございます int operator() とvoid operator () と違うから継承不可能なのでしょうか?
インターフェースにコピーコンストラクタや代入ってつけないほうがいいですか? ぜんぜん違う実装同士だとすごい困るんですけど・・・
>>249 付けて困るんなら付けなきゃいいじゃん。
コンストラクタから、オーバーロードされたコンストラクタを呼び出すってアリなんですか? class CHoge { public: CHoge(int x) { CHoge((float)x); } CHoge(float x) { ... } };
0xではアリ
もしかして、コンストラクタからオーバーロードされた普通のメソッドもダメ?? class CHoge { public: virtual void func() {...} }; class CHogeEx: public CHoge { public: CHogeEx() { func(); /* CHogeEx::func を呼びたい */ } public: virtual void func() {...} };
>>254 × オーバーロード
○ オーバーライド
「ダメ」の意味がよくわからんが、 CHogeEx をさらに派生して func() をオーバーライドしていても
CHogeEx のコンストラクタで呼び出されるのは CHogeEx::func() になる。
つまり C++ のコンストラクタ(とデストラクタ)の中では仮想関数による動的多態は効かない。
それオーバーロードされてなくね
クラスのstaticなメンバの初期化は class Hoge{ public: static int foo; }; Hoge::foo = 1; のように、fooをクラス宣言の外で初期化してあげるのが 教科書や多くのサイトで書かれていますが、 std::basic_string::npos は、 static const size_type npos = static_cast<size_type>(-1); とクラス宣言内で定義されています。 同じようなことをstd::stringで行ってもできません。 これは単純に、staticなメンバ変数でもプリミティブ型であればクラス宣言内で定義しても良い、ということでしょうか?
関数を抜けるころにはもう参照を使わないとわかってる→参照か生ポインタを引数にしてもよい メンバ変数にほかのインスタンスへの参照として持たせたい→寿命がよくわからない→スマートポインタ 動的に確保して返す関数→値捨てられたら困る→スマートポインタ メンバ変数を返す関数→外で参照を保存されたらバグる可能性がある→値返し 引数と返り値の参照について↑みたいにやってるんですが、もっと明確で安全な基準みたいなのってありませんか?
>>260 さらに int 型、じゃなかったっけ?
>>258 ,260,262
staticでconstで整数型じゃなかったっけ。 超うろ覚えだが。
ちなみにVCの6か7ぐらいまではそれすらもできないので、enumハックという手法があったがそれはもう昔の話。
enumはOKで整数はダメとか、実に理不尽だったよな。
ゆとりは知らない残念なVC++の歴史シリーズ ・#pragma warning( disable : 4786 ) ・#define for if(0) ; else for ・#include <c****>してもstd名前空間に入っていない ・クラススコープでstatic const intの初期化ができないので代わりにenumを使う ・std::wcout << L'A' << std::endl ・<algorithm>にmin/maxがない ・typenameがなくても大体なんとかなってしまう(今でも) ・newが失敗すると0を返す(標準策定前なので仕方ないと言えば仕方ない) ・テンプレートクラスにテンプレートメンバ関数を作成できない(当時ほとんどのコンパイラは未対応だったのでまぁ仕方ない) それが今ではexportと例外仕様以外はだいたい標準準拠の立派な子に成長しました。
__finally節が実行されない場合があると知ったときの落胆ときたら。 なんのためのfinallyなんだよw 今ならBOOST_SCOPE_EXIT使うけど。
今でも、ダイアモンド継承が正しく機能しないとか ADLが標準に合致しないとか Cライブラリがstd名前空間に含まれてないとか 問題山積みだけどね。
まぁ問題山積みじゃないコンパイラは珍しいし C++以外ですら
VisualStudio6の時代が長すぎたのもあるね。 2002/2003は見送ったところが多かった。 2005からかな、みんな使い出したのは。
CInputState& s=State[0]; s.Up|=KEYDOWN(DIK_UP); このソースの2行目の |= は何を表しているのでしょうか? +=や-=ならちょくちょく目にしますが、|=というのは・・・?
>>270 a += b は a = a + b といっしょ。
a -= b は a = a - b といっしょ。
a |= b は a = a | b といっしょ。
>>271 ありがとうございます。
助かりました。
C言語から入ってアセンブラに行くと a += b の方が a = a + b よりも機械語の形式に近いと知って軽いカルチャーショックを受けるよな? 俺だけか?
>>273 考えた事もなかった。
ADD A, B
こうゆう事?
>>274 そうそう
CPUによっては3オペランドの四則演算もあるんだろうけど
ほとんどのCPUでは2オペランドが基本なんだよな
考えてみれば当たり前なんだが
昔々アセンブラを初めて触ったころ、へぇ〜と思った
BASICに代入付き四則演算子がなかったもんだから
なおさら、ほぉ〜と思ったな
先にアセンブリ言語を知っていたから、Cは簡単だった。
>>275 このスレで答える側の人たちは昔からプログラムやってる人が多いのかな?
BASICなんて見たことも触ったこともないな。
>>276 Cが簡単って人は俺にとって神に見える。
俺はJavaからC/C++に入ったからCがかなり難しく感じる。
涙でディスプレイが霞むほどに難しい。
人によるとしか言いようがないんじゃね?
最近Fortranやったんだがa+=bが使えなくてがっかりした でもa(1:n)=a(1:n)+b(1:n)とか配列周りに関しては感動した
少なくともCは、データがどのようにメモリに格納されているかを常に念頭に置いておけば 難しいところはないんじゃないか。 C++は全然違うけど。
>>277 VisualBasicも基本的にはBASICだということを忘れてないかい?
C++は言語仕様が大きすぎて
ソフトを作るためにC++使ってるのか
C++の深淵を知るためにC++を使ってるのか
分からなくなる
>>281 なんか作ろうとして、その途中でつまずいたりアイデアを思いつくと言語の勉強が始まって、気づいたら半日過ぎてたとか良くある
>>281 そういえばVBなら少し触ったな。
基本的にはVBもBasicか。あまりにイメージが違いすg・・・
今までJavaでWeb系の開発やってていっぱしのプログラマ気取ってたんだが
C++の難しさになみだ目。C++の何が難しいって、そもそも実現しようとする事柄が難しい。
プログラミングの第一線から退いた先輩方から「オブジェクト指向ができるなんてすごいね」
なんて言われて「いや、そんな事ないですよ(フフ」なんて言ってたんだが
C++を勉強し始めた今になって猛烈に恥ずかしくなってきた。
あんたらがやってきたことに比べれば、俺がやってるWebのプロジェクトなんか屁みたいなもんですよと。
あんたらがもっと若かったら純粋なオブジェクト指向の言語においても俺より優秀な技術者になってんだろと。
今度先輩に現役時代の話を聞いてみよう。
チラ裏ごめん。
どっちが凄いなんてないけどな たまたま時代のニーズによって勉強した物が違うだけじゃん でも確かにC++の深淵を〜は確かにそういう嫌いがあるよね……
1byteを削るのに必死な時代は想像できないよな ドラクエ1を64KiBに収めるとかどんな拷問かと… memcpyさえないレベルから作るわけで そもそもC言語とか一切使ってないんだろうなぁ
バイト単位で削る世界だとアセンブラ以外は論外だな。 ところで、C++は巨大と言われるけど、一つ一つの機能をどうコンパイルされるか 把握しながら理解すれば、そこまでバカみたいな巨大さは感じないなぁ。 とは言っても、応用が色々と奥深いけど。
C++が巨大っていうのはどこらへんを言ってるのだろう。皮肉じゃなくて、純粋に。 他の言語はLLぐらいしかあまり使ってないので。 たしかに大きいなとは思うけど、必要だから大きいのであって、無駄なものは そんなにないと思うんだが。
Cとの互換性を保ちつつ必要そうなものを足していったから 複雑怪奇に感じてそれを巨大だと表現したりするんだろう 無駄だとかじゃないんだ
巨大とまでは言ってないでしょ
C++は直接見えない部分の注意点が多すぎると思う
コンストラクタでの例外とか
>>251 みたいなのとか
多重継承とか
デストラクタの動作タイミングとか
STLの諸々とか
無駄ではないけど複雑すぎるんだよね
メモリイメージさえできてれば使えるCに比べると
間違いなく問題ないコードを書いていると確信できるまでに
必要な知識量があまりに多すぎる
だからといってJavaでは中途半端すぎて満足できないw
>>289 もう――――――――
もう何時間―――― こうしているのか――――
蹴っても――――
いくら蹴っても――――――――
不安がなくならない!!!
ってことだよな。CとC++の最大の違いはw
それはちゃんと理解してないまま使ってるからだな ちゃんと理解してないと安心して使えない言語なのが悪い、というのも一理あるし、 理解してればCより遙かに安全で気楽になったりもするし
Cでは異常系の処理がパンクしちゃうから、C++のほうが結局は楽で安全だと思うけどな。 C++とCの最大の違いは、仕様変更の荒波にどれほど楽をして対応できるかどうかではないかな。
C++で気を付けなければならないリストみたいなのを作って、新たにC++を学ぼうと する者が全員それを読めばいいんじゃないか。
>>293 Effective C++はじめ、そこらじゅうに名著がありますよ。
もちろん、業務としてC++を使う人たちは全員読んでいますが。
C++ の方が基本的にはCより使うの安全で楽だとは思う。 流儀はある程度決めておかないと収集つかないけど。 気分的には「巨大」というのはわからないでもない。CとC++と両方 のやり方がかぶってる部分がかなりあるから、機能面だけから考えれば 不要な部分が多い。互換性は重要だから無駄ではないのだけど。
入力ファイルからデータを読み込みロジック部分を関数化し、 qsort関数以外を使用して番号順にソートしたいのですが何かいい方法があれば教えてください。 例) F016 C002 C002 C015 H001 F016 C015 H001 H009 H009 左のデータをソートし、右のように並び替えたいです。
関数オブジェクトは値で渡せって言われたんだけど、実行時ポリモーフィズム的に使いたい場合はどうするの? struct func_obj { virtual void operator () (hoge &h) = 0; }; struct func_obj_1 : public func_obj { void operator () (hoge &h) { h.method_1(); } }; struct func_obj_2 : public func_obj { void operator () (hoge &h) { h.method_2(); } }; void execute(hoge &h, func_obj &f) { f(h); } int main(void) { hoge h; execute(h, func_obj_1()); execute(h, func_obj_2()); return 0; } この場合はconst参照にすればいいけど内部に乱数を持ってたりするとconstじゃ困る
>>296 読み込みが終わったらソートできてる状態にすればいいと思う
>>294 それは当然だが、それらを読まない人が多いから巨大だとか言われるわけで、それらを
簡単にまとめた物を言っている。原理を詳しく知りたかったら原著を読めばいいし。
C++には新規参入など要らないということであれば話は別だけど。
>>281 でもその「深淵を覗いている感じ」は、なかなか他の言語では得難いものがあるよねw
なにか、つきあいの長い人に意外な一面を発見する喜び、みたいな。
整数のゼロ除算はif(div==0)でチェックできますけど実数のゼロ除算はどうやって調べるのが妥当でしょうか?
実数の内部表現は処理系依存。
エラーで停止したくないんだったら、 z = x/y を if ( y < 十分小) z=十分大 else z=x/y にしとけ
>>302 std::numeric_limits<double>::epsilonとか使うといいんじゃないか。
if ( y ニアリーイコール0) z=十分大 else z=x/y
>>297 struct func_obj_wrapper {
func_obj_wrapper(func_obj& f) : f_(f) {}
void operator()(hoge &h) { f_(h); }
func_obj& f_;
};
>>303 > 実数の内部表現は処理系依存。
…なんだけど、IEEE-754 な環境だと普通に
x / 0
= ±∞ (x != 0)
= ±NaN (x = 0)
じゃなかったっけ?
C++ の ostream について質問なんですが、数値を大文字の 16 進数に変換するのに 簡単な方法は無いでしょうか? std::hex だと小文字になってしまうし・・・。
>>310 std::ios::uppercase
>>311 速答ありがとうございました。
うまく大文字に変換できました。
std::vector<int> lhs; for (p = lhs.begin(); p < lhs.end()-6; ++p) { } lhs.end()-6 の表記が間違っていると思うのですが、どのように書いたらいいでしょうか?
間違ってはいないと思うけど、constじゃないコンテナのend()はちょっと重いかもね。 それと、size()が6以下だとまずいね。
実現したいことがいまひとつ分かりにくいけど lhsの先頭から終わりの6つ前まで走査したいってこと? それなら for(size_t i = 0; i < lhs.size() - 6; ++i){ // lhs[i]でアクセス出来る } でいいと思うが
素直に書けばいいのに不自然なことして悩んでる質問が多くね?
パフォーマンスがそれほど気になる状況なら if (lhs.size() <= 6) ; // エラー処理なりreturnなり std::vector<int>::const_iterator last(lhs.end() - 6); for (std::vector<int>::const_iterator p(lhs.begin()); p != last; ++p){ } でおkでは。
C++ではfor文の比較は!=にしようね。<などは、あるイテレータの種類やカウンタで フォールトトレランス性はあるけど、コンテナの種類が変わると使えなくなる可能性がある。
2ずつカウントアップしたらスルーされる可能性ある。 n++だとしても、ループ内でnの値が変わったら停止しなくなる。
>>319 ステップが1でないループやカウンタが任意の値に変わるようなループは
普通じゃないんで、使う側がそれを想定したコードを書くべきではあるが、
普通はそんなことを想定しなくてもいいと思うよ。
基本的にintなど大小が付いてる場合では、条件はなるべくきつめにつけて置くべき。 != → <= 値が小さいとき、どちらもループするが、!=では飛びこえても停止しない。 同じ事を説明しているだけだがな。
バグが見つかる可能性を減らす事になるんでしない
漏れも。たとえば5周でぴったりとまってほしいのに、 6周や7周して何事もなかったかのように続行されてはあとで大変なことに。 だから「5周で終わらなきゃだめ!」って言う条件を 「まぁ、5周以上になったら適当なところで終わってね」なんて緩めたりしない。
!=とアサート併用が常識だと思ってた
>>324 それは「5周以上」じゃなくて「5周以下」じゃね?
1→7とかなって2周で終わる。
あと、i!=5 と i<5 は事後条件に違いがあるから
どちらが適切かは事後条件次第じゃないかと。
で、forにおいて日常的に!=を使うか<を使うか、++iを使うかi++を使うかは
効率の問題とかもあるんだけど、結局は宗教論争なんだよね。
cout と printfに並ぶくらい。
>>318 の、コンテナの種類が変わると使えなくなる可能性があるというのは宗教的な話で片づけられることなのか?
そりゃあ書き換えると不適切な場合は言わずもがな。 いちいち言及しないと気になる?
気になって夜も眠れないでごわす! ・・・うそw for文の宗教論争はGoogle Coding Standardsにも出てくるけど 「まぁ、好きにしろよ」っていうオチだったと思う。
http://codepad.org/fR8BNHWy C++を学び初めて四日目です (VC++2008です)
ドラクエ風戦闘プログラムの勇者の攻撃だけの部分を作ってみたんですが、
クラスのオブジェクトが生成できてないとかメンバ関数が何故か使えないとかで困ってます
オーバーロードが多重定義だというのはググったんですが、関数は一つしか定義してないはずなので多重定義といわれても分かりません……
どうにか問題を解決してもらえないでしょうか
ちなみにオーバーロードやらポインタやら継承やらはまだ勉強してません
あと他の部分のコードでこうしたらいいよ、とかあれば教えてください
!=のほうが<よりも効率はいいことが多いがな。
vectorからlistに変えたいとき、for文がたくさんあれば!=になってないと 修正が大変だわな。
>>331 それがまた宗教論争の種なわけだ。
サッターは時期尚早の再不適化はやめようと書いているけれども
果たしてコンパイラの最適化能力をどこまで信じないかという問題もある。
>>332 こちらの問題にはメイヤーズが答えている。
どのコンテナにも使えるコードを書けると思ってはいけない。
・・・一般論では宗教論争にしかならないのはこのため。^^
だいたい、std::vector<T>::iteratorが < や <= で比較可能なことは保証されてるのかよ。 == と != は確実に保証されてるけどな。
仕様は!=なんで、<にするのはフォールトトレランス性は確保できるが、上にもあった けど、バグは潰せないんで、やっぱ自分は!=かな。
あとでSTLを使うかもしれないという理由で != に統一すると、停止しないバグに遭遇する危険。 整数型なら< >にしとけ
>>333 宗教論争と言うけど、いろんな引用してるけど、ピントが合ってないよ。
時期尚早の最適化は止めよう。
↓
最適化と仕様の実装とは別の話。仕様は!=。
どのコンテナにも使えるコードを書けるとは思ってはいけない。
↓
だが、多くのコンテナに変更可能なコードを書くことは悪ではない。
for(n=0; n!=10; n++) { n+=rand()%3; } とか中で追加してたら、バグ発生するだろ。 バグでないのに。
>>330 見てるところがちがんじゃない?
どうも「endl」でエラーが出てるよ。
endlってそういう使い方しないと思うんだけど。
>>336 バグはassert等で対応するべきであって、仕様を曲げるのはおかしい。
>>334 保証されている。ランダムアクセスイテレータは<や<=が使用可能。
>>336 停止しないバグがあるならバグを直すべき
>>337 >宗教論争と言うけど、いろんな引用してるけど、ピントが合ってないよ。
そう、あなたのおっしゃるとおり。
あなたにはピントが合ってないように見えるけど
そう主張している側からはピントぴったりにしか見えてない。
for文の宗教論争史(あるかどうかしらないけど)を調べると
今まさにあなたの反論がそのまま出てくるよ。
>>344 いやいや、それは逃げてるだろう。
仕様と最適化の問題は答えが明らかだろう。
>>339 ありがとうございます! endl;を抜いたらうまくいきました。 cout<<endl;とすべきでしたね
>>345 まぁまぁ。^^
いちどそのあたりの宗教論争を調べてみるとおもしろいよ。
まったくかみ合わない論争だから。w
ちなみに、自分はさっきの引用が「正しい」とか「的を射ている」とは思ってないよ。
かみ合わないのを承知で引用している。
>>321 の条件ならfor文じゃなくてfor_each使うべきじゃね?
まぁ使いにくいんだけど
>>346 あと、各case節の終わりでbreakしなくていいのかい?
>>349 変なループが直りました! ありがとうございます
まぁ普通はポインタやインデックスじゃなくイテレータを比較するなら!=が無難だろ 実装の中身が生ポインタならば、というような仮定はしたくないからな
別の話になるけど ちょっとイテレータを弄ろうとするとend()に++したり、begin()に--出来ないから 一々チェックを入れる必要が出てきて非常に面倒。でも普通のポインタも保証無いんだっけ?
最初の前は見れないけど、最後の次は見れるんだっけか。
>>353 3行目以降の意味が全くわからんけどとりあえずboost::nextとboost::priorでぐぐれ
参照とポインタってどっちが速いんだろう
バイナリになっちゃえば同じ。 そうでない処理系もあるかもしれないけど。
参照だな。 参照とインライン展開だと、ひとつもメモリの生成しないですむが ポインタは32bit か64bitの変数を生成するからな。 でも計測可能なほどかは微妙だが
別に vector 使うなら iterator 明示的に使わないで v[j] みたいに 使ったっていいんだけどな。そっちの方がわかりやすいなら。
>>350 リンク先を見ずに言うが、「的を射ている」と書いてるよ。
当を得ているとすべき、的を得るもあながち間違いとは言い切れない
という意見もあるけど、何で「的を得ている」についてのアンカーを?
「ちなみに」と書いてあるから、ちなんだんだろう。
NULLが入っていた場合対策では
よくわからないので試してみましたが、エラーにはなりませんでした。 int main(){ int iii = NULL; iii = 1; }
f (NULL, NULL)という呼び出しの場合。
私の実行環境のビジュアルスタジオではヌルで呼び出しても問題ありませんでしたが
>>1 のアップローダーでコンパイルしたところ、エラーになったため、理解できました。
ヌルの扱いはコンパイラ依存なんですね。
ありがとうございます。
初期化子の方がまだわからないのですが、教えて下さる方いませんか?
>>362 引数リストでの代入式はデフォルト引数の指定。
ClsA(n1) は基底クラスの初期化。
理解できました 変数だけでなく、コンストラクタも初期化子で初期化できるんですね。 というと、基底クラスの関数も初期化できそうですね。 ありがとうございました。
なんでNULLとかいってんだ?
>>362 は納得できたからいいけど。
ソース1の2行目に出てくるi(list)はどうゆう構文なのでしょうか? iがそもそもなんだかわからないのでVisualStudioの「定義へ移動」を使用したところ、WinCrypt.hに飛ばされ その中の記述がソース2のようになっていました。 不思議な事に、「定義へ移動」を使用してもWinCrypt.hに飛ばされずに何も起こらない事もありました。 //ソース1 1:void CShtGame::DrawTask(CTaskList* list) { 2: for (CTaskIter i(list); i.HasNext(); ) { 3: ((CMover*)i.Next())->Draw(); 4: } 5:} //ソース2 1:typedef struct _CRYPT_RC4_KEY_STATE { 2: unsigned char Key[16]; 3: unsigned char SBox[256]; 4: unsigned char i; 5: unsigned char j; 6:} CRYPT_RC4_KEY_STATE, *PCRYPT_RC4_KEY_STATE;
>>370 iはCTaskIterクラスのインスタンス。名前から察するに、CTaskListのイテレータなのだろう。
i.HasNext()はiが指しているlistに次の要素があるかどうかを返す関数だと推測する。
いずれにしろ、この際WinCrypt.hは関係なさそうだな。
CTaskIter 型の変数 i を1個の引数 list で初期化している for 文の最初で for (int i = 0; ..... ) のように変数宣言できることをご存じない? それとも int i(0); のような書き方で変数が初期化できることをご存じない?
>>371 VisualStudioの誤動作だったんですね。
>>371 >>372 CTaskIter i(list)は、CTaskIterクラスの引数がCTaskListになっているコンストラクタを呼び出してたんですね。
いろいろ勘違いしていました。ありがとうございます。
違う。コンストラクタの呼び出しじゃなくて、インスタンスの生成。 インスタンスを生成する途中でコンストラクタも呼び出すけど。
誤動作って言うよりは誤操作って感じだな。
>>374 そんなこと言うと、変数の初期化だとか変数の定義だとか、もっと言い換えできるぜ。
コンストラクタの呼び出しとインスタンスの生成の違いは、言い換えってレベルじゃねーだろ
>>377 「コンストラクタの呼び出し」と「インスタンスの生成」って、そんなに違うか?例えばどこが?
その違いは「インスタンスの生成」と「変数の定義」よりも大きいんだよね?
CTaskIter(foo); // A CTaskIter i(foo); // B Aがコンストラクタ呼び出しの構文だろ? Bが変数定義。
>>378 この場合は自動インスタンスの生成だから、スタックからメモリを確保する作業が
含まれるな。
自動インスタンス生成と変数定義は変わらん。インスタンス生成と自動インスタンス
生成は違う。
CTaskIter i(); // C では、これは何でしょう?
コンスラクタの呼び出しはplacement newを使う。 void* p; に対して、 CTaskIter* q = new(p) CTaskIter(foo);
>>380 「自動」ってつければそうなるね。
後だしジャンケンっぽいけど、言いたかったことはわかったからまぁいいや。
俺が
>>381 だが、誰か俺の引っ掛けクイズに反応してやってくれ
正しくは、CTaskIter i(list)はCtaskIterクラスの引数CTaskListのコンストラクタを呼び出してインスタンス化し、
そのインスタンスの位置情報(使用しているアドレスの先頭)をCtaskIter型のiという名前で定義した変数に割り当てている。
ということでしょうか?
書いてて自分でよくわからなくなってきたんですが、おそらく間違っていないでしょう。
間違っていないで下さい。
>>384 CTaskIterクラスのデフォルトコンストラクタを呼び出してインスタンス化し、
そのインスタンスの位置情報(略)をCtaskIter型のiという名前で定義した変数に割り当てている。
ひっかけ・・・?
有名な本のネタをそのままやってもな。
>>385 ありがとう。救われた気持ちです。
iという名前で、CTaskIter型の戻り値を持ち、引数が無い関数のプロトタイプ宣言です。
関数の宣言に見えるものは関数の宣言。
T t = param; じゃなくて T t(param); を使いたい時ってどんな時だろう。何かあった気もするけど。
すまん、焦りすぎてて豪快に間違えた、忘れてくれ
>>387 正解しちゃってすみませんと思いながら書き込んだのにこのざまですよ。
Cみたいにvoidがないとプロトタイプ宣言と見做さない仕様ならこんなこともなかったのに…… とは言え、CTaskIter i(void);と書くのも気持ち悪いなw
まぁ、Cのその仕様も単にANSI以前への互換性の為に一応、って感じみたいだしな
C++を独学で覚えたくて本を買って勉強しはじめたばかりなんですが、質問があります。 BCCDeveloperを使ってDXライブラリを使う設定したはずなんですが、DXLib_lnitとDXLi_Endで未定議の関数とエラーがでます。 ググッて調べてみてもわからず... どなたかアドバイスいただけないでしょうか。
関数名が間違ってるだけじゃね?
エラーメッセージはコピペしてくれないと質問時のタイプミスなのかもとから違ってるのかわからん
>>395 です。
みなさんありがとうございます。
今はコピペできないので帰宅したらエラーメッセージをコピペします。
まあまあ、要領を得た質問ができるようなら、そりゃ既に初心者じゃないよ。
初期化はこれが安全ってことでOK? explicit widget(type); widget w = widget(t);
>>400 explicit使うと下の書き方は出来なくなるだろ
widget w(widget(t)); でも関数とみなされるかもしれないから
widget w((widget(t))); が一番安全だな
最近C++も勉強しはじめたのですが、new演算子がよくわかりません。 下記の二つのソースは、出力を行う関数の内部的な動作を除き まったく同じ意味になるのでしょうか? あまり要領を得た質問とは言えず、心苦しいばかりですが もしもJavaもわかるという方がいらっしゃればお願いします。 //Javaの場合 Test t1 = new Test(); Test t2; t2 = t1; System.out.println(t1 + "\n" + t2); //t1とt2は同じ値(アドレス値)が表示される。 //C++の場合 Test t1; Test *t2 = new Test(); t2 = &t1; cout << &t1 << "\n" << t2 << endl; //t1とt2は同じ値(アドレス値)が表示される。
>>403 //C++の場合
Test t1;
Test *t2;
t2 = &t1;
こう。
じゃないとメモリリークする
>>402 VCとCODEPADでコンパイル通ったよ
最適化されてないとコピーコンストラクタ挟まれるっぽいけど・・・
>>404 なぜnewした方だけがメモリリークするのでしょうか?
ポインタはnewしたしないにかかわらず、deleteしないとメモリリークしてしまうものだと思っているのですが・・・
今回の場合、Test *t2 = new Test();でもTest *t2;でもdeleteをすると実行値エラーが出てしまいます。
結局newしない書き方でもメモリリークするように見えるのですが、違うのでしょうか?
javaのTest t1はc++のTest* t1。javaのTest t1 = new Test()はc++のTest t1* = new Test()に等しい。言語仕様の違い。考えることではなく覚えておくこと。
408 :
お約束 :2009/10/29(木) 20:12:51
これだからJava厨は……
ガベコレあるからメモリリークしても問題ないもんね
>>409 何も考えずに shared_ptr 使えばいいよ
>>395 とりあえず、こだわりが無いなら素直にVC++2008EEにした方がいいと思うが。
昔はWindowsで比較的素直に使えるフリーコンパイラがBCCくらいしか無かったが、
今はVC++EEがあって、ぶっちゃけBCCより遙かにまともに動くし、Windowsだと
VC++以外全く考えられてないのも普通だし。
イテレータでvectorをfor文でbeginからendまで読んでいる途中でそのvectorにpush_backしても問題ないですか
>>403 はむしろ、C++のTest t1;の意味を誤解してそうな気がする。
C++の場合、これで作られるのは参照じゃなくて値(インスタンス)。つまり、
そのソースではインスタンスが二個作られてる。
Test *t2 = new Test();の方は、new Test()がヒープ上にインスタンスを生成して、
それを指すポインタを返す。で、t2というポインタ変数に代入する。
C++では、ヒープ上に生成したインスタンスは必ずdeleteしなきゃ駄目なので、
delete t2;をしないとリークする。これが忘れやすくて危険だから、専用のクラスを
作って、コンストラクタでポインタを記憶してデストラクタでdelete、という手法が
ある。いわゆるスマートポインタで、有名なのはshared_ptr。既に標準ライブラリに
入ってる処理系も多数あり。無くてもBoostライブラリを入れればおk。
これをポインタ以外に広げて、例えばファイルハンドルをコンストラクタで生成や
記憶などして、デストラクタでクローズ、というように、資源の確保と開放を専用の
クラスに包んでしまうのがRAIIという概念で、資源リーク回避の基本技。
>>412 push_backでイテレータは無効化される
push_backの後でイテレータを拾い直すならおk
shared_ptrのコピーってポインタの十倍以上時間かかるのね これからは生ポインタ引き数でいいところは生にしよう
すいません。下記のようにやるとセグりました。どうやればいいんでしょう。 vector<Objects*>::iterator it; for(it=v_obj.begin(); it != v_obj.end(); it++){ if(ある条件){ push_back(new Objects()); } }
v_obj.push_back(new Objects())のミス
とりあえず、下記のようにして回避したんですが、もっとスマートな方法ないですかね。 vector<Objects*>::iterator it; for(it=v_obj.begin(); it != v_obj.end(); it++){ if(ある条件){ flag = true; } } if(flag){ flag = false; v_obj.push_back(new Objects()); }
>>416 別にテンポラリのvectorを作って、ループの中ではテンポラリの方に追加しておいて、
ループを抜けてから連結。
あと、激しくメモリリークの予感。
>>407 把握しました。
>>410 >>413 Test t1;の動作は理解していましたが、newはメモリ領域を確保するだけで、インスタンスは生成しないものだと思い込んでいました。
つまり、
>>404 さんが示してくれた方法の場合、ヒープ領域を使用していないからdeleteはできないし不要なわけですね。
下記のように書くと、1行目と2行目で計2回インスタンスを生成していて、2行目でnewしたインスタンスが完全に無意味になる上に
Testクラスにポインタを使用しているメンバ変数があった場合、そのメンバ変数に割り当てられたヒープ領域が開放されない(リーク)というおまけが付いてくると。
1:Test t1;
2:Test *t2 = new Test();
3:t2 = &t1;
shared_ptrはおもしろいですね。
メンバ変数に関してはデストラクタにdeleteを書けば良さそうですが
ローカル変数に関してはこれを使っておけば安心できそうです。
ためしに近々使ってみます。
ありがとうございます。
>>416 生ポインタをコンテナに突っ込むのはやめれ、どうしてもというならshared_ptr を使うと幸せになれる
STLは糞。全部自分で管理するしくみを作った方が早い。
>>419 やりたがってることがイマイチわからないけど、そのコードから受け取れるものだけで言うなら、
ループ内でこうすればいいんじゃないの?
if (ある条件) {
v_obj.push_back(new Objects());
break;
}
今回の君のコードからは、一つでも「ある条件」を満たすものを見つけたら
もうその時点でループは用済み、という状況がうかがえるので。
そういうこと(何をやりたいか、何をやらなくていいか)をちゃんと書いて欲しいんだけどな、
質問する時は。
プログラムを簡略化してるからちょっと分かりずらいかもしれません。 ループは最初から最期まで全てのイテレータである処理をしてます。 (*it)->do_something(); 途中でbreakするわけにはいかないです。 この方法だとif(ある条件)が複数回満たされた場合に1回しかpush_backしませんが、 今回はこの方法で私の問題は解決しました。複数回できればなお嬉しいですが。
譲れない条件を「簡略化」したら、「分かりづらい」じゃなくて、わからなくなるよ。 もう他に新事実が無いというのなら、for文の前にint count = 0;でも置いて、ループ内で if (ある条件) { ++count; } として、あとからcount個の要素を追加すればいい。
粘着うぜ
>>415 shared_ptrのconst参照という手もあるよ。
>>421 メンバ変数もshared_ptr使っておくほうがいい。デストラクタでdeleteだと抜けがある。
>>421 リークする、と断言したのは、
1:Test t1;
2:Test *t2 = new Test();
3:t2 = &t1;
としたときに2でヒープに確保した領域をdeleteできなくなるから。
>>421 まだ何か誤解があるぽ。
> Testクラスにポインタを使用しているメンバ変数があった場合、そのメンバ変数に
> 割り当てられたヒープ領域が開放されない(リーク)というおまけが付いてくると。
そうではなく、Testクラスのインスタンスがnew Test()によってヒープ領域に生成
されるが、CやC++では、ヒープに確保したメモリ領域は自分で解放する必要がある。
newで確保したならdeleteで。mallocならfreeで。new[]ならdelete[]で。
だが、そのコードでは、newでヒープに確保したメモリ領域を指すポインタはt2に
まず代入されるが、t2 = &t1;の時点で上書きされるので、newした領域がどこに
あるか分からなくなる。つまりdeleteできないので、普通に考えればリーク確定と
いうこと。Testクラスのインスタンスそのもののメモリ領域がリークする。
純粋仮想関数を持つ抽象クラスはインスタンス化できませんが デフォルトコンストラクタをprotectedとして宣言、定義して、インスタンス化拒否を明示するのか コンパイラが自動的に生成するのを用いるのか、どちらが妥当なんでしょうか。
>>431 なんでそんな余計なコードを書こうかなんて思うの?
>>428 shared_ptrは一般的なんですね。
レスポンスが少し気になるところですが、使っておきます。
>>429 new Test();がdelete不可なんですね。把握しました。
※newして生成したインスタンスを格納した変数は、deleteせずに他の値を格納すると
デストラクタ内で処理されているか、スマートポインタを使用していない限り必ずリークする。
>>430 昨日は少し混乱していました。
Testクラス内にメンバ変数がなくても、newした段階で最低1byteは使用するため、結局deleteできなくてリークすると。
今度こそ完全に理解しました。
>>433 大丈夫、未だ勘違いしている。
生成したインスタンスのポインタを格納しているポインタ変数に、他の値を格納してしまうと
単純に、最初のインスタンスのポインタが失われるのであってデストラクタも何も走らない。
まさに、>408だな。
なんと! デストラクタ内で適切に処理しておけば問題ないと考えていましたが、書き方によってはリークするんですね。 ヒープに確保した領域が行方不明になるような書き方してたら コンパイルエラーにしてくれればいいのにというのは甘えですか?
1:Test t1; 2:Test *t2 = new Test(); 3:foo->bar(t2); 4:t2 = &t1; この場合leakするかどうかは 3 の内容に依る。不完全 な警告をコンパイラに実装して「警告が出てないから leakしてない」なんていう阿呆を産み出すよりは出さな い方がマシ。
書き方によってはリークするのではない。 適切に書くことによってリークしないのだ。 -- Test * func() {return new Test();} -- void someOtherFunc() { func(); } -- これでもリークするわけだが、例えばfunc()が別のコンパイル単位にあるとしたらどうやって検出しろと?
3行目はいったい何をしているのでしょうか? 関数のプロトタイプ宣言のように見えますが そうすると戻り値がvoidで関数の名前がInitで引数は無し?*の意味は・・・? .h.cppのどちらにもInitを実装しているような箇所は見当たらないし 3行目はどうゆう意味なのでしょうか?
失礼しましたソースです。 //Common.h 1: struct STAGE { 2: const wchar_t* Name; 3: void (*Init)(); 4: int TopTime; 5: };
関数ポインタです。
>>438-439 引数も戻り値もない関数へのポインタ。
わからない単語はぐぐればいいと思うよ
>>439 型がよく判らないときは、括弧に注目。この場合、Initに*がついていてそれが括弧で拘束されている。
つまり、Initはポインタ変数であることが判る。
それが指しているものは、void ()()となるので、戻り値のない、引き数もない関数となる。
要は、void func()という関数と同じ型の関数ポインタであるInitの宣言。
少し調べてみました。 メモリ領域はコード、データ、ヒープ、スタックの4種類にわかれている。 //関数ポインタ。コード領域へのポインタ。 void (*Init)(); //普通のポインタ。データ領域へのポインタ。 int *a; //deleteしないとリークするポインタ。ヒープ領域へのポインタ。 int *a = new int(); //スタックは今のところ使い方がよくわからないので割愛。 構造体の中に関数ポインタを入れておくと、より汎用的なコーディングができる事がある。 助かりました。
>>443 ヒープに確保されないオブジェクト、つまり自動変数とかはスタックに確保されて、
スコープアウトしたらデストラクトされる。
>>444 補足ありがとうございます。
//普通の変数。スタック領域に実態がある。
int main(){
int a;
Cls b;
}
//普通の変数。データ領域へのポインタ。
class Cls{
public:
int a;
TestCls b;
}
//これはスタック違いかな?メモリ領域のスタックの事ではなく、スタックという機能?
#include <stack>
template<Class T, class Container = deque<T> > class stack{};
>>445 *が付いてなければおよそポインタではない
まだ何か勘違いしてない?
>>445 スタックってデータ構造もあるけど、それに近い機能をもったメモリ領域がある。
関数とかの中で、
{
/*DoSomething...*/
}
のように記述するとブロックとして認識されてそのブロックの中で宣言された自動変数はブロックを抜けると破棄される。
これをスコープという。ブロックは入れ子にしたりして何個でも作れる。
ポインタなどはポインタ変数は破棄されるが、指してる先をdeleteするような器用さはない。
ちなみに、以下は
class Cls{
public:
int a;
TestCls b;
};
どっちの宣言も自動変数。
sizeofで見てみるとわかると思うけど、sizeof(int)+sizeof(TestCls)の領域が確保されることになる。
C++の参照型は、
Cls& <- 一度しか初期化できない参照。
Cls* <- 何度でも初期化できる参照。名前はポインタと呼ばれる。
javaだとクラスを宣言すると無条件でC++でいうCls&の形をしたポインタが使われるみたいだ。ちなみに俺はJAVAは初心者以下だ。
仮想関数テーブルとか考えると危険な…いや、なんでもない よく分かってないことは書かないことにしましょうか
449 :
447 :2009/10/30(金) 14:47:30
>>448 vtableは使ってないから説明してない。
仮想関数のオーバーライドの説明だけど、
C++の上書きオーバーライド(virtual function)は、大雑把に言って関数ポインタを上書きすることで実現している。
そのためにはクラスのメモリのどこかに関数ポインタのリストを持つためのポインタを持つことになる。
基本的にこれはメモリを操作してかきかえる類ではないのであることを知っていればいい。
で、仮想関数を持ったクラスをsizeofをすると関数ポインタのリストのポインタ変数のサイズ分増分して返ってくる。
>>446 ×//普通の変数。データ領域へのポインタ。
○//普通の変数。スタック領域に実態がある。
なんかもう滅茶苦茶ですね。
書き間違いと勘違いといろいろまざtt・・・
>>447 #include なんちゃら
int gInt; //データ領域に実態が格納されているグローバル変数(非自動変数)
TestCls gCls; //同上
class Cls{
public:
int a; //スタック領域に格納されている自動変数
TestCls b; //同上
};
int main(){
int a; TestCls t; //スタック領域に格納されている自動変数
}
今度こそOKでしょうか?
>>448 >>449 初めて目にした単語なので、wiki見てみましたがイミフ。
基底クラスAを継承したサブクラスB,Cがあり
Aで仮想関数speakを宣言し、B,Cクラスでそれぞれ実装した場合、次の関数の呼び出しはどうなるか?
ClsB b;
ClsA *a = &b;
a->speak();
どう考えてもBで実装したspeakが呼ばれます。vtableの入る余地がありません。
ちょっと試行錯誤してきます。
1.ClsA *aはポインタ型なんだから、ClsAの継承クラスのインスタンスならどれでも受け入れられる。 2.受け入れるオブジェクトの型は、ユーザーの入力などにより動的(実行時)に変化する。 以上より仮想関数テーブルが必要になる。 450のように、静的(コンパイル時)に型が限定できる場合ばかりではないということ。
>>450 基本的にグローバル変数も自動変数というルールに違いはない。
それは、グローバルスコープに宣言されているという前提になる。
あと、ちょっと妙な書き方をしてしまったので訂正するが、
class Cls{
public:
int a; //スタック領域に格納されている自動変数
TestCls b; //同上
};
上のクラスをnewしたら、自動変数とされる領域もヒープに確保される。でも動作は自動変数と変わらない。
deleteした瞬間がスコープ終了の瞬間。
あと、オーバーライドの話。
C++のオーバーライドはvirtualをつけなかったら、上書きされない。よって、vtableも生成されない。
つまり、基本的には、そのクラスで宣言されたそのメンバ関数が呼ばれる。
virtualをつけてオーバーライドされる前提のメンバ関数は継承先で上書きすることができる。
virtualの上書きされた関数は、基底でも上書きされた関数を呼ぶ。
もちろんインスタンスは実装したクラスのインスタンスじゃないといけないけども。
ちょっとした違和感を感じたんだが、
>>450 の言うデータ領域って、たとえばimmutableな文字列定数とかを格納するところかな??
static constの変数とか。
何かもう、ネイティブコードでどう実装されてるかから説明した方が早い気がしてきた
>>451 ttp://codepad.org/Pldw34mI 1と入力するとsub1が表示され、1以外を入力するとsub2が表示されます。
何も問題ありません。頭が爆破寸前です。
>>452 >上のクラスをnewしたら、自動変数とされる領域もヒープに確保される。
おkです。
>でも動作は自動変数と変わらない。
>deleteした瞬間がスコープ終了の瞬間。
自動変数の定義は、「関数内で宣言された記憶クラス指定子の付かない変数」ですよね?
deleteさえしっかりやれば、newしたものも自動変数と同じ振る舞いをすると。
>>453 >>450 のソースのコメントは間違い・・・?
下記2種「以外」の変数が格納される領域がデータ領域?
・グローバル変数
・自動変数
>>455 C++におけるメジャーなメモリ領域は2つ。
一つはスタックと呼ばれる領域。一つは、ヒープと呼ばれる領域。
スタックは宣言したときに確保されてスコープが終了したら破棄されることを約束された領域。
ヒープはメモリのプールで必要なときに確保して不要になったらユーザの責任で開放する。資源は有効に。
で、コード領域やデータ領域というのはコンパイラやOSの最適化によって発生した領域。
たぶん、データ領域は何度も参照されるような定数データを効率よく回すための機構で基本的に書き込み禁止。
で、たぶん、コード領域はプログラムコード自身をOSがロードした領域。
なので、後の2つはC++の仕様外だと思う。
>>456 静的記憶期間(static付きやグローバル変数など)のオブジェクトの置き場なのだから、
データ領域はスタック・ヒープと同列に扱おうよ。
規格書でも(言葉は違うけど)その3つの概念は出てくることだし。
コンパイル時には、ClsSub1になるのかClsSub2になるのかわかっていない。
→このままでは、ClsSuper::test(), ClsSub1::test(), ClsSub2::test()のどれとしてコンパイルすればいいのかわからない。
このコードで言うと、sub1, sub2 superのどれを表示していいかわからない。
ここまでは大丈夫?
次に、ClsSuperの隠しメンバ変数にpTestFunctionという関数ポインタを追加して、
実行時、インスタンスが生成時にその関数ポインタへ使用すべきメンバ関数を代入するようにする。
ClsSuper *s; には使用すべき関数ポインタが含まれているので、
コンパイル時に s->test(); という文を、関数ポインタからの呼び出しに翻訳する。
実行時に、sがどの型をさしていようと適切な関数ポインタが指定されるので、問題なく実行できる。
> 1と入力するとsub1が表示され、1以外を入力するとsub2が表示されます。
というのは、仮想関数テーブル(=関数ポインタのようなもの)が仕事をしてるから。
とりあえずコメントにも補足書いたけど、以上が仮想関数テーブルが必要な理由。
http://codepad.org/uuPlC3eO
>>456 >>457 も言ってるけど、スタックとヒープと静的の三つとした方が。
静的記憶は普通に読み書き可能なことが多いんじゃないかな、x86では。dsセレクタで
アクセスされるようなセグメントに配置するのが一般的な気がする。
リードオンリーの定数はむしろ、コンパイル時点で埋め込んじゃう気がするし。
スタックもヒープも物理的には同じだぞ。 コンパイル時に固定サイズの領域を割り当てるのがスタック。 スタック不足になるのは、メモリが足らないからではなく 予測以上に初期の固定メモリを使い切ったため。 物理的には、スタックもヒープも違いはないので、 多くメモリ確保するなら動的=ヒープがいい。
>>456 >>457 >>459 >>460 今の私の認識と、説明していただいたメモリ領域の説明がだいたい一致するので
メモリ領域に関しては大丈夫そうです。
>>460 >多くメモリ確保するなら動的=ヒープがいい。
私がはじめに学んだ言語ではそのあたりを気にしながらコーディングしていましたが
c++においてはまったく意識してませんでした。
メモリをいっぱい使うような処理をする場合には気をつけてみます。
>>458 40行目で正しく関数が呼べてるのは仮想関数テーブルがあるからなんですね。
コーディングしている分には見えないものですが、内部的には説明してくださったような動作になっていると。
今日1日でc++に対する理解度がだいぶ深まった気がします。
aa
でもヒープ確保には、OSとのやりとりがあって、生成に時間食うがな。 スタックは、はじめに確保した領域を使い回すだけだからOSとのやりとりはなく 高速。
動作速度に関しては、 スタック ヒープに違いはないが 生成と破棄に関しては違いが出るってこと。 長いこと(10秒以上とか)保持するなら、 生成コストは無視できるから 安定性のためヒープを使う方が良いな。
待て待て、スタックとヒープは実装原理が全く違うがな。適当言うんじゃない。 一般的なスタックは、pushするかスタックポインタを移動させることで積み上げて、 破棄する時はスタックポインタの移動だけで終わるから、ヒープに比べたら圧倒的に 確保も解放も高速だぞ。
確保と解放は速度差があるが、確保されたメモリを使う分には同じ速度だな。
>>465 確保方法に違いはあっても、どちらも同一の(実)メモリつかうんだよ。
OSに問い合わせるか、C言語が管理している領域に問い合わせるかだけ。
スタックでさえ仮想メモリに移動することもある。
OSや他のアプリからみれば特殊な物ではない。
とりあえず確保解放の速度が圧倒的に違うのは確実だけどな、スタックとヒープじゃ。
>>466 がほとんどの環境で正解。
圧倒的に違うといっても総実行時間の何%だよ 以下ループ
ボトルネックに突っ込んだら恐ろしく違うだろうな
まぁ環境によっていろいろあるってことでFA
dllを作っているのですが デバッグでは作成できて、リリースしてビルドすると ライブラリ ***testdll.exp を作成中 LINK : fatal error LNK1561: エントリー ポイントを定義しなければなりません。 ビルドログは "***" に保存されました。 testdll - エラー 1、警告 0 と表示されてできません どうすればできるのでしょうか・・・・・
>>472 「エントリーポイントを定義しなければなりません」
↓
エントリーポイントを定義すればできる
これぐらいの推測ができないようじゃ、前途多難だな。
enumとかstatic constの定数は外のクラスに見せないならクラススコープでprivateで定義するのが良いんですよね?
コンテナのイテレータから、渡されたコンテナの要素数を求めることはできますか? template<class Iterator> size_t Size(Iterator it) { return ?; } int main() { std::vector<int> lhs; lhs.push_back(1); lhs.push_back(2); std::vector<int>::iterator ite; ite = lhs.begin(); int n = Size(ite); // こんな感じでコンテナの要素数を求めたいのですが }
vector::size()では何か不都合でもあるの?
>>475 です
vector::size() をこのように使っているのですが
これでは、イテレータを渡しても、当然のことですがエラーになってしまいます、
なんとかイテレータを渡して、そのコンテナのサイズがわからないものかと思案しています。
template <class Container> inline
size_t Size(const Container& c)
{ return c.size(); }
要素へのポインタを所有しているコンテナを特定する手段があるなら可能
>>470 ボトルネックの個所で
スタックだろうがヒープだろうがメモリの確保解放するコード書くのは論外だろう
>>479 秒間一万回程度の半端なボトルネックだと、スタックかヒープかで致命的な事態に
なるだろうな。
まぁ、違いを知った上で、大差無いと判断したところで使うのは最初から問題無い。
「違わない」と断言するのは激しく問題があるってだけ。カーネルに落ちる場合は
スタックの数万倍も重いことがある訳で。
>>478 thx です
関数オブジェクトを作っていて、引数が多くなってしまい
なんとか、減らせないものだろうかと思い質問したしだいでした
要素へのポインタを所持しているコンテナを引き渡すのなら、
要素数を引き渡すだけのことなので、同じくらいのコストがかかりそうで
あききらめますが、要素へのポインタを所持しているコンテナを引き渡して
要素数を求める方法へ関心があります、単純な実装例をご教示願えませんか。
c.size()
>>477 イテレータのペア(開始と終端)を取る関数オブジェクトなら
std::distance(it1, it2) で [it1-it2)間の要素数が求められるよ。
>>475 ,477,481
ひとつのイテレータからコンテナの要素数を求める一般的な方法はないよ。
実装依存の機能でそういうのがあるか、自分で実装すれば可能。
beginとendがあるなら
>>483 のでいける。
>>484 ありがとう
>実装依存の機能でそういうのがあるか、自分で実装すれば可能。
もし仮に実装するなら、どんな感じになるのでしょうか?
まずは、イテレータのアドレスを取得しなければならないのはわかるのですが
それ以降の展開が想像できません、向学のために概略だけでも教えてもらえないでしょうか。
>>485 MinGW だとイテレータはコンテナのアドレスを持ってるようだ
そもそもイテレータ渡ししてるのに本当に要素数が必要なのかから考えるべきな気がする。
>>485 元のイテレータの派生クラスかラッパークラスを作って、そいつに要素数か親コンテナのポインタを持たせる。
しかし、親コンテナの要素数が必要な処理ってどんなだ?
コードをさらしてみる気はないか?
技巧する必要なし 元のをを渡せよ。
引き数へらしたいならレンジイテレータでもつかってコンテナまるごと渡せよ
演算子のオーバーライドって一般企業でも使ってますか? パッと見どうゆう動作をするのかわからないから、危険な香りがするのですが。 例えば、タスクシステムを使っていて、とあるクラスをnewするとそのクラスをタスクに追加したりするような仕組みの場合 一見メモリリークするコードに見えます。
>>491 基本的にそういうことはドキュメントに書いておくべきことじゃないかなぁ。
読まない人もいるみたいだけどね。読みやすいドキュメントって言うのもむずかしいけど。
>>491 何を使っても酷いことになる人はどこにでもいるよ
>>491 そんな事言ったらoperator+をオーバーロードしてマイナスの動作を
させるへそ曲がりな事だって出来るぞ
仕様書でちゃんと最初に決めとけ
>>491 基本的には使わないだろう。企業に限らず。
でも、例えば多倍長整数クラスとか、有理数クラスとか、ベクトルクラスとかを
作るなら、operator+を定義しても恐らく誰も間違わない。そういう場合は使う
方が楽という判断も十分有力だし、それでも使わないという判断もやはり有力。
まぁ、暗黙の変換なんかと同じだな。 無闇やたらと使うのは糞設計だが、完全排除すれば良設計というものでもない。
微妙なら()つけろよ。簡単のために公開しない関数内部で使うなら別に良いだろ。
>>497 俺は argument 一つの constructor はやっぱり explicit 付けてる。
operator overloading の方はたまに使う時がある。
スマポなんかは暗黙の変換に対応しないと微妙
>>491 × オーバーライド
○ オーバーロード
あと、タスクシステム死ね。
> とあるクラスをnewするとそのクラスをタスクに追加したりするような仕組みの場合
> 一見メモリリークするコードに見えます。
具体的なデメリットがわかってるのに、なんでそのうえで一般論を持ち出す必要があるの?
すいません。下記のようなことがやりたいのですが、 ”\debug.cpp(13) : error C2059: 構文エラー : ')'” と表示されコンパイルが通りません。どうしたらいいですか。 void Debug::create_debug_message(...) { char tmp_str[100]; sprintf(tmp_str, __VA_ARGS__); // line: 13 }
>>502 void Debug::create_debug_message(const char *format, ...)
{
char tmp_str[100];
va_list ap;
va_start(ap, format);
vsprintf(tmp_str, format, ap);
}
できました。ありがとうございました。
そういや可変長引数長い事使ってないなあ リハビリしとかなきゃ
506 :
491 :2009/11/03(火) 18:00:50
>>492-497 多倍長整数クラスの+のように、直感的にわかるような動作をするものなら演算子のオーバーロードをしても良いが
基本的に多用するものではないということですね。
>>501 >×オーバーライド
間違いを確認しました。
>具体的なデメリットがわかってるのに、なんでそのうえで一般論を持ち出す必要があるの?
デメリットがあっても、それを打ち消すようなコーディングの仕方や
デメリットを凌駕するメリットがあれば、演算子のオーバーロードを積極的に使っていこうと考えていたからです。
私はC++を勉強しはじめてまだ日が浅いので、私の知らない何かがあるのかもしれないと思い、質問させてもらいました。
一般的な演算子のオーバーロードに対する考えが聞けて、とてもためになりました。
ありがとうございます。
>>506 業種によっても違うんじゃないかな。
私のところは画像処理や数値計算関係なので座標の足し算とかベクタの掛け算なんかが
頻発するので演算子オーバーロードはあるとないとじゃ大違いだから。
ベクトルの掛け算も演算子オーバーロードしちゃうのか… 内積にすんのかな
スカラ倍のことじゃないの
内積、スカラ倍両方オーバーロードするのもありだな。 いずれにせよ、ベクトルや行列使った数値計算とかは オーバーロードしないとコードが読めなくなるからリスクとの トレードオフとして悪くないと思う。
インラインアセンブラと組み合わせれば演算子でSIMDも可能 って考えるとなんか夢が広がるような気がするよね 実際には関数呼び出しだって同じなんだが、表記的に 高水準(抽象的)・低水準(具体的)の混在具合が脳汁出そう
ベクタ×ベクタは演算ライブラリによっては内積だけど、 演算ライブラリによっては敢えて用意していないね。 それでもスカラ積があるだけでも随分違うけど。
「絶対に内積だろ」とは言い切れないし、スカラ積だけ対応するのが個人的には好み だけど、内積でも別に文句言うほどじゃないかな
スカラ積って内積じゃないの
iostreamやBoostに見られるような「Cの文脈からかけ離れた演算子オーバーロード」 は、実際使ってみると割と平気だったりするんだよな。 ただ、見慣れない問題に直面する可能性も高いから、やっぱりお仕事だと微妙かな。 boost::formatとか激しく便利ではあるんだけど。
小学生ktkr
スカラー積=内積 ベクトル積=外積
スカラー積ってスカラ倍のことじゃないの?
もうその話題は終わり
namespace Hello { class A; }; namespace World { class B; }; ヘッダーファイルに上記のように書いたところ、 class Bの所属がなぜかHello::World::Bとして扱われてしまい、 コンパイルエラーになります。これはコンパイラのバグでしょうか? 環境はwinXP x86 VC++ 2008Expressを使ってます。
どうせ打ち間違い 523自体は正しい
ていうかエラーメッセージ書けって
もう少し状況を詳しく書いてみます "helloworld.h" namespace Hello { --class A; } namespace World { --class Hoge; --namespace Button --{ ----enum Value { A, B, C }; --} }; "hoge.h" #include "helloworld.h" namespace World { --class Hoge --{ --public: ----Button::Value m_value; --} }; "error messeage" C3083: 'World': '::' の左側のシンボルには、型を指定しなければなりません C2460: 'Hello::World::Value::m_value' : 宣言されている 'Hello::World::Value' を使用しています。
>>526 namespace Helloが閉じていない。
# まぁ、想定の範囲内だな。
Hello:: まで書くとvisual studio のインテリセンスがWorldや ヘッダーに書いた他のnamespaceを全部含んでしまっているように表示します。 World::やその他のネームスペースからはHelloを参照することはありません。
;が抜けているのに気づけない間抜けであったか。
本当だ。すいません小さなミスでした。
VCなんですけど floatとdoubleはどっちが速いですか?
>>531 一概には言えませんが、doubleで組んで速度に不満があったら両方実測して比較すればよいでしょう。
floatが速いよ 昔は、doubleに変換されるという説もあったが、いまは直に計算する。
特に配列に格納すると、メモリ呼び出しが半分のサイズですむから 計算だけではなく、メモリサイズと呼び出し時間が短縮できる。
フロートがSSEで二倍速い
namespaceって;必要だっけ?
必要じゃないことはないですよ
floatにしてみます。
floatは有効桁数がIEEE754では6桁しかないよ だから用途が限られる 画面座標とか
配列のインデックスは符号無しですか?
厳密に言えば、いいえ
ポインタの計算だからマイナスもある
まず配列のインデックスの定義をだな
namespace は ; いらないよね?? class は ; いるけどさ。 ていうか namespace {} に ; つけないで普通に使っているんだが…
クラス定義は文だから;が必要で名前空間はスコープだからいらない。たぶん
確かポインタ間の距離はptrdiff_t型で符号あり整数じゃね?
struct foo { int bar; } buzz; class foo { int bar; } buzz; namespace foo { int bar; } buzz; // ← これだけ明らかにおかしく見えれば大丈夫
>526がセミコロンが抜けているのは事実だが、>527は間違い。 >534、>535は正しいが、速度よりも>539の問題の方が通常は問題になるので、doubleを使っておくのが無難。 ポインタ演算については>542、>546の通りだが、>543の言うように「インデックス」が何を指しているかが問題。
C/C++でZipファイルの追記したいのですがいいライブラリありますか。 DLL使うと、中間ファイルを生成してから追記するので遅いです。 100Mのzipファイルならそれをopenして追記したいです。
tarならできるだろうけどzipはむりじゃね
zlibは圧縮は出来るけど、書庫のフォーマットには対応してないですよね?
>>548 > doubleを使っておくのが無難。
それは微妙。どっちが向いてるのか考えるべき。ちょっと考えれば大体正解が選べるし。
例えば、APIがfloatを要求してるような場合はfloatが無難。
floatは精度に注意、floatとdoubleを無駄に混在させるのはアホ、SSEでは圧倒的に速度
が違う、SSE使わないならほんの僅かにfloatが速い、くらいであとは自己判断かな。
混在を避けるのは鉄則。doubleの演算速度よりも、float⇔doubleの変換の方がよっぽど遅い。
下のようにvectorの入った構造体があります。 typedef struct { std::vector<int> foo; std::vector<float> bar; } HOGE; これを値渡しすると、各vectorのコピーコンストラクタはちゃんと呼ばれるんでしょうか。
>>556 それも環境次第だとは思うけど、少なくとも整数の符号拡張みたいに単純にはいかない。
フォーマットの変換が必要だから。
x86のFPUだと相当なコストがかかるけど、SSEなんかだとどうかは知らない。
>>557 ヒント : C++では基本的にclass と struct は同等の扱い
デフォルトのprivateとpublicが違うだけ
>557 ヒントより短い答え:呼ばれます。
そんな巨大になりそうなもの値渡しして欲しくないな
大丈夫 俺のちんこよりは小さいから
>>553 よく読めてないけど、オンメモリで展開、追加、圧縮をやってるんじゃないの?
>>561 新人「大丈夫ですよ先輩。sizeofで見たらたった80バイトです」
ああそうだ、俺のコンパイラは構造体に巨大な配列を入れて 値渡しすると馬鹿みたいにpushの荒らしになる rep movsが使えないのはpushが逆順になるからだろうな それなら簡単なループ組んで転送すればいいと思うのに pushを配列数分吐くもんだからexeが巨大になって馬鹿みたい
>>563 追記は新規に作ったファイルだけだった
既存ファイルには追記できなかった
追加しようとしたらデータ初期化されたよ
もう一度いうけど、tarならできるだろうけどzipは無理だと思う。 無圧縮zipならできるかな
100個のファイルを圧縮したzipを用意して、それを展開して、一つファイルを増やして、 圧縮して、バイナリ比較して、「追記」が実現可能かどうか見てみたら。 無圧縮でもそれやってみたら。
駄目な理由はなんだ> 絶対出来るはず
rep movsとか最近のコンパイラは間違っても使わないような
サイズ重視のコードなら使う
俺のコンパイラは断りもなくmemcpy呼んでるな。構造体の初期化には勝手にmemset使うし。
>>571 変数の初期化に使われているよ
特に配列だと間違いなく出てくる
そもそも構造体の値渡しが必要な状況ってどんなの? ポインタや参照が使えない状況ってのが思い浮かばない。
逆に考えるんだ。ポインタでは困る場面なんだよ。 それが必要な状況?それは↓
578 :
デフォルトの名無しさん :2009/11/07(土) 03:36:48
ぬるぽ
579 :
デフォルトの名無しさん :2009/11/07(土) 06:46:06
再帰させるときなんかたまに使うけどね。
RECT rc = { 0 }; とかってありなの? VCだと中の変数ゼロになるんだけど
そうだよ
zip64の追記つくってくれ
後半の情報フォーマット部分を追記データで 書き換えれば理論的には可能なはずなんだ。 でも正しいセットの仕方が判らない。
ファイルを個別に zip 圧縮してから tar でまとめるとか…
つか 追記くらいライブラリないのかよ
zipの構造はおおまかに
ファイルヘッダ
圧縮データ
ファイルヘッダ
圧縮データ
....
ファイルヘッダ
圧縮データ
アーカイブインデックス(
>>583 のいう情報フォーマット部分)
てなってるから最後の圧縮データとアーカイブインデックスの間に
追記のファイルヘッダと圧縮データを入れて
アーカイブインデックスにも追加できればいける
7zとかcabなんかのソリッド圧縮形式だと
LZ77の辞書とエントロピー圧縮のコンテキストが必要だから
オンメモリでもいいから一度展開作業をしないと追記できない
ちなみにJavaScriptで無圧縮zip作るひとがいるくらいだから
圧縮をzlibですればzipのフォーマット自体はそれほど難しくない
作ってクレオ
パイロンだと、直書き出来る。 でも巨大ファイル(個数が100万とか)に追記すると解析に時間かかる。 パイロンのzip64の追記のソースをC++に書き換えられる人いますか。 パイロンの例 import zipfile z = zipfile.ZipFile("test.zip", "a", zipfile.ZIP_DEFLATED, True ) z.write("log_data.txt") z.close()
590 :
589 :2009/11/07(土) 14:13:08
実際に400M、50万ファイルのZIPファイルで実験したから間違いない。 コピーしたり展開したら時間かかるが、追記はコピーより速くできた。
c言語の話題かぁ?
struct Bar { Bar(): x(m_x), m_x() { } Foo &x; private: Foo m_x; }; 初期化子の実行順序は、初期化子の順序ではなくて変数宣言の順序だと記憶していますが、 (例のコードではどちらにせよxが先だと思います。)上のようなコードを書くと、xの初期化から 始まって何物でもないm_xを参照してしまうはずなのにVisual C++のコンパイラは警告すら発し ません。 このようなコードは避けるべきということは言うまでもないですが、コンパイラがまったく順序に 関知しないというのはいかがなものでしょうか、と。
>>591 Zipは追記できないという説に対して
ZipもZip64も追記できたと言うこと
VCで複数のソースファイルがある場合、プリプロセッサの処理順てどこで定義されているの? 例えば aaa.h, bbb.h, ccc.h の3つが互いにインクルードしている場合、 全体で使用できるためにはどのファイルで定義すればいいのかわからん
#includeした順に決まってるだろ
何を言いたいのかわからないけど、 #includeはそこにテキストがそのまま展開される。 #include "aaa.h" #include "bbb.h" #include "ccc.h" なら aaa.h が真っ先に展開される。 しかし、非ローカルなスタティック変数の初期化順とかいう話になるのなら それはそれは難しいことに。 違ったかな。ほほほ。
結局、「暗黙の初期化順に依存するな」ってことね。
#define #undef みたいにusing namespaceを無かったことにできないもんでしょうか
逆に、using namespace を使うところだけスコープを切ればいい。 { using namespace boost::lambda; // ここでbindとか_1とか使う } // ここでは using namespace は無効
みんなはusing namespace std;ってグローバルにおいちゃう派?おいちゃだめ派?
Google Coding Standardsではらめってなってた。
チーム全員がstd名前空間の全内容を把握しているなら グローバルでもいいんじゃないですかね。
同一プロジェクトでstd::stringとhoge::stringが混在したらそっちのほうがいやじゃない? だからまとめて共通ヘッダに入れてグローバルusingしてる
いちいちstd::stringとかhoge::stringと書けばいいじゃない。
WinAPI使ってるともっと長くてどうしようもない名前がわらわら出てくるから あんまり気にしたことないなぁ。って言うか末尾にSEXついてるの多すぎ。 マイクロソフトの技術者はどんだけ欲求不満なのか、と。
入力補完で切るエディタなら std::と打ったほうが楽
>>607 sexわろたw
気にしたことなかったけど確かにそうだな
>>576 インライン展開を期待するときなんか、あえて構造体の値戻しを使ったりする。
611 :
デフォルトの名無しさん :2009/11/07(土) 19:41:39
WIN32APIのSendMessageを使用する時、引数のwparamを文字列で渡す方法ってある?WinXPが環境です
とりあえず、グローバル変数の初期化順序に関しては、チューリングマシンの停止問題 みたいに定義不可能な面があるから、依存するな、とかEffectiveC++に書いてあった ような気がしなくもない
そこでシングルトンの登場ですよ。
シングルトンは俺的にはもうアンチパターンだな Google的に、コンストラクタでは単純な初期化にとどめて、複雑な初期化はInit()で やれ、というコーディングを採用してれば、初期化順序で悩むことも無い気がする
単豚
>>614 コンストラクタから初期化を追い出す必要は無いよ。
Init() 呼ぶくらいならグローバルなポインタに new すればいいじゃん。
ゼロオーバーヘッド的にはグローバルなポインタにnewするくらいならInit()呼ぶなぁ
operator newのオーバーロード(配置ではなくて)なんですけどグローバルにするのかstaticメンバにするのはどっちがいいんでしょうか?
一緒。staticメンバは単にクラスのスコープの中に入っちゃうだけ。
>>618 追加の引数が無い奴はグローバルにすると全体に影響が出るから気をつけてな。
ありがとうございます グローバルだと目的のクラス以外でもオーバーロードされてしまう staticメンバだと目的のクラスだけオーバーロードされる ということでしょうか。基本的にはstaticメンバにしたほうがよさそうですね
>>621 影響範囲については、だいたいそういうこと。
細かい話をすると、クラスの奴は派生クラスでも使われる。
あと、追加の引数が無い奴をグローバルに置くのはオーバーロードじゃなくて置き換え、な。
基底クラスのポインタから派生クラスのポインタへのキャストって dynamic_castは遅いけど変換不能な場合NULLを返す static_castは早いけど変換不能でも知らせてくれない これ以外の違いってなんかある?
その基底クラスが仮想関数を持たない場合、dynamic_castは使用できない その派生クラスがその基底クラスを仮想継承している場合、static_castは使用できない (両方に当てはまる場合、どちらも使用できない)
>その基底クラスが仮想関数を持たない場合、dynamic_castは使用できない マジすか初めて知った 確かにできてもあんまり意味はないけど
キャストしない暗黙変換が一番使いやすい。とか本末転倒なこと言ってみる。 HogeBase* hoge; Hoge2 *p = new Hoge2; hoge = p;//基底があってなかったらコンパイルエラー吐く。
dynamic_castが必要になるのは糞設計に仕方なく対応する時だけ
クロスキャストには必須だろ
クロスキャストしたい時点で糞設計になってるんじゃ?
>>629 違う
クラスが複雑になるとクロスキャストしたい局面はよく現れる
×クラスが複雑になると ○継承関係が複雑になると あ、継承関係が糞設計なんだろって突っ込みは無しな そういう事を言い出すとキリがなくなってしまうんで
そうは言っても、継承関係が糞設計なんだろ?w
>>632 ほうら来た
だからそういう突っ込みは無し
人間そこまで完全な奴はいない
特にある程度プロジェクトが進んでしまっていると
今更設計を変えられない事も多い
配られたカードがどんな悲惨でも それで何とか勝負するしかないって事はあるだろう、仕事なら。
最初から「仕方なく対応する時」って書かれてるんだから、それは分かった上でだろう
少なくともC++では、dynamic_castを使う必要が出てきた時点でほぼ糞設計。 糞設計をしてしまうことはあるし、気付いた時には引き返せないこともあるから、 使う時は使うべき。設計は変えられないが他の方法でどうにかしよう、というのは 最悪だから。 でも、そういう事態になったなら設計が糞だったんだ、という認識はすべき。
>>637 それは当たり前だろう
そんな事はわざわざ言わなくても誰でもわかっている
つーかそれ以上の話をする必要を感じない
シェア的にC/C++のコンパイラあげると上二つはVCとgccかなって思ってるんだが、 ベスト5ぐらいには他にどんなのがあるの?
当然 icc は入ると思う。
Code Warrierも入るな。間違いない。
じゃあ俺はLSI-C
http://codepad.org/kd2xzcnB コードパッドのほうだと期待通りに動くんですけど
僕の使ってるコンパイラ(VC++EE2008)ではdelete[]が確保したサイズじゃなくてクラスのサイズを引き数に渡してしまいます
これは規格で定まっていないんじゃなくて僕が使ってるのがただのクソッタレコンパイラということですか?
>>641-645 「シェア」の意味によって違ってくるだろうな。
使ってる人数か?コンパイルされたコードの走っている台数か?
商用に限るのか?学生の講義とかも含めるのか?日本なのか世界なのか?
コンパイルされたコードの走ってる台数だとOSなんかも入って
ちょっとナンセンスになるから、結局人数なんだろうけど。
そうすると組み込み系とかはそんなに多くないと思う。
>>646 size_tを引数にとるoperator delete[]なんて規格にあったっけ?
ああ、そうか。メンバ関数のほうはsize_tを引数にとるのか。
関数を作っています。 int型の引数nに応じて、配列の大きさを決めたいのですが、コンパイルすると 「定数式が必要です」とのエラーメッセージが出て失敗します。 どうすれば私の意図する動作が可能になるでしょうか? int* getTest(int n, int o[], float r) { int p[n][2];// = new int[n][2]; //省略 return *p; }
mallocもしくはnewで調べれ 配列の大きさはコンパイル時に決定されなければならない。
>>650 配列の大きさを指定できるのは一番右側のoperator[]内だけ
int (*p)[2] = new int[n][2];
>>650 関数内でnewやmallocしてそのポインタを返すのは危険きわまる。
C++なんだから、vector<vector<int>>を参照渡しするのがいいと思う。
すまぽが早く実用化されれば、こんな問題どうってことないんだけどなぁ。。。
これがJavaやC#なら、どんなオブジェクトでも平然と返せるんだけどねえ。 shared_ptrを使えばいいんだけどね。std::tr1::shared_ptr<std::string>とか 長くなりがちなのがちょっと。
どこでもshared_ptrに頼るのってどうなのよ コピーと代入のコスト結構馬鹿にならんし 寿命と例外安全考えて使わなくていいところは使わないほうがいいと思うんだし
659 :
650 :2009/11/11(水) 02:52:29
スマートポインタ使わずに平気で関数内new&returnしてますが何か
もらったほうがきちんとすてればなんのもんだいもない
>>659 そこで new はおかしいし、それじゃインスタンス作りようないでしょ。
(vector の大きさも指定していない)単に、
vector<vector<float> > v = vector<vector<float> >(n,vector<float>(2,0));
…
return v;
とかいう話?(次元 nx2 で良いのか知らんが)
それにしても cast をたくさん使ってるね。
毎回floatにキャストしても CPUの中の人は結局doubleで計算するわけ?
>>663 x86系CPU+Visual C++では、そう(doubleじゃなくてlong doubleだけど)。
x64だとちょっと違ってて、多分floatで計算してると思う。
詳しくはx87FPUとSSE演算を調べてみてくれ。
重要なのはx64+WindowsだとFPUレジスタがDisableされていること。
>>660 プロジェクトに悪意あるメンバーがいたらメモリリークさせられるぞ
悪気は無かったんです・・・
667 :
デフォルトの名無しさん :2009/11/11(水) 14:25:35
VC++のMFCアプリで、あるjavaアプレットの画面イメージを取得するため 対象ウィンドウを検索して存在すればCWnd::SetWindowPos()で最前面にもってきて CWnd::RedrawWindow()で再描画、ということを行っています。 対象ウィンドウが他のウィンドウに隠れている場合はこれでいいんですが もともと最前面にある場合は、再描画の処理は不要だと思うのでスキップしたいのですが 最前面であるかどうかはどう判断すれば良いのでしょうか? CWnd::GetWindow()でいろいろやってみているんですがうまくいきません。
>>664 >x64+WindowsだとFPUレジスタがDisableされていること。
されてねえよ
タスクスイッチの時もスレッド切り替えの時もちゃんとFPUはsaveするように
仕様が変わった
>>667 ::EnumWindows()とかでどうか
不安ならそれに::GetWindow()を組み合わせる
ソース1とソース2のコストは同じでしょうか? CPUのコストはわかりませんが、少なくともメモリの使用量は同じに見えますが、どうでしょうか? 1: //ソース1 2: for(int i=0; i<10; i++){ 3: for(int j=0; j<10; j++){ 4: static const float x = 10; 5: //処理省略 6: } 7: } 8: //ソース2 9: static const float x = 10; 10: for(int i=0; i<10; i++){ 11: for(int j=0; j<10; j++){ 12: //処理省略 13: } 14: }
>>671 コンパイラと環境によって違いますとしか言えない
最適化が優れたコンパイラなら float x そのものを消去してしまうと思う
使用していない変数は消去ってやつですね。 処理省略の部分でxは使っている事とします。 変数は静的な領域に確保するわけですから、どのコンパイラでもメモリの使用量はかわらないように見えるんですが、違うのでしょうか?
>>673 そうとも言えない
とにかくコンパイラの吐いたコードを見るしか確かめる手はない
>>671 横から、付け加えるなら、省略された部分の処理内容も影響する。
場合によっちゃあ処理フローまでガラッと変わる。
あ、xは使ってるのか それなら変わらないだろうという予測が立つ しかしあくまでも予測だという事を忘れないように
>>673 言語仕様では、静的変数の振舞は定義されていても、実装方法までは定義されていないので、
本当に静的な領域に確保されるかどうかは、コンパイラの出力したコードを見ないとわからない。
もっとも、一度確認したからといって、次にコンパイルしたときは違う結果になっているかもしれない。
x86/x64のVCやgccなら、たぶん即値として命令コードに埋め込まれちゃう。 あくまで予測ですがね。
679 :
671 :2009/11/11(水) 18:25:50
私のレベルからしてコンパイラが吐いたコードを解析するのは無理です。 コストに関しては曖昧な感じですし for文の中に書くと気持ち悪いので、forの中でしか使わない定数でも外だししときます。 ありがとうございました。
for(int i = 0, const float x = 10; i < 10; ++i) つーか80:20の(ry
>>679 >for文の中に書くと気持ち悪いので、forの中でしか使わない定数でも外だししときます。
そりゃ逆だ。
「スコープはなるべく小さく」といわれている。
L2キャッシュが良く効くからな
じゃなかった、バグが減るからか C++はスマポがあるからいいんだが
嘘みたいな話だが、昔の gcc だとスコープ狭い方が良 いコードが出た(龍本レベルでもあり得ないと思うんだ が…)。 しかしまぁ、人間にとってもスコープ狭い方が読むとき に気にすべき情報が減るので読み易い。
{ const int c = 10; for(int j = 0; ・・・ } でもこれってちょっとダサくない? インデント深くなるし
慣れればスコープ無視したコードの方がダサイと思うようになるさ
コピーコンストラクタとoperator=()の内容って同じことが多いのですが、 コピーコンストラクタには「*this = コピー元;」とだけ書いて operator=()のほうに処理を集約してしまうことって、なにかまずいことはありますか?
俺もよく使うな、自動変数の生存範囲を限定するためだけのスコープ。
場合によってはバグの元になる ならなくてもメンバ変数が全部初期化された後 すぐに代入することになるから無駄な処理が発生する
>>687 コピーコンストラクタと代入演算子で2つも似たような処理を書きたくないのなら、
逆にコピーコンストラクタ(とswap)を使ってoperator =を実装するほうがおすすめ。こんな感じ。
class Hoge
{
Hoge(const Hoge&); //コピーコンストラクタ
void swap(Hoge& other); // *thisとotherの全メンバをswapする
Hoge& operator =(const Hoge& y)
{
Hoge(y).swap(*this);
return *this;
}
};
めちゃくちゃ新しい処理系ならswapの代わりにstd::moveを
(ムーブ代入演算子を定義して)使う方法も使えるけど、ここでは取り上げない。あしからず。
>>690 これ未定義の動作にならない?
class Hoge
{
int i;
public:
Hoge(int ii = 0) : i(ii) {}
Hoge(const Hoge& j) : i(j.i) {} //コピーコンストラクタ
void swap(Hoge& other) { // *thisとotherの全メンバをswapする
Hoge* tmp = new Hoge;
std::memcpy(tmp, this, sizeof(*this)); // undefined behavior
std::memcpy(this, &other, sizeof(*this));
std::memcpy(&other, tmp, sizeof(*this));
}
Hoge& operator=(const Hoge& y) {
Hoge(y).swap(*this);
return *this;
}
void print() const {
std::cout << i << std::endl;
}
};
int main()
{
Hoge a(1);
Hoge b(2);
a = b;
a.print();
b.print();
}
質問です C++において、関数ポインタを使う意義は何があるでしょうか? 言い換えれば、具体的にどのような事をするときに便利なのでしょうか どなたかお願いします・・・
コールバックとか。・・・でもC++だとその多くは仮想関数に取って代わるかな? C++でも使う例というと、関数テーブルかなぁ。 たとえば、ユーザーの入力したコマンドに応じた動作をしたい場合(以下コードは適当)、 typedef int(*Cmd)(T* args); Cmd command = { &CommandA, &CommandB ... }; // 関数テーブル(関数ポインタのリスト) みたいなのを用意した上で、それをこんな風に実行する。 int Execute(int cmd, T* args) { return (command[cmd])(args); } // cmdの値はユーザーの入力次第 もちろん、switch (cmd) { ... } で分岐させてもいいけど、それだと各コマンドに対応する関数を 色々切り替えたい時とかには少々不便だし、コマンドの総数が3桁だったりするとswitch文が長すぎちゃう。 まぁその辺は結局作りたい物次第なわけだけど。 世の中に無数にあるはずの、オリジナルのスクリプト言語(ゲームエンジン用でも何でも)のコードには、 関数テーブルが山ほど出てきそうだなぁ。
最近の OO 学習から入った C++ な人は基底クラスのポ インタ使ってれば無理に関数ポインタ使わなくてもいい 気がする。
クラスのインスタンスのメソッドへのポインタって使えますか?
はい
>>692 Win32を使うと嫌でもコールバックを使う場面に出くわすよ
>>695 使えるけど使わないほうが無難だな。 ->* とか .* とか見たくないよ。
C++的には operator()()がいいかも。
->*は拡張メソッドで使ってしまう
Cです 構造体の初期化でmemsetを使うと問題があると聞きました. ループ文でまわしている場合,毎回初期化する必要があるんですが どうすればいいんでしょうか? ポインタ配列です. typedef struct{
struct Hoge hoge = {0};
702 :
700 :2009/11/12(木) 21:52:57
すいません.途中で送信してしまいました. どうやって初期化すればよろしいのでしょうか?
>>701 ありがとうございます.
実際にはポインタで宣言しているのですが,
Hoge *hoge
hoge = malloc(sizeof(Hoge) * 100);
for(i = 0; i < 100; i++){
hoge[i] = {0};
}
でいいんですかね?
zeromemory使えや
std::fill()使えや
Hoge foo = {0}; for(i = 0; i < 100; i++) hoge[i] = foo;
C++ならmalloc()の戻り値をキャストしないのはエラーなのでは
Hoge の中に微妙なモノが union で詰まってる時は必要 に応じて何種類か用意しておいてコピーすればいいと思 うんだけど、この場合何も考えずに {0} で初期化する と未定義動作だっけ?
HogeがPODじゃない場合はそもそもそういう初期化は出来ない
>>646 規格の 12.5 p5 で、解放されるメモリブロックのサイズが渡されると
定められている。
> When a delete-expression is executed, the selected deallocation function
> shall be called with the address of the block of storage to be reclaimed
> as its first argument and (if the two-parameter style is used) the size
> of the block as its second argument.
かなり古い VC についてはバグとして見つかっていたみたいだけど、
新しいのでも直ってないのかな?
http://ml.tietew.jp/cppll/cppll/thread_articles/5126
結論、そのコードがCで、今後C++に転用する可能性を排除できるのならmemset()でもいいんでない? そうでないなら、>708で。間違っても、一部のロートルの世迷言に釣られてmemcpy(hoge + i, & foo, sizeof(foo))なんてしないように。
>>711 こういうことなんだが。
struct {
union {
void *p;
void (*func)(void);
float f;
double d;
} u;
} s = {0};
>>715 今規格見た。最初のメンバが初期化されるんだな。
unionを{0}で初期化してもいいけど 最初のメンバと違う型で参照したら処理系依存ってことか
EUCで「。」の区切りを見つけるにはどうすればいいですか 文字コードは0xa1 0xa3です。 偶然にaaaa 0xa1、0xa3 bbbb となった場合が判断できないですが。
>>718 探したい対象が文字列のように、EUCエンコードされていることが保証されているなら、
0xa1から遡って0x80以上のコードが偶数個連続していたらその0xa1が1バイト目。
遡るのが嫌なら、先頭から監視するしか。
実行ファイルやDLLに画像など任意のバイナリデータを埋め込むにはどうするればいいんでしょうか? 今考えてるのは、unsigned char配列にデータを読み込んで0xXX, 0xYY, 0xZZ, ・・・のような形式で出力するプログラムを作り コンパイル前に一度実行してdata.datに保存。利用者側は unsigned char data[] = { #include "data.dat" }; と書いて使う。という感じなんですが・・・
>>720 windows限定なら、標準のリソースとして埋め込めばいいのでは。アイコンなど。
>>719 文字化けや不要コードの埋め込みなどが原因と思うけど
いい具合に出来なかった。
724 :
718 :2009/11/13(金) 14:05:36
変換ツール任せでやってみる。wstring型に変換できれば比較は簡単だから。
wchar_tに変換して出来ました。 手間かかるけど、文字化け多発するよりかは良いか。
vs2008なのですがboostのshared_ptrでインテリセンスって使えますか? 試したところ効かなかったのですが using boost::shared_ptr; shared_ptr<Hoge> pHoge = shared_ptr<Hoge>( new Hoge( 3 ) ); pHoge-> ↑で出したい
std::tr1::shared_ptrなら出るよ。
C++の識別子長すぎていらつく スコープ付きの識別子の別名定義ができれば便利なのに
つスコープ内でtypedef
725だけど、「。」の発見は出来たけど、こんどは文字種の特定が困難になったよ。 かな、カナ、漢字など。UTF16らしいが文字コードがよくわからん。 EUC -> UTF16 -> SJIS OR EUCと何度も変換するしかないのか。
>>727 試したけどダメっぽいです。コンパイルは通るんですが
何か根本的な間違いをしてるのかも・・・。
ひとまず諦めます
>>729 それじゃ型限定じゃん
変数や関数の別名を参照や関数ポインタ使わずに楽に短くしたいんだよ
>>731 インテリセンスするための情報収集が狂っちゃうと、そういうことがおきるねー
リビルドや
中間ファイル(.obj や .res .scc .pdb .pch .ilk .idb .ncb .plg .bsc まだあるかも)を完全に消してのビルドで
復活したりするよ。
>>732 C#のusing的なやつ(しかもスコープ限定)が欲しいってことか。
>>714 まぁ俺も sockaddr_in 辺りは memset でクリアしちゃ
うけどさ。
> そのコードがCで、今後C++に転用する可能性を排除で
> きるのならmemset()でもいいんでない?
厳しく言うと
>>715 みたいなのは union を struct に
しても memset はアウトだよな?
>>737 リンク先あっているのか?
A a[10] = {0} で a[0]〜a[9] のすべてが0クリアされるのか?
static なら保障されているが、auto な配列ではダメなのでは?
されるよ ダメくない
>>739 確認しました。
明示的に初期化される、ただし、一部しか明示されていない場合は、残りは 0 で初期化される、これは
auto でも static でも同じとのことですね。
thanks a lot.
>>733 もしやと思ってSP1にアップデートしたらstd::tr1::shared_ptで出来ました!
今までアップデートしてなかったんだなぁ…
sscanfでは、第一引数の文字列の 半角スペースのある領域を""で囲っても、 ひとつの区切りとしてくれないみたいですが、 それができる方法がありましたら教えてください。 sscanf("\"abc de\" 5", "%s%s", s1, s2);
*scanf は糞
parserつかえ
>>746 ありがとうございます。
試してみます。
>>742 "%s"ではなく、"\"[^\"]"を使えばOK!
構造体の配列について質問です 構造体Aを A **a で定義し a[x][y] でメモリを確保して他の関数に引数として渡します その際 test_func(**a) test_func(*a[y]) test_func(a[][y]) で全て同じ定義だと思うのですが全て関数の中で a[i][j]でアクセスできますよね (ただし i <= x && j <= y) 二つ目と三つ目では[y]で定義しているのでアクセス可能かと思いますが 一つ目はどうやって認識しているのですか?
750 :
デフォルトの名無しさん :2009/11/14(土) 07:23:15
unsigned long からfloatに変換した場合、起こりうる問題を教えてください
>>749 アクセスの仕方は一緒でも
渡されるものの内容が違います
>test_func(**a) >test_func(*a[y]) >test_func(a[][y]) >で全て同じ定義だと思うのですが ちがいます
>>753 一つ目と二つ目は違いますが二つ目と三つ目はおなじですよね?
ポインタのポインタとして渡された先頭のアドレスが渡された関数で
アドレスしか渡してないのにその内部構造が定義したように認識されているのはなぜなのでしょうか?
>>754 二番目と三番目で渡している型は
配列を指すポインタであって、ポインタのポインタではありません
>>754 少なくとも2と3はまったく違う
1と2は一緒とみなしてよいときとそうではない場合がある
>>748 ありがとうございます。
試してみます。
CLASS x=y; は xは初期化されず コピーコンストラクタへいくね。 これってたまたま不定値によっては動作がおかしくなりそうだが。 メモリ確保してあるかどうかのフラグの部分でおかしな動作したよ。
>>758 コピーコンストラクタは初期化処理の一種なわけだが。
CLASS の定義がバグってるんじゃね?
CLASS () { flg=0; }やCLASS (int n) { flg=0; }だとflgは確定してるけど コピーコンストラクタは、xが初めて生成されたのか不明で 初期化して良いのかわからないと思ったんです。 コピーコンストラクタは初期化時にしか使われないんですか。 代入と一緒の気がしてました。どちらの場合も対応しないといけない気がしてました。
>>760 コンストラクタはぜんぶ初期化処理。
初期化後のコピーは代入演算子で定義する。
トンクス!
>749 >test_func(**a) >test_func(*a[y]) >test_func(a[][y]) これはプロトタイプ宣言の話? それとも呼び側? それによって話が変わる。 プロトタイプ宣言ならNを正の整数定数として 1)void func(char **a); 2)void func(char *a[]); 3)void func(char a[][N]); 4)void func(char (*a)[N]); 1と2は全く同じ意味。3と4は全く同じ意味。
764 :
763 :2009/11/14(土) 19:15:55
>749 よく読むと A a[x][y]; を渡したいみたいだね。 それならば、>763の3か4を使う。 1,2ではダメ。
765 :
763 :2009/11/14(土) 19:23:23
>749 何度もすまん。 >A **a >で定義し a[x][y] でメモリを確保して他の関数に引数として渡します aの定義がA **aなら1か2で渡す必要があるが、 それと >a[x][y] でメモリを確保して という部分がつながらない。 やりたいことはこれ? A hoge[x][y]; A (*a)[y] = hoge; それともこれ? A **a; int i; a = malloc(sizeof(A*)*x); for (i = 0; i < x; i++) { a[i] = malloc(sizeof(A) * y); }
Visual C++ 2005 の環境でファイルを出力するプログラムを作成していますが、 期待通りに出力が行えません。 fprintf_s関数の第2引数の中で、%sを指定していますが、 文字列ではなく、文字として、「C」だけが出力されているようです。 どのようにすれば、文字列「C:\test」が出力されるのか、お分かりの方がおりましたらご教授いただけませんか? -----プログラム----- CString csvFile = _T("C:\\test"); FILE *fileStream; if(_tfopen_s(&fileStream, (LPCTSTR)csvFile, _T("w")) != 0) { return -1; } fprintf_s(fileStream, "あいうえおABC123\r\n"); // あいうえおABC123 fprintf_s(fileStream, "FILE %s\r\n", csvFile); // FILE C:\test → FILE C -----出力結果----- あいうえおABC123 FILE C -----期待している出力結果----- あいうえおABC123 FILE C:\test ※ファイル名を格納してる変数の型は、他の処理でも使用している都合上、変更できません。
>>766 試してないけど、こうじゃない?
_ftprintf_s(fileStream, _T("FILE %s\r\n"), static_cast<LPCTSTR>(csvFile));
可変長引数に渡す場合にクラスからの暗黙の変換は効かない。
CString 使うなら TCHAR を扱うように統一しないと。
Cスタイルキャストは無しで。
fprintf_sの引数を(LPCSTR)csvFileにしたらどうだろうか
>>767-768 大昔はともかく、いまのCStringはLPCTSTRとして扱ってもかまわないようにできてるから、
この場合問題なのはfprintf_sの"%s"にLPTSTRを渡してることだと思う。
つまりtprintf系の関数を使うのが正しい
>>769 それは間違ってる。むしろ至る所に_Tマクロを使うべき
771 :
766 :2009/11/14(土) 20:09:45
記載いただいた内容で出力することができました。
ありがとうございます。
>>767-770 C言語と比べると全然違うんですね。
Cを少しかじったことがあるので、書けると思っていたら全然でした…。
772 :
766 :2009/11/14(土) 20:14:34
>>770 770さんの書き込みをよくよく読むと出力はできるけど、
これだと正しくないということですか?
ジェネリックテキスト(_Tマクロとか使うやつ)は使わないほうがいいだろ。 95/98対応する必要があるとかかわいそうな人なんてもう、そうそういない だろうし、ワイド文字列きめうちのほうがトラブルがなくて楽だよ。 それにジェネリックテキスト使っていたって、本当にワイド文字列と マルチバイト文字列の両方に対応できてるコード書けてるかってのもあるし。 両方で動くように意識して書いてるやつなんて少数派だし、_UNICODEありと なしでコンパイルが通るかとか、テストを両方でやってるところとかまで いくと壊滅状態だろうし、事実上ジェネリックテキストなんて機能してないよな。
>>770 > 大昔はともかく、いまのCStringはLPCTSTRとして扱ってもかまわないようにできてるから、
へー。いまの可変長引数の ... 部分に渡したときも LPCTSTR への暗黙変換が入るのかー。
いったいどういう仕組みで?
クラスに operator LPCTSTR () を持ってるだけじゃ、そうはいかないよね?
>>773 一般的な話ならそれでもいいんだけど、ここでは CString を使ってて、
その型は変えられないと質問者が言ってるんだから _T() が要るだろ。
>>774 >>770 じゃないけどCSimpleStringT<>のソースは大分前に見たよ
データメンバがポインタ1個でvtblもないから
メモリレイアウトがTCHAR*と同じになってるんだよ確か
777 :
768 :2009/11/14(土) 20:29:40
よく考えたらLPCSTRへ変換はできなかったかも CStringへ代入はできるけど
778 :
766 :2009/11/14(土) 20:31:31
ごめんなさい。 出力はできるようにはなったのですが、日本語が含んでいるとクエスチョンマークの 文字列が並んでしまいます。 これはやっぱり、上で説明されている変換がうまくいっていないからですか?
>>778 setlocale(LC_CTYPE, "");
とかやろう!
>>780 #include <cstdio>
#include <atlstr.h>
int main()
{
CStringA s = "world";
std::printf("hello, %s\n", s);
}
うちではこのコードはVC7.1でもVC9でも動くよ
まあ推奨はしないってか誰もしてないと思うけど
>>780 古いATLの利用を考えているならキャストするのが安全だろうけど、
最近のはreinterpret_cast相当の操作でも安全に使えるようにできているから必要はない。
というのはATLの解説書のどれかに書いてあったはず
783 :
766 :2009/11/14(土) 20:44:59
>>779 無事に出力できました。ありがとうございます。
第2引数に何か入れた方が良いのかと思いましたら、そのままでも平気なんですね。
784 :
781 :2009/11/14(土) 20:52:17
どーでもいいけど例が良くなかったね #include <cstdio> #include <atlstr.h> int main() { CStringA s = "world"; std::printf("hello, %s %d\n", s, 123); } これがちゃんと動きます。
785 :
774 :2009/11/14(土) 21:08:10
C++でポインタを *で参照はがしした時って、*pointerは参照ということになるの?
http://codepad.org/A8sFOqoG こんな感じで仮想関数使いたい場合、とりあえず思った通りに動くんだけど、
*baseとした時点でBase型に補足されるということはないんですか。
わかりました。ありがとうございます。
char 配列が300個連続で0であることを高速で見つけるにはどうすればいいですか。
どういう意味で高速なんだ
CPUの性能を上げれば高速になるよ
ひとつひとつ探すより、memcmp使うとかです。 これは実際に速くなるのですが、500個になると困ります。
0に限定すれば、memcmpより高速に出来る可能性があると思いますが アセンブラなどわかりません。
O(n)よりは速くならないんだから、あとはCPUのデータシート眺めながらチューンしていくしかないよ
いい方法わかりました。300個目だけ1だったら途中は調べなくて良かったです。
ああもうそれでいいよ、もう来ないでね
>>795 もう少しマシにしようか
300個が0なら150個目を調べる
それも0なら75個目と225個目を調べる
それも0なら・・・・
非0である確率が高いならともかく、そうでないなら最初から順々に調べたほうがマシだな
データに偏りがあるなら、そういう最適化もあるが、ないなら最初から配列舐めるなぁ。。。
つまらないこと言ってないで、死の行進しとけよ 学生はIT土方になるために必死に勉強しとけ
> これは実際に速くなるのですが、500個になると困ります なんで? そもそも memcmp() 呼び出しが 単純なループ処理より速いってどんな環境? (つーか、まさか毎回if判定してないよな?)
>801 いや普通、ループは毎回判定してるぞw
例えば ・charではなく、もっと大きな(intとか)のサイズでアクセスし ・毎回判定するのではなく、数十個単位とかを|してから判定することにして ・さらに、場合によってはプリフェッチ的なアクセスの仕方も行う というようなことをすれば、 ・もしかしたら ・あなたの使っているCPUやOS、及びコンパイラと使用ライブラリ限定で ・データによっては ・気休め程度には 速くなる可能性はあるかもね。
804 :
デフォルトの名無しさん :2009/11/16(月) 11:02:47
バーチャルで関数をオーバーライドするときって型を変えたりできないんですか? virtual ってvoidばっかりなのですが
>>804 基本的にはできない。
例外として共変戻り値がある。
グローバル変数はどこから書き換えられるか解らないといった弊害があるから推奨されないかと思うのですが グローバルな定数であれば別にガツガツ使用しても問題ないのでしょうか?
一番大事なことはそれではないとおもう。 変数がかぶることと思う。 ネームスペースやオブジェクト指向も 変数名、関数名がかぶらなくなることが大事思う。
変数や関数の生存範囲が小さいほどよい。 公開する部分はのぞく。 グローバル定数も変数も公開するで無ければなるべく範囲を縮める。
変数を生成するコストを減らすためとかいう理由で グローバル使うのはあほですよ。 大して時間食わないし、変数生成がボトルネックなることはまれ。 時間食ってることが確認できてから変えれば良いんです。 なるべく生存範囲が短くなるようにするのが吉
じゃネームスペースの中にグローバル変数入れときゃいいじゃん
名前の競合なんて屁でもないだろ。 モジュール間でのカプセル化という意味合いの方が大きい。
813 :
806 :2009/11/16(月) 17:29:33
グローバル定数も出来る限り控える方が良いんですね。 ありがとうございます。
814 :
デフォルトの名無しさん :2009/11/16(月) 18:25:46
error C2276: '&' : 仮想関数のアドレスを取ろうとしました。 とか、書き方を変えると、 error C2440: '<function-style-cast>' : 'overloaded-function' から 'float' に変換できません。 とか出ます、仮想関数をはじめていじくっているのでどうすれば良いかわかりません 仮想関数のオーバーライド中では引数のメンバの型を変えてはいけないのですか?
グローバルスコープがふさわしい物までグローバルから追い出そうとするのも問題だと 個人的には思う つーか、初心者が一番やらかしやすいのは、関数スコープがふさわしい物をファイル スコープに出してしまうことじゃないかと
817 :
デフォルトの名無しさん :2009/11/16(月) 22:23:03
vc++でトランプゲームとか作ろうと思っています。そこで質問が二つあります。 @画像データをPROJECT内に保管しておいて必要な部分を切り取って表示する方法ってありますか? AWIN32とmfcとで方法が違うかもしれませんが、ゲームを作成するのに向いているのはどっちでしょうか? ※開発環境(といえるほどのレベルではないのですが・・・)VISUALSTUDIO2005でvista32bitです。 入門書とかも何冊か読んでみたのですが、自分が求めている情報がズバリ載っているわけではいないので、 質問させていただきました。詳しい方がいらしたらぜひアドバイス願います。
>>817 1、ビットマップの管理方法で違う。APIに任せるなら、loadImageしてBitBltなどのAPIを使う。
自前で管理するなら、配列いじるのと変わらない。が、約束事はある。
2、どっちでも作れるから、作りやすいほう選べ。CかC++か位の違いしかない。どっちにもお約束事はある。
環境変数はグローバル変数だから使用禁止 外部からファイル読み込むのもグローバル変数だから使用禁止
#define HOGE 1 #define HOGE 1 #define HOGE 1 #define HOGE 2 #define HOGE 1 #define HOGE 1 同じ名前の定数を何度も宣言した場合、値が同じうちは何も言われず、 上の場合は1→2と2→1のところでのみ警告が発生するのですが、 これはCやC++の標準の仕様として頼ってしまってもよいものですか? Win32のDLLからエクスポートするクラス群が複数のヘッダに分散していて、 各ヘッダにそれぞれ #ifdef HOGE_EXPORTS #define HOGE_API __declspec(dllexport) #else #define HOGE_API __declspec(dllimport) #endif を入れてしまいたいのです。 それとも、上のものだけが書かれた二重インクルード対策付きヘッダも別に用意して、 各クラスのヘッダからちゃんとインクルードするべきですか?
>>820 #ifndef HOGE_API
#ifdef HOGE_EXPORTS
#define HOGE_API __declspec(dllexport)
#else
#define HOGE_API __declspec(dllimport)
#endif
#endif
>>820 同じ名前で内容の全く同じマクロなら何度定義してもいいことになってる。
(厳密にはもう少し複雑な規定があるけど)
>>821-822 何度定義してもよいということが仕様として存在するのですね。
安心しました。ありがとうございます。
824 :
デフォルトの名無しさん :2009/11/16(月) 23:49:24
名前: デフォルトの名無しさん E-mail: 内容: 818さんアドバイスありがとうございます。さっそく、プログラムに入力しビルドしてみました。私の力量不足でエラーになってしまいましたが、 loadImage()をいかに使いこなせるかというところが質問の答えのようですね。 A:秀和システムの本:「VisualC++.net逆引き大全」 B:秀和システムの本:「C言語逆引き大全」をぱらぱらとめくってみました。 AのほうにはMFCのところにLoadBitmapを使った方法が載っており、BのほうにはLoadImage()を使う方法が載っていました。 Aのほう CBitmap m_hBitmap; if (m_hBitmap.LoadBitmap(CARD)){ } pDC->DrawState( CPoint(0,0), CSize(100,100), &m_hBitmap; DST_BITMAP); Bのほう HANDLE LoadImage( HINSTANCE hinst,//インスタンスのハンドル LPCTSTR CARD,//イメージの名前または識別子 IMAGE_BITMAP,//イメージのタイプ 100,//希望する幅 100,//希望する高さ LR_DEFAULT //ロードのオプション ); という風なことが書いてあるのですが、Aのほうは、構文エラー )や;があるとかないとか。 Bのほうは、LR_DEFAULTが認識されない識別子だとか、 )や;があるとかないとか。 のエラーが出でしまいます。 これはなぜエラーになってしまうのでしょうか? 理由が分かる方、ぜひアドバイスをお願いいたします。※CARD.bmpという画像ファイルを扱おうとしています。
825 :
デフォルトの名無しさん :2009/11/16(月) 23:54:46
デバッグしてるときに変数に何が入ってるか知りたいのですが_CrtSetBreakAlloc(1162);これしかないですか?
827 :
デフォルトの名無しさん :2009/11/16(月) 23:59:30
>>826 効果的な使い方がわからん
_CrtSetBreakAlloc(1162);で止めて下に出てるツリーを開いていくやり方以外やったことない
教えて
>>827 _CrtSetBreakAlloc()って知らんからググってみたら、メモリリークの箇所を
調べるみたいなことが書いてあった。
勉強になるなぁ。
変数の中身をみるって、適当にブレイクポイントでとめて、ウオッチで見るとかじゃなくて?
829 :
デフォルトの名無しさん :2009/11/17(火) 00:10:22
おkサンクス、やってみる
830 :
デフォルトの名無しさん :2009/11/17(火) 00:13:03
ああ、普通こうやってやるのか すげえな、サンクス
VCならウォッチ式の設定とか言わず、変数をポイントするだけでもおk。
832 :
デフォルトの名無しさん :2009/11/17(火) 06:05:27
ちょwwVC便利すぎワロタw プログラム暦2年だけど何やってたんだ俺wめっちゃ簡単に割り出せるやんw
vectorの内部で確保されているメモリってclear()でも解放されるの?
解放されない swapですれよ
835 :
833 :2009/11/17(火) 06:47:54
なるほど、どうも
std::vector<T> v のバッファサイズをバイト単位で取得したい時は、 v.size() * sizeof(T) でいいんでしょうか? 実装によっては何か詰め物でも入っているのではないかと不安なんですが。
vectorのバッファは配列と同じメモリ配置であることが保証されてるから、それでいいよ
>>836 そのサイズを使った操作が何であるかによっては危険な予感がする。
普通に書き込めばいいじゃん
>>839 ostreamのシフト演算子を定義すればいいと思うよ。
v.size() * sizeof(T) だと、vtableがあったら色々まずい。
バッファサイズに仮想関数テーブルは関係ないだろ
copy(v.begin(), v.end(), ostream_iterator<T>(cout, "\t"); これってさ、Tによっては<<定義しても動作しなくね?
>>844 いやそういう下らん揚げ足取りはいいから
>>843 動作しそうで動作しない T の例をひとつでも挙げてみてくれ。
そうじゃないと、当たり前のことを聞かれてるだけにしか見えん。
メモリイメージをメモリマップトファイルにmemcpyすれば楽ちん。 ていう考えは古いですか。
質問させてください。 静的メンバはクラスが存在する前からあるはずなのに、なんでクラスの外で再宣言しなくてはならないんですか?
ヘッダファイルにクラス定義を書いた場合ということでいいのかな? その場合、各翻訳単位の間で重複してクラスの静的変数を定義しない為。 ヘッダファイルにグローバル変数を書いて共有するときも、externで宣言しといてどこかで一度だけ実体の宣言をするよね。
http://codepad.org/auJS2ura ngの部分でコンパイルエラーが出てしまいます
VC++2008EEのエラーメッセージによると引数があいまいだから、ということなんですが
どうすれば曖昧さをなくせるのかちょっとわかりません
うまいことstd::endlを渡す方法はありませんか?
CParent ◇- CChild というように親クラスが子クラスを保持しているとします。 子クラスはプログラム動作中、たくさんnewでメモリを確保します。 プログラム終了時、CChild内でdeleteせず、CParentでだけdeleteすれば、 CChildがそれまで確保してきた領域も伴ってdeleteされるのでしょうか? というのも、ある書籍についてたサンプルコードを見ると、newしまくりなのに、 それらがdeleteされる記述がぜんぜんないんです・・・ 最も最上位のクラス(他の下位クラスを保持している)を最後にdeleteしてるところ くらいしか考えられない・・・ よろしくお願いします。 m(_ _)m
メモリリークしちゃうね とりあえずその書籍の名前を
スマートポインタ使ってたらそう見えるかもしれない
855 :
852 :2009/11/18(水) 22:01:00
>>853 「3D格闘ゲームプログラミング」という本です。
不思議なことに、サンプルのVC++プログクトでビルド実行してプログラムを終了させたとき、
リークがある場合にVC++のログ出力に出てくるメモリリークバイト数が出て来ず、
正常終了できたかに見えます・・・
>>854 スマートポインタを使っているようにも見えません・・・
一例として
ヘッダファイル内
char* xxx
C++ファイル内
xxx = new char[ strlen( yyy ) + 1 ];
で、xxxはどこでもdeleteされていません。
VC++上でソリューション内を検索もしましたが見つかりませんでした・・・
別の変数に代入されてどっかで解放されてるんじゃないの
857 :
852 :2009/11/18(水) 22:21:50
>>856 追跡してみましたが、見当たらず・・・
そういえば、newされたやつの多くはSTLのvectorにpush_back()されています。
ヘッダーファイル内
#include <vector>
using namespace std;
vector<CChild*> Child;
C++ファイル内
Child.push_back( new CChild() );
何か関係があるのでしょうか?
このvectorはポインタのコンテナになっていて、やはりどこかでそれらのポインタの先にある
実体領域を解放してやる必要がありますよね?
そういわれても実際にコードを見られないんじゃ何とも答えられん。
Childが死ぬときに開放してるんだろ。 とりあえずステップ実行して、本当に開放されないのか一行ずつ確認してください。
>>848 クラスの外に書くのは、宣言ではなく定義。
861 :
852 :2009/11/18(水) 23:01:49
なんか苦しい言い訳に見えるな。百歩譲ってそれが「正しい」方法だとして、 プログラミングを勉強する本にそういう書き方をするのはいかがなものだろうか…
質問を勝手に自分の理解できる範囲の問題に解釈し直すのはいくない
>>861 そんなこと言ってると、ごちゃごちゃ言ってないで std::vector 使えカス、ってバカにされちゃうよ。
VC6 時代の古い本ならしょうがないか、と思ったけどそのリンク先 Q&A の 日付見たらごく最近なのな。著者が不勉強なんだろうと思う。
866 :
852 :2009/11/19(木) 00:57:36
>>864 多態を使わなければ、クラスのインスタンスのvectorを使ってもOKみたいですね。
vector<CXXX> xxx;
CXXX x;
xxx.push_back( x ); // xxxコンテナへのコピーになる
これだったら、領域確保はvectorがしてくれるので楽ちんですね。
これでいきます。
ありがとうございました。
コンストラクタ初期化子を使わないと駄目だっていうけど、初期化の順番を明示したい場合はコンストラクタ関数内で初期化してもいいよね?俺悪くないよね?
どうでもいい。
>>867 IDE のインテリジェンス機能が動かなくてもいいならそれでもいいよ
コンパイル時にクラスや構造体のメンバのオフセットアドレスを得る方法ってあります?
offsetof
>>861 それはメモリリークそのものだろw
そんなレベルで本書くなよ…
よく読んでないけど 説明は下手糞だけど、最初に確保したメモリをプールしておいて使いまわす手法じゃないの? だとしたら、そういうのはリークとは呼ばないよ。 MoreEffectiveC++にもちゃんと書いてあるし。 違ったらごめんな。
×使いまわす手法 ○使いまわして、最後まで(プログラムのコード内では)解放しない手法
メモリなら最悪リークしてても、プロセス終了時に解放されますよって話だろ? まぁメモリ以外のリソースだと解放してくれなかったりすることもあるけど。
だから、たとえ解放処理(free/delete)をしていないとしても ちゃんと管理できているものは「リーク」とは呼ばないって話だよ。
>>867 初期化の順番はメンバの宣言順と決まっている。
コンストラクタの記述方法で明示などできない。
無知なオマエ悪い。
最後にOS任せで消滅させて、途中どんなに肥大してもシラネ、ってのは管理ではなく リークと呼ぶだろw
>>879 だから、
>タスク用メモリはプログラムの終了時まで解放しない
が、「deleteを呼ばない」という意味ではなく
「プログラム終了まで使用している領域である」という意味ではないか、と言っている。
使用している(管理している)領域なんだから、deleteするコードが無くても問題ない。
もちろん、その「タスク」が、プログラムの中で際限なく増えていく
(あるいそのタスクを指す領域を見失っている)ようなら問題だが
俺はコードを読んでないので、どういう構造なのかは明言できない。
だから、「よく読んでないが」「説明は下手糞」と書いた。
そして、(明示的にdeleteを呼んで無くても)管理下にあるものはリークとは呼ばない。これは確実。
で、使いまわしているかどうかは問題の本質じゃない。 管理下にあるかどうかが本質。
>>881-882 よく読んでみなよ。
>>861 のやつは管理下にすらない。
「タスク」じゃなくて char 配列のほうな。ローカルな生ポインタ変数に入れて、
そのままスコープアウトしちゃってるみたい。
当たり前の主張を長文で繰り返す前に、「よく読んでない」と自分でわかってる
なら元記事をよく読めと。
このサンプルでは以下の理由から、new char[]で確保した領域を明示的に解放する処理を省略しています。同様の理由で、他にもメモリの破棄を省略している部分があります。 * サンプルプログラムをなるべくシンプルにしたい * タスク用メモリはプログラムの終了時まで解放しない * プログラム終了時にはOSがプログラムに関連するメモリを解放してくれる * 一般にdeleteで解放したメモリはOSには返却されず、プログラムの内部に保持されたままとなるため、タスクリストの場合は実行中に解放する意味が薄い 上記の理由から、メモリを解放しなくても動作に問題はなく、他のプログラムへの影響もありません。推奨される方法としては、例えばタスクリストのデストラクタ ~CTaskList() を記述して、その中で上記のバッファを、 delete [] buf; のように解放します。この場合、bufをメンバ変数にしておく必要もあります。
「禁無断転載」と明記された記事を意味もなく転載するのはおすすめしない。 せめて引用の形にとどめておけ。
っていうか、いかなる場合でも 確保したメモリちゃんと解放すればいいんだよ。 メモリを解放するデメリットなんてないだろ? もし、終了時に遅くなるとかいう話なら 「終了処理を速くするテクニック」として使えばいいだけの話。 それが必要になるときがくれば使え
>deleteで解放したメモリはOSには返却されず、プログラムの内部に保持されたままとなるため、 再利用されるとか考えないのかね?
その機構部分は仮に良い という立場だったとして new と delete がペアになっていない構造だから 別コードで本当にリークさせてる部分の追跡をするのに面倒じゃね?
deleteしてもメモリ返せないの?なんで?じゃあどうすんの?
どうもしない
なんで、サンプルで手抜きをするのかねぇ? deleteなんて一行増えるだけじゃん。 いちいち言い訳を書くよりも deleteを書けばいいじゃんか。
deleteしてもメモリ返せないの?なんで?じゃあどうすんの?
どうもしない newしたときに再利用されるだろうな
サンプルをシンプルにしたいからって理由で無茶すんなよなぁw リーク検出とか使えなくなりそうだしなぁ
897 :
852 :2009/11/19(木) 19:05:22
物議を醸していますね^^; 作者の方は東大を出ておられますが、地頭が良いとこういう考え方になるのでしょうか・・・ ともあれ、今はnew、deleteはセットで書くよう心がけたいですね。
deleteするしないはコードの本質でないと判断したんだろう。 まぁ論文ならそれでいいんだろうが、一般向け、しかも初心者が食いつきやすいゲームプログラミングの書籍で それをやると何も考えずに模倣する馬鹿が出てきてしまうから、やめた方がいいと思うがな。
メモリリークしてたらだめだ 実測しむ
1Mのメモリーリークが100回起これば100M消費する プログラムが終了すればOSが回収するが、 動いている間はそのまま。
東大出てても糞コード書く奴はどうしようもないよ しかも学歴が高いせいで自信だけはあるから逆にめんどい
Cなら終了時まで解放しないメモリをfreeしないっていう層は結構いるから その亜流なんだろう
>>897 もちろんnew/deleteをセットで書いてもいいが
それよりスマートポインタを使うんだ
904 :
852 :2009/11/19(木) 23:01:20
>>903 COMでCComPtrを使ったことがあって、めちゃくちゃ便利でした。
自前のを作るとなると・・・うまく組めるかちょっと心配です(汗)
でも便利なのはたしかなので、勉強してみます。
ありがとうございます。
shared_ptr < ・・・
BCB5+Win環境です char配列などを頻繁にnew・deleatする際、どっかのサイトで win環境では固定サイズでnewしたほうが断片化しにくいと 書いてあったような気がするのですか 本当でしょうか? あまりnewをいじりたくないので気になります
907 :
852 :2009/11/19(木) 23:45:36
>>905 おおお!
こんな便利なものがあったのですか!
VC++2008ならstd::で使えるそうですが、自分は2005ですね・・・
しかし、boostを導入すれば使えますね。
CComPtrと同じように使えるのであれば、慣れていますし、導入もし易そうです。
教えてくださって、ありがとうございました!
std::multimap<int, int> test; test[0] = 1 test[0] = 2 test[0] = 3 ...いろいろ代入... としたときに、 std::multimap<int, int>::iteartor begin = test.lower_bound(0); std::multimap<int, int>::iteartor end = test.lower_bound(0); std::multimap<int, int>::iteartor it; for (it=begin; it!=end; ++it) printf("%d", it->second); で得られる結果は必ず 1, 2, 3 の順番になると保障されていますか?
std::multimap<int, int>::iteartor end = test.upper_bound(0); でしたすみません
されてません。
>>906 new の回数を減らせば断片が減る(断片化しにくい)のはあたりまえ。
それ以前に、ほんとうに断片化による悪影響で困ってるのか?
Windows 上では、特にギガバイト単位のメモリ空間(アドレス空間)があたりまえな
最近の一般的な環境ではかなり稀なケースになると思うんだが。
>>901 実際に動作させるコードでdeleteするしないの問題と、解説書でdeleteを省略するしないの問題を
区別できていないお前は多分低学歴なんだろうな
実際に動作させるコードからかけ離れたコードを提示する解説書がそもそも問題 削っていい部分とそうでない部分があるが、こういうのを削っていいと思うようなら 糞コードと言われても仕方ない
ま、万人向けの本でやっちゃだめだよな。
ぶっちゃけこんなアホなコードを本気で擁護する奴なんて本人以外いるの?w
>>912 省略したほうがシンプルでいいと思ったけど結局は言い訳がましい Q&A を書くハメに
なったってことで、解説書のための判断としても失敗だろ。
紙面の問題を考えても、 std::vector 使っとけば #include が1行増えるかもしれないって
程度だし。
まぁ、全てを綺麗に書くことが正義という言語でもないし、本当に必要ならば手を汚す
こともあるけどな。
>>884 は手を染める理由としては全く不足だと思うが。
とりあえず買っちゃいけない類の本ではあるな。良い初心者は混乱し、悪い初心者は
汚れる。中級者以上なら他に投資すべき本があるだろう。
確保したハンドルやリソースを開放しないままプログラムが終了しても 言語やOSの仕様でプログラム終了時に確実に回収することがわかっていて かつ、リークしないこともわかっているなら、別に開放しないまま終わってもいいじゃないか。^^ たとえば、 int main() { int* i = new int; } 上のプログラムはメモリリークしていない。 なぜなら、ポインタが消失して削除不能になるのはプログラムが終了する瞬間であり その直後にはすべてのリソースが回収されることが仕様で決まっているからだ^−^ 美学とかいうなら別だが。
classのお作法を守ってないからでしょ。後で書いた方?は直してるみたいだし
あえてdeleteしない、なんて初心者向け解説本でやるべきじゃないよな。 「3D格闘ゲーム」ってことだから、おそらくキャラクタ2体分のオブジェクトを作って プログラム終了まで開放しない、みたいなコードだと思うんだけど、 読者がそこから拡張していこうとした途端にメモリリークを起こす気がする。
繰り返しのnewがでたらやばいんだって。
922 :
852 :2009/11/20(金) 08:12:39
この本はdelete問題の他にも、ちょっと「?」というか、もっと効率的な方法があるのでは?と 思ってしまうようなところもあるのですが、 アニメーション付Xファイルの読み込み、およびそれをゲーム中でアニメーションさせるところの 解説はものすごく参考になっています。 今までいくつかのWebサイトでそれを解説しているところも見てきましたが、 この本の内容が一番分かり易かったです。 アニメーションのための本質的なところ(動作、仕様レベル)だけ抽出して、 実装に向けたクラス設計や仕様は自分で改めて考えてからコーディングしていったら良いと思いました。
分かりやすいように見えても、どこに罠が仕込まれてるか分からんのではなぁ
糞コードを本にして売るほうも、本に書いてあるコードを吟味せずにそのまま使うほうもアホ
Amazonレビューを見たら、そのアニメーションの解説も参考にするとまずそうな 雰囲気に見えるが… まぁ、買っちまったら何とか活用したいんだろうけどなぁ… つーかサンプルプログラムの作り方もひどそうだ ゲームがコマンドライン引数でviewerに変わるらしいが、やってみたくてやっちゃった のかな、使い勝手とか全然考えずにw もちろん「コマンドラインの処理サンプルを入れたかったので」とか言い訳はいくら でも思いつくが
DLLとEXEでは使ってるアドレス空間が違うとのことなんですがポインタがどっちのアドレス空間に属しているかしらべる方法はありますか?
>>918 そういう特殊な事例でしか当てはまらないものは
特殊な例としてあげればいいんだよ。
int foo() {
int* i = new int;
}
関数名を変えただけで、この処理はリークしているかもしれない。
int main() {
MyClass* i = new MyClass;
}
クラス名を変えただけだが、delete時にファイル削除とかしているかもしれない。
な? コードは修正されるもの。
そういうときに自分で罠を仕掛けてどうする。
連続稼働させるものや、多くメモリ確保する物では メモリリークは致命的。 512K確保する関数を200回呼び出せば、合計で1ギガ消費する。 deleteしないでこれを放置するやつは超初心者
ブラウザはよくリークする
>>918 それはメモリリークだよ。
もう使わないからdeleteしていいのにdeleteしないままプロセス終了を迎えたら、それはメモリリーク。
「プロセス終了時に把握できているメモリリークがあっても特に問題無い」には反論しないけど、
「リークじゃない」はおかしい。
そのプログラムがメモリリークしてないなら、メモリリークしてるプログラムなんてこの世に無いよ。
目立ってメモリリークしなければ無視でも良いけどね。 たとえば、4バイトのメモリリークで128M=2^24バイトたまるには、 400万回やらないといけない。 10秒に一回起こったとしても、400万回するには一年半ほどかかる。、
まぁ、習慣的にリーク対策しないと、大事なとき忘れるし、コードの再利用したときも不具合を生みやすい。 俺は基本的にnewしないでスタックに確保するから、そういう問題はほとんどないな。 はやくスマートポインタが使いたいぜ。
vcでメモリリーク検出できるからそれでいいよ。 わずかに残ったとしても致命的にはなりにくい。 なったら変更すればいいし。
シングルトンな奴は基本 delete しねぇなぁ、俺は。
new deleteはコンパイラ依存していますか? 別のコンパイラで確保したメモリを、VCでdeleteは出来ませんか?
>>936 別のコンパイラどころか、同じコンパイラでも異なるDLLでnewしたオブジェクトをdeleteすることは
原則としてできません。(MFCの拡張DLLは別)
new deleteはオーバーロードだってできるからな。 あえてやるひとはいないだろうけど、 自分以外誰にも使えないnewの実装だってありえる。
そうだったんですか。 そうだとすると、DLLがメモリ確保してリターンしたら解放不可能になるんですか。
んなこたーない メモリを確保する関数 と 確保したメモリを開放する関数 を用意しときゃよい fopen() と fclose() の関係
DLL が提供しているのが newしたポインタを戻すだけで
その後始末の delete は呼び出し側がやってね という造りはマズイ ってこと
DLL は 自前newしたものを戻すつもりなら それを受けて delete する部分も提供すべき
# で、後者を記述するのに安全を見て
>>926 で保険かけたいんだけど… どうすれば良い?
# という流れになるのかな?
Windows APIだとCreateなんたらでハンドル作ったら、 CloseHandleよびだしたりするね。
----DLL---- typedef void *(*dll_alloc_t)(void *(*)(size_t), size_t); __declspec(dllexport) void *dll_alloc(void *(*)(size_t), size_t); void *dll_alloc(void *(*alloc)(size_t), size_t s) { return alloc(s); } ----EXE---- dll_alloc_t dll_alloc = (dll_alloc_t)GetProcAddres(hDLL, "dll_alloc"); void *p = dll_alloc(malloc, size); こうした場合メモリはどっちに確保されるの?
内部実装に詳しいわけじゃないから適当にいうけど、 EXEから呼ばれるDLLがリンクしているalloc関数を実装しているライブラリ・・・が OSにメモリ割り当てを要求して、OSが返してくれる適当なメモリ領域・・・・の 一部分をallocが適当に調節して返すんだから、 どっかOSが適当に決めた場所なんじゃないの?
VC++だとこうなったが・・・ //DLL.c #include <stddef.h> __declspec(dllexport) void *dll_alloc(void *(*alloc)(size_t), size_t size) { return alloc(size); } //Main.c #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <string.h> typedef void *(*dll_alloc_t)(void *(*)(size_t), size_t); int main(void) { HINSTANCE hDLL = LoadLibrary("DLL"); dll_alloc_t dll_alloc = (dll_alloc_t)GetProcAddress(hDLL, "dll_alloc"); char *p = (char *)dll_alloc(malloc, 10); strcpy(p, "hello!"); puts(p); FreeLibrary(hDLL); puts(p); free(p); puts(p); return 0; } //OUT hello! hello! ンンンンンンンンンンンンンンンン-
これで良いみたいだな。winapi使った // DLL #include <windows.h> #include <stdio.h> extern "C" WINAPI void memo( HANDLE hd, char *&p ) { p = (char*) HeapAlloc(hd, HEAP_ZERO_MEMORY, 1<<20); strcpy(p,"hgujyguyguyguyguby"); printf("%s\n",p); } // EXE #include <windows.h> #include <stdio.h> typedef void (WINAPI *FNC)(HANDLE , char*& ); int main(){ HINSTANCE hd= LoadLibrary("dll.dll"); FNC memo = (FNC)GetProcAddress(hd, "memo"); HANDLE hHeap = HeapCreate(NULL, 0, 0); char *p; memo(hHeap, p); printf("%s\n",p); HeapFree(hHeap, NULL, p); HeapDestroy(hHeap); getchar(); }
C言語でWin32APIをさわっています。winbase.hに WINBASEAPI VOID WINAPI OutputDebugStringA(__in LPCSTR lpOutputString); と書いてあったんですが__inって何ですか?
DLLとメモリのやりとりを確実にするには、(HANDLE, char*)のペアで 扱うのが良いと思いますが、 一方ではペアとして、一方ではchar*と自動的にキャストさせる方法はありますか。
>>948 縛りの弱いconstのようなものでしょうか?
SAL解釈と言うんですね
ググったんですがなかなかそこまでたどり着けませんでした
951 :
949 :2009/11/20(金) 18:43:43
自作関数だと、ペアでもchar*でも受け入れるように出来ますけど 自作ではない関数に対しても、自動でキャストして通るように出来れば便利なんですが。
何でもかんでも暗黙キャストしてると後ですごい不安になる
953 :
950 :2009/11/20(金) 18:46:57
>SAL解釈と言うんですね SAL注釈ですね、間違えました
double - int みたいな暗黙キャストを実現する方法はないですか?
>>949 ごめん、なんでハンドルが出て来るのか分からない。
>>946 の
HANDLE hHeap = HeapCreate(NULL, 0, 0); と char *p; のペアを
char*型のように扱いたいって事なんです。
無理でしょうか?
std::vector< boost::shared_ptr< T > > と boost::ptr_vector< T > はどちらを使っても同じでしょうか? 「一方ではこれができないから注意!」とかあったら教えてください m(_ _)m
猿介錯
よくわからないならvector<shared_ptr<T>>のほう使っとけ
960 :
957 :2009/11/20(金) 20:33:38
>>959 分かりました!
ありがとうございます!
shared_ptrって余分に一回メモリ確保してない?あれは何なの?
参照回数を共有するため、その変数を確保してる。
関数の戻り値は、通常 値渡しですが 100Mほどのデータをもつクラスでも値渡しになりますか。 (値渡しのコストを下げるために) もし100Mがポインタに入っていて、 auto変数でリターンするとデストラクタが働いてメモリは解放されてしまいますが newで確保した物をリターンすると、それは解放できなくなりますか。
戻り値にクラスを持ってこずに引数を参照渡しにすればいいのですが 変数を用意する事無しに、リターンがクラスになっていると便利なことがあるんです。
戻り値がクラスというのは意味不明。 オブジェクトを返すとして、たとえば、 LARGE func() { return * new LARGE; } というのは結局コピーしてるし、メモリが回収不能になるので、絶対にだめ。 LARGE & func( LARGE & inout ) { //LARGEを使った処理。 return inout; } として、外で大きなデータを用意してやるか、 funcで全く新しいオブジェクトを作成したいと言うなら、newしてポインタを返せばよい。
>>965 Qtでこんな関数をオーバーロードしろって言われてるんだけど、
何を返せばいいの?
QSize sizeHint(引数略)
{
return ?
}
QSizeオブジェクトでいいと思うよ。
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const あとこんなのもあるんですが・・・
QSizeオブジェクトを返すことが、ライブラリによって強制されてるんだから、従えよ。
お前が何を聞きたいのかわからない
> というのは結局コピーしてるし、メモリが回収不能になるので、絶対にだめ。 ってかいてるじゃないですか
QSizeって大きくないでしょ。(というか100Mというサイズはどこから) 値で返しても何も問題ないじゃん。
それ以前に QSize sizeHint(引数略) をオーバーロードするのに、 戻り値を参照やポインタにはできんだろ。 オーバーロードのルールを思い出すのだ。
いや、戻り値を変えられないのはオーバーライドじゃろ。
たまにいるよね(値|参照)(返し|渡し)の違いがわからない人って まあわからないようなレベルでできることなんて高が知れてるから分かるまで値返しでいいんじゃないかな
977 :
デフォルトの名無しさん :2009/11/21(土) 05:12:37
インテルコンパイラでコンパイルしている場合に#ifdef分岐させたい場合、 #ifdefの後何を書けばよいのでしょうか?
defined (__ICC)
980 :
デフォルトの名無しさん :2009/11/21(土) 05:37:04
オンラインで見られて、プログラム未経験者向けのC++の講座って、ロベール以外に何がありますか?
ロベールの翻訳は分かりやすい
自作クラスをcoutで出力するにはどうすれば良いですか?
そのページに書いてあるのは標準ストリームクラスの拡張であって、 君がやりたいのは標準ストリームクラスで自作クラスを出力することでしょ? まったくの別件だと思うよ。 君が勉強すべきなのは、演算子オーバーロード。
サンクス!です
これで出来ることはわかりましたが、char*からsize分だけ渡すにはどうすればいいですか。 std::ostream& operator<<(std::ostream& os, const ustring& x) { return (os<<*****): }
>>983 多くのプログラミング書籍が洋書からの翻訳であることを揶揄したジョークだろう
よく書かれるコピペみたいなものだ
>>988 C/C++言語の仕様で\0まで出力だと思うので、任意の場所に\0を突っ込んでやればいいと思うよ。
バッファのオーバーランやアンダーランに気をつけて。
\0があっても標準出力へ渡したいんです… ustringはchar*とintのペアです。 STLは使えません。 あと、別の質問があるのですが。 クラスのメンバ関数で、 char* & operator [] ( int n ) { return &(ch[n]); } だとエラーになります。 char* & operator [] ( int n ) { static char*p=&(ch[n]); return p; } だと通るのですが 同時にアクセス来た場合に困ります。 衝突しない参照渡しはどうやればいいですか。STL stringみてもよくわかりません。
>>991 変数でもないものの参照を返したいとか訳分からん
値を返すんだと不都合なの?
>991 やりたい事は本当に operator[] で char* & を返す事なのか? ch って char* なんだよな? string と名のつく型で operator[] だったら普通 char& が返ると思うんだが。
値で返すと memcpy(buf, &str[0], size); が実行できないんです。 error メモリ上に配置されなければならない がでます。 static char*の参照返しだと出ません。
わかりました。間違えてました。
>>993 さんのご指摘通り間違えしてました。
>>988 たのみます
char* , intが与えられたときに標準出力( << )に\0を含む文字列を出力したいです。
>>996 その前に、どういうインタフェースにしたいのか考えれ。
operator<< をオーバーロードすると
cout << yourclass << endl;
のような書き方ができるわけだが、
char*とintの二つのパラメータを与えるなら
そういう書き方はできなくなる。
それとも const char * operator()( int ) みたいなメンバを持たせて
cout << yourclass( 文字数 ) << endl;
とかけるようにでもするかい^^
stringは、string(ch, size)で、\0を含む文字列を cout<<に渡せるじゃないですか。 この実装はどうやってるのかわかりたいです。
templateクラスのメソッドってnewしたら使われてなくても全部実体化しちゃう?
>>998 コンストラクタの話とoperator<<の話がごっちゃになってるじゃないか^^
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。