1 :
v(^・^)v :
04/02/29 01:19 C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
また、テンプレートライブラリ(STL含む)に関する質問は
専用の別スレへどうぞ。
過去スレ、関連スレ、関連リンクなどはこちら
>>2-13
2 :
v(^・^)v :04/02/29 01:21
3 :
v(^・^)v :04/02/29 01:22
4 :
v(^・^)v :04/02/29 01:22
5 :
v(^・^)v :04/02/29 01:23
6 :
v(^・^)v :04/02/29 01:24
7 :
デフォルトの名無しさん :04/02/29 01:25
こんなもんかにゃ〜 後何かあったら付け足してください。
8 :
デフォルトの名無しさん :04/02/29 01:39
すみません、質問させて下さい。 CDでのRAWに対応するものをDVDで引き出すコマンドってありますでしょうか。
STLつかうと一気に実行ファイルサイズが10倍に?!
>>12 環境によるだろ。
俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力
ランタイムを使用するようにして使っているが、例えばstd::vectorを
使っても使わない時と比べ10Kほどしか増えない。
>>13 すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。
さすがに飽きたぞこの伝統芸能
C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。 とかいうエラーが出るんだけどこれってどうすればいいのでちゅか?
そんなエサで俺様がクマ――!! (AA ry
ム板の地鎮祭?
iostream関連でおすすめの日本語サイトあったら教えて下さい
検索でたまにひっかかるRogue Waveのドキュメントはわりと参考になる。 WWWで公開されてていいものかどうかは知らんが。
前スレのレス数が1002って表示されてるんだけど、開いてみるとふつうに1001で終わってる。 これ、どういうこと?
当方、以下のコードが通りません。どこが悪いかご指摘願います。 Metrowerks CodeWarrior 8.2 Pro for Winを使っております。 (hello.cpp) class hoge { public: hoge(); ~hoge(); private: struct impl* pimpl_; }; struct hoge::impl{}; hoge::hoge() : pimpl_(new impl){} hoge::~hoge(){delete pimpl_;} int main() { hoge hage; return 0; } (メッセージ) エラー: 宣言シンタックスエラー hello.cpp 行: 9 struct hoge::impl{}; エラー: 宣言シンタックスエラー hello.cpp 行: 10 hoge::hoge() : pimpl_(new impl){} 警告: 不完全な struct/union/class 'impl' の使い方が不当です。 hello.cpp 行: 11 hoge::~hoge(){delete pimpl_;} ちなみに struct impl; impl* pimpl_; とあらかじめ宣言すれば通ります。
>>27 'struct impl'の形はelaborated-type-specifierといって、でてくる文脈によって働きが微妙に異なる。
struct impl;
とかくと、そのスコープでimplが宣言され、
struct impl* pimpl_;
とかくと、「そのスコープを含む、最も内側の、非クラス、且つ、非関数宣言の」スコープ(この場合はグローバル名前空間)
でimplが宣言されたことになる。
詳しくは規格の3.3.1の5を参照すべし
訂正 誤:とかくと、そのスコープでimplが宣言され、 正:とかくと、その宣言を含むスコープでimplが宣言され、 誤:とかくと、「そのスコープを含む、最も内側の、... 正:とかくと、「その宣言を含む、最も内側の、...
こんな怪しい仕様、根拠がさっぱりわかりません。
>>28 レスありがとうございます。ご指示のありました規格書を読みましたところ、
ご指摘の通り、この場合struct implはグローバル空間に宣言されていて、
struct hoge::impl〜のhoge::を削除することによってコンパイルすることが
できました。
しかしながら、一つの疑問が増えます。前掲のコードはExceptional C++(訳)の
Pimplイディオムに必要な部分だけを取り出してきたものと認識して
おります。私の認識がが間違っているのでしょうか。それとも前掲の
書籍のサンプルコードが間違っているのでしょうか。どなたか更にご指摘願います。
>>31 本は持ってないけど、
> struct hoge::impl{};
これを
struct impl{};
こうしてあった、とか?
>>33 少なくとも手持ちの本ではしっかりhoge::に当たる部分が書かれています。
(項目27に1回,30に2回)和訳の際の誤植とか…結構他にもありますし…
>>34 項目27は「先行宣言してあるクラスへの」と書いてあるから
struct impl; は省略されていると解釈したほうがいいんじゃないだろうか。
しかし、項目30とか見ると、Sutterタンのサボりやね。
36 :
デフォルトの名無しさん :04/02/29 20:14
質問おねがいします。 よくC++にはガベージコレクション(GC)がないのが欠点(?) とか言われますが、自分的には数年C++を使ってきて スマートポインタで十分なのですが、それでもGCが必要という のには何か理由があるのでしょうか?
すまぽすらろくに使えない人が多くてねぇ・・・
STLもろくにかじらずに入門本だけ見てGC無いといってるか、 標準には使いづらいauto_ptrしかないからそのことをいってるんだと思われ。 shared_ptrとかそのうち標準になるんだろうね。 制御できないGCなんていくらあっても屑なんだが。
参照カウント型のスマポぐらい C++ Templates 読んで自作しろ。
レスを下さった皆さん、ありがとうございました。恐らくご指摘の通り、 Sutterさんがサボったのだろうと思います。これからはきがねなく先行宣言 しようと思います。重ね重ねありがとうございました。
>39 成熟させるのが面倒。
スマートポインタと書いておきながらstd::auto_ptrを 使っておりました(TT もう一度勉強してきますです。 ありがとうございました。
ガーベジコレクションがあったら、 スレッド間のデータの受け渡しが簡単になるよ。
ハァ?
>>44 そんな話聞いたことないので、詳細きぼん。
>>45 ,46
データオブジェクトをのやり取りにキューを使用したてスレッド間通信する場合、
所有権があいまいになるからGCがあれば楽だといいたいのでは?
まあ、別にGCなくても実装簡単だけど。(それともJ*V*儲の戯言か?
>>36 ポイントされるオブジェクトの寿命によるんじゃないの?
リソースオブジェクトみたいに寿命が長ければ、smart_ptrで十分。
っていうかそういうものをGCにしてしまうとデストラクタがいつ走るか
わからんのでかえってよくないような気がする。
寿命が短く頻繁に生成・破棄を繰り返す場合には確かにGCあれば良いかも。
しかし、そういった状況は設計時に手を打てば回避可能だとおもうし。
(・∀・)→(・∀・) ↑ ↓ (・∀・)←(・∀・) アアアァァ━━━━━(ゞ゚Д゚)ゞ━━━━━!!!
C++ マニュアル tp://www.cc.nao.ac.jp/fsunman/japanese/C++/
51 :
デフォルトの名無しさん :04/03/01 13:28
in_availが両方とも0しか返さないのですがどうしてでしょうか。 また、in_availってどんな風に使うのでしょうか? ifstream file("test.txt"); cout << file.rdbuf()->in_avail() << endl; ←こいつ file.read(buf, M); cout << file.rdbuf()->in_avail() << endl; レスお願いします。
52 :
デフォルトの名無しさん :04/03/01 13:28
52get
53 :
デフォルトの名無しさん :04/03/01 13:39
ファイルの存在チェックを行うには、どんな手法がよいのでしょうか? ifstreamを使って、エラーをチェックするのが一般的なのでしょうか?
access(2)
>>53 実行してエラーになったらファイルがない。
56 :
デフォルトの名無しさん :04/03/01 16:35
VC++.NET2003なんですがネームマングリングが 日本語版と英語版で違ってたりしますか? リンクでエラーが出るのでLIBの中身を見てみたところ 一文字だけ違ってました。 ?関数名@クラス名@@QAEXI@Z が ?関数名@クラス名@@QAEXK@Z みたいな感じでI->KやH->Jみたいに どこか一箇所がコード2つ分後ろにずれます。 ご教授よろしくお願いします。
スレ汚しすみませんVisualStudioスレの方に逝きます。
Sutterさん、項目37ではちゃんと先行宣言書いてるじゃないですか!…
禿の本って全然初心者ようじゃないってことにやっと気づいた。
>>53 boost::filesystem::exists
>>51 test.txtは空じゃない?
ちなみにBCC5.6.4で14,278バイトのテキストを入力に取った
時の出力。
14278
3928
63 :
デフォルトの名無しさん :04/03/02 07:45
このコード、GCCだとコンパイル通るのですが、 VC++6.0だとコンパイルできないのです。 通したいのでしがなにか技ないですか? #include <iostream> class A { public: int a1; char *p; int a2;}; class B {public: int b1; int b2;}; union C { A aa; B bb;}; C c = { aa:{ 1, "hoge", 2 } }; C d = { bb:{ 3, 4 } }; int main(){ std::cout<< c.bb.b2 << "\n"; return 0;}
最初のメンバ以外での初期化はまずできないだろうねえ。 どうしてもというのなら 独自拡張があるかどうかVCスレあたりで聞いてみては?
ネタねーな。ぼるじょあスレで関数オブジェクトで苦しんでるヤシ がいるからここに誘導するか?
教えて君はイラネ
まあ俺が三枚にあげてやらぁ
(´-`).。oO(三枚には"開く"のではないだろうか…)
おろすだよ
inline int foo(int a, int b) { return a * 100 + b; } enum { VAL1=1, VAL2=2 } int result = foo(VAL1, VAL2); みたいに inline 関数の実引数が定数のとき、コンパイラが a * 100 + b を定数式と認識してくれることを期待してもいいもんですか?
>73 奇遇ですなぁ.漏れつい昨日これと同じことして遊んでたよ. もっと複雑なことさせたけどね. 結論から言うと期待しても良い. その例ではfooの呼び出しはリテラルの102に置き換えられることを期待できる. ただし,どこまで深く定数の伝播を評価できるかはコンパイラ依存かと.
>>73 期待できることもあるし、できないこともある。
コンパイラにアセンブリコードを吐かせてみたまえ。
最適化の結果は多分定数になるだろうが、文法的に定数式である必要がある場所 (配列のサイズとか)には使えないんじゃないか?
>>74-75 大変さんくすです。マクロにしようか迷ってたんですが期待できることが
分かれば満足です。アセンブリの方は分からないので済みません、勉強
しときます
>>76 ごめんなさいリロード遅れました。確かに最適化で結果が
変わってしまうとなると無理かも知れませんね。
そもそも inline 指定にコンパイラが従う義務はないからな。 どうしてもコンパイル時に評価して欲しければというのならテンプレート使って計算させろ
アセンブリわかんないのに、はいたコードがどうと愚痴愚痴言うなよなー。
というか、その計算を何万回もやるんならともかく、
そこだけ取り上げてどういう風に最適化されるか考えるのは
どっちかというと無駄。初心者卒業あたりって、とにかくそうやって
一つ一つの命令を最適化しようとするけど、実際にはアルゴリズムとか
ループを見直した方がよい。20-80の法則ってやつ。
profiler使った結果、その関数の呼び出しがボトルネックだって
言うのが前提なら何も言わないけど。
ま、一番正解は
>>76 ってことで。
pimplメソッドって、クラスをデフォルトのoperator=()を使って代入すると、pimplと いうポインタがコピーされるのだから、privateメンバ変数の隠蔽に使いたい場合には 自分でoperator=()を定義する必要がありますよね?Exceptional C++にはそういう 記述は見当たらないのですが。
てきとーなスマートポインタに放り込むほうが簡単。
>>81 Effectiveならともかく、Exceptionalはそういうレベルは当然の話題として
わざわざ触れてないんだと思う。
>>82 smart_ptr使うのとoperator=のオーバロードはぜんぜん趣旨が違う。
> smart_ptr使うのとoperator=のオーバロードはぜんぜん趣旨が違う。 たとえば、 boost::scoped_ptr<impl> pimpl; // コピー禁止 boost::shared_ptr<impl> pimpl; // 参照カウンタ方式で共有 こんなふうにすると、operator=のオーバーロードは不要になると思ってる。 なんか間違ってる?
コピー禁止は明示的に boost::noncopyableだな
>>boost::shared_ptr<impl> pimpl; // 参照カウンタ方式で共有 「組み込み型のように振舞え」という原則にはずれている。 本当に共有していても動作に問題が無いとか、 ライト・オン・コピーしてくれてるんなら文句は無いが。 クラスライブラリとかで勝手にこんな実装されると混乱するのでやめてほしい。 デバッグの最中に「このクラスは代入されても実装部分は共有される」なんて ドキュメントを見たらぶち切れると思う。
沸点の低い奴だ
みんなboostの使い方はどうやってマスターしてるの? ソース読んでるとか?
89 :
デフォルトの名無しさん :04/03/05 10:35
とりあえずドキュメント読むだろ。不完全とはいえ邦訳もあるんだし。
>>88 STL覚えるのと似たような感じ?
てーか、どうやっても糞もねーだろ。
使って覚える、これ最強。
93 :
デフォルトの名無しさん :04/03/05 22:26
for(i=0;i<array.size;i++) { cout << array[i]; } これをアルゴリズム(for_each ?)を使って書くには どうしたらいいのでしょうか?
>>93 #include <iterator>
copy( array.begin(), array.end(), ostream_iterator<T>(cout) );
Tはarrayの要素の型ね。
Boost使ってよければ
using boost::lambda;
for_each( array.begin(), array.end(), cout << _1 );
>>95 for_each以外に
vector<int> v;
copy(v.begin(),v.end(),ostream_iterator<int>(cout," "));
あとlambdaでの注意点。
using namespace std;using namespace boost::lambda;
for_each(v.begin(),v.end(),cout << _1 <<" ");//これは動く
/*これは動かない、少なくともbasic_ostream<char,char_traits<char> > & endl(basic_ostream<char,char_traits<char> > &)と
basic_ostream<wchar_t,char_traits<wchar_t> > & endl(basic_ostream<wchar_t,char_traits<wchar_t> > &)があるので。
*/
for_each(v.begin(),v.end(),cout << _1 << endl);
Boostの「使って覚える」ような本が出れば売れると思う。
for_each( array.begin(), array.end(), cout << _1 ); この衝撃的なコードがなぜ動くのかも疑問だけど、なにがどうlambdaなのかがもっと疑問 λってナニを意味してるの?
関数
λは ひと と ひと とが支え合ってできています
一瞬、ランバダって読んだよ(w 若い人は知らんか
102 :
デフォルトの名無しさん :04/03/06 01:55
腰の辺りがむずむずしてくる。
ってことはオレも若くないのか。
あ,ごめん.templateスレだとばっかり思ってた.下半分は無視してちょ.
>>105 もはや実行コードのサイズなんて問題にはなりませぬ。
むしろコンパイラ側の最適化に一任した形となっているのでは。
コンパイラ技術はまだまだこれからだけど。
コードサイズ要求のシビアな分野では普通にCを使うだろうし。
なんでも適材適所かと。
> でもexpression templateの多用って実行コードを
> 爆発的に肥大化させるように思えるんだが,
確かに typeof / auto がないと途中でExpression Templateを
virtual関数に分断せざるを得ないのでその分コード量が
増えるんだがしかし、
逆に言えばtypeofやautoや型推論があれば、むしろETによって
最適コードだけが出力されるので、実行コード量は減る方向に
行くんじゃないかと思う。例えば型情報を全部手書きで頑張ると、
http://www.boost.org/libs/spirit/doc/techniques.html の no_rule3.cpp
くらいにはすぐに落ちるわけで。
>>107 ぎゃーす!そのページ読み落としてた.ありがとう.
っていうか,すでにそのレベルの文法でも,頑張ってらっしゃる
no_rule3.cppのtypedefがやばいことになってるんですがw
やっぱauto( ゚д゚)ホスィ…
再帰的なBNFだと連中はどうするつもりなんでしょうかねぇ・・・
(仮想関数に逃げるしかなさそうな・・・)
>>108 > no_rule3.cppのtypedefがやばいことになってるんですがw
禿同w
再帰的BNFは、やるとすればBoostのVariantみたいな
recursive_wrapper か、コンパイラの発展を期待して
特大subruleで頑張るか…。微妙だけどな。
110 :
デフォルトの名無しさん :04/03/06 10:16
std::for_each(text.begin(), text.end(), std::cout << boost::lambda::_1 << ' '); これの最後に改行文字を入れる一つの式を作ることはできますか?
複文を関数化すればいくらでもできるが たぶん君の期待してるようなものは無理。
std::endlが多用されてるようですが、なぜでしょうか? 出力ストリームのフラッシュは必要ない場合がほとんどだと思うのですが。
>>112 その通り。'\n' と同じ効果を期待するなら '\n' で十分。
std::endl; が多用されているのは '\n' より美しく見えるという
理由だけのような気がする。
114 :
デフォルトの名無しさん :04/03/06 18:47
>>112 出力先が常にstd::coutと仮定できればね
115 :
デフォルトの名無しさん :04/03/06 18:52
>>112 改行コードに関する環境差は今でこそ大所では何とか辻褄あわせしているようだけど
根本的に「ヤバい状況」であることには間違いなかんべ
本格的に破綻するまで待たずに予防策を打っておく案にはおいら賛成だ
cout << "HELLO " << "WORLD!" << endl; これの意味がわかりません。Operator Overloadをどう活用すれば こういった記述ができるようになるんでしょうか?
>>116 今回の例では
A << B は
ストリームの A と文字列の B を取って戻り値として A を返す左結合の演算子
つまり
((cout << "HELLO ") << "WORLD!") << endl;
(cout << "WORLD!") << endl;
cout << endl;
cout;
と計算が進んでいく
>>116 どの部分がわからんのかちゃんと書いてくれ。よけいな手間がかかる。
文字列リテラルはchar*に対するoperator<<のオーバーロード、
マニピュレータは関数ポインタに対するオーバーロードを用いている。
繰り返し適用できるのはどれも演算後に自分自身(この場合cout)をreturnしてるから。
#マニピュレータはメンバでなくフリー関数だったかもしれない。が、本質には関係ない
>103 多謝。初めて知った↓ The reason this is called a lambda expression is that traditionally, such placeholders are written using the Greek letter lambda λ.
「ラムダ計算」とか「lambda calculus」でぐぐってみ。
>>116 coutのoperator<<の引数としてそれ以降のやつを取る、といえば分かるか?
(c +_+) < C++だけど何か質問ある?
>>122 C++を使うと禿げるってホントですか?
C++作ったやつはC++作ったせいで禿げたそうだ。
あれだけ奇天烈で頭痛くなるもの作りゃ、禿げもしようというものだ。
MACアドレスを取るのはどういう方法があるのでしょうか?
そう、マックね、マック。
>>126 どこのMACアドレスかわからんし処理系依存。
129 :
デフォルトの名無しさん :04/03/07 17:39
>>117-118 ,
>>121 どうもありがとうござます。
/usr/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/include/g++-v3/
の下を眺めているんですが、coutの定義されてる場所が見つかりません…
あ、書き込んだ後に見つけたんですが、 /usr/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/include/g++-v3/iostream に extern istream cin;///< Linked to standard input extern ostream cout;///< Linked to standard output extern ostream cerr;///< Linked to standard error (unbuffered) extern ostream clog;///< Linked to standard error (buffered) #ifdef _GLIBCPP_USE_WCHAR_T extern wistream wcin;///< Linked to standard input extern wostream wcout;///< Linked to standard output extern wostream wcerr;///< Linked to standard error (unbuffered) extern wostream wclog;///< Linked to standard error (buffered) #endif という記述がありました。どうもすみませんでした。
>>130 演算子オーバーロード以前にC++の基本的な部分の勉強が足りな過ぎ。
処理系のソースを漁るのもいいが
標準ライブラリの体系だった説明とコード例の載った本を読め。
おりはprintfの引数の ...) よりは operator << の方がわかりやすかったな。
>>132 ん?
cout の定義場所もわからないでいるのに
演算子オーバーロードの利用もないだろうってこと。
無論学習順序はそれぞれだろうが、
その目的のためにも標準ライブラリは参考になるところが多いはずだしな。
<iostream>を#includeすればcoutが使えることがわかれば十分だろうが。 細かい実装の詳細なんてどうでもいい。
大元の
>>116 の質問を読んで言っているのか……?
お前の個人的な意見だと言うのなら勝手だが
137 :
デフォルトの名無しさん :04/03/07 18:19
>>134 なるほど、そういうことか。
まあ、俺はcoutの定義場所(おそらくスタティックライブラリの中)を知ることが
重要なことだとは思わんが。
139 :
デフォルトの名無しさん :04/03/07 18:20
面白いコピペを見つけたので、皆さんの手でこのカーチャンが言ってる事をもっと凄くしてやれませんか? J( 'ー`)し たかしへ 最近C++勉強してるのでウィルス添付してみました 開くと自動実行するからね (`Д) OSごと消えたウィルス送るな殺すぞ J( 'ー`)し ごめんね。おかあさん始めてウィルス作って見たから、ごめんね (`Д) うるさいくたばれ、しかも俺から世界中にウィルス発信されてるじゃねーか J( 'ー`)し ニューヨークも全体落ちたみたいです 食事はしてますか? (`Д) もうおなかいっぱいです
140 :
デフォルトの名無しさん :04/03/07 18:22
J( 'ー`)し たかしへ 最近.NET勉強してるのでウィルス添付してみました 開くと自動実行するからね (`Д) OSごと消えたウィルス送るな殺すぞ J( 'ー`)し ごめんね。おかあさん始めてウィルス作って見たから、ごめんね (`Д) うるさいくたばれ、しかも俺から世界中にウィルス発信されてるじゃねーか J( 'ー`)し ニューヨークも全体落ちたみたいです 食事はしてますか? (`Д) もうおなかいっぱいです
なんだかお騒がせして申し訳ないです。coutがなんなのかは分りました。 ### gcc/libstdc++-v3/src/globals_io.cc ### typedef char fake_ostream[sizeof(ostream)] __attribute__ ((aligned(__alignof__(ostream)))); fake_istream cin; fake_ostream cout; ### gcc/libstdc++-v3/src/ios_init.cc ### extern istream cin; extern ostream cout; ・・・ ios_base::Init::Init() { ・・・ new (&cout) ostream(&buf_cout_sync); new (&cin) istream(&buf_cin_sync); new (&cerr) ostream(&buf_cerr_sync); new (&clog) ostream(&buf_cerr_sync); ・・・ しかしostreamの定義場所がどうしても見つけられません…
>>142 /usr/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/include/g++-v3/iosfwd
(iostrem → ostream → ios → iosfwd という順序でインクルード)
ここに
namespace std {
・・・
typedef basic_xxx<char> xxx;
typedef basic_xxx<wchar_t> wxxx;
・・・
という風にIO関連の型定義がいくつかありました。どうもお騒がせしました。
144 :
デフォルトの名無しさん :04/03/07 20:24
C++のmain前の初期化順序の問題なんだけど int i=0; struct A { A() {i=1;} static A & a() { static A a; return a; } private: static A * ap; // (*) }; A * A::ap=&A::a(); // (*) int main() { A & ap=A::a(); // (**) return 0; } (*)の部分がない場合は(**)の呼び出し前後でiの値が 変わることになる。(*)の部分があるとmainの呼び出し前に A::a()の呼び出しが行われているみたいだけど、 これってC++の仕様的に保証されているのでしょうか? Singletonのインスタンスにmain前にアクセス可能にする場合 上みたいに実装すること思うけど、スレッド安全性の確保の 為に、main前にはA::a()が呼び出されていて欲しくてこんな風に してみた。まあ、mainの先頭で手動で呼び出してもいいんだけど。 apに誰もアクセスしないので最適化で消えちゃうかなあ?
グローバルオブジェクトはプロセス開始時(mainの前)に初期化される。 ただ依存関係を持つ複数のオブジェクトがあったりすると話がややこしくなるけど。
グローバルじゃないね。スタティックだ。 ただポインタ ap はクラス変数じゃなくて ふつうのグローバル変数として定義するべき。 翻訳単位の異なるスタティックオブジェクトの初期化順序に関する規定はないんで そういう場所で定義するのはよろしくない。
あー、まだ誤解を与えそうだ。 ローカル(関数内部)のスタティックオブジェクトの初期化は その関数を最初に呼び出したときに行われるんで、 a() の呼び出しそのものを省いたりはしないで。 ついでにグローバルの ap もポインタじゃなくて参照でいいよね。何で織り交ぜてるのか知らないけど。 無駄レススマソ。
main()突入前/脱出後にアレコレするのは、はっきり言ってすすめられない。 たとえば、DLL化とか言い出した日にはもう目も当てらんない。
149 :
デフォルトの名無しさん :04/03/07 20:56
>>148 俺もそう思う。
サボりの美学と非科学的な神頼みの境がわかってないヴォケ大杉。
>>145 >何で織り交ぜてるのか知らないけど。
A * A::ap=&A::a();
とすることによりのapの初期化の為にA::a()がmain前に
必ず呼ばれる事を期待しているって意図は伝わってる?
apをprivateなクラス変数にしたのは、main前には
apがいつ初期化されるか未定だから、誰もapにアクセス
できないようにしただけです。
>>148 (Winの)DLLにしてもプロセスのアタッチ時にグローバル変数は
初期化されるんじゃないの?
>>150 私に対するレスですか?
まあ一度痛い目にあうのもいいかもしれん。 そうしてヒトは成長するのさ〜
変ちくりんな実装が必要になる時点で 多くの場合は設計に問題があるんだけどね
155 :
デフォルトの名無しさん :04/03/07 23:53
>>154 ここ一発ふんばらにゃならんときに
ふとよぎる悪魔のささやきだな
>>151 そっちよりも↓のが重要。
>ap はクラス変数じゃなくてふつうのグローバル変数として定義するべき
まあ今回の件に関してのみ言えばどちらでもよいことなんだが
ふつうは(というかそのクラスを再利用するつもりがあるのなら)
初期化は最終的にはクライアントのコードで指示する。
簡単に説明するなら、
初期化の順序や必要なパラメータの指定はプログラムの全体像を知らないと記述できないから。
まあもっと頭の痛くなる問題もあってそっちのが重要なんだけど。
#つーかモジュールでオブジェクトの生成までやってしまうのなら Singleton の意味ないし。
#たいたいコンストラクタが引数持ってたらどうするつもりだ?
何度も言うが、今回のプログラムでしかそのクラスを利用しないというのなら別にどちらでもいい。
>>156 クラス変数でもグローバルでもどっちでもいいです。
どうせアクセスしないし。
>初期化の順序や必要なパラメータの指定はプログラムの全体像を知らないと記述できないから。
Singletnoの問題はむしろ破棄の順番では?勿論、ファイルやドライバのハンドル等の
場合にはまずいかもしれないけど。少なくともそういったリソースの管理クラスに
当てはめ様とは考えていません。
>#つーかモジュールでオブジェクトの生成までやってしまうのなら Singleton の意味ないし。
んー、そうですか?ちょっと言い過ぎなような気がするけど。
>>144 雑談がしたいのか、仕様が知りたいのか、はっきりしる。
ファイルの依存関係を最小限にするには pimpl イディオムやらなんやら ありますが、実際にやってみると非常に面倒くさいと感じます。皆さんは そのへんどう解決してますか?気にせずがんがん再コンパイルですか? それとも、ちゃんと設計してからコード書けやごるぁ!!!って感じですか?
ファイルの依存関係よりも、 クラスやコンポーネントの依存関係を気にするべき。 コンパイル時間なんて気にスンナ。 あ、gccをご利用?そりゃごめんなさい。
pimpl使え。
162 :
デフォルトの名無しさん :04/03/08 01:37
>>160 気にしたくないよ
気にしたくないんだよおおお
んなこと言ったって・・・(泣
>>158 別に雑談したかったわけじゃないんだけど。
・・・main前にあれこれするなつう事で納得しました。
ありがとうございました。
漏れはファイルの依存関係も気にする。 コピペで再利用するわけじゃないし。
あんただけならどうでもいいよ。
>151 >147の織り交ぜるってのは A & A::ap=A::a(); 何故こうしない?と言うことでは。 しかし、普通に、一番最初のstatic A & a();呼び出しで初期化すればええやん、と思うのだが。 pimplは、めんどくさくは無いけど、 小さいオブジェクトにnewは何となく嫌症候群だからなぁ。
説明不足だったので再び MACアドレスを取るのはどういう方法があるのでしょうか? IPのMACで例えばWindowsなどの処理系です ipconfig.exeを使う方法があるのですがバージョンなどの問題などありますから
>>167 IPにはMACアドレスという概念はありません。
Windowsは処理系ではありません。
網かarp掬え。 物事を正しく把握し、説明する練習をしてからまたもどってこい。
頻繁に構築・解体するコンテナ(例えばループ内の一時変数など)は、 ヒープの分断化を招きますか? やはりループ外で事前に定義しておくか、自前でアロケータを書くべきでしょうか? ちなみにalloca()などを使ってスタック上にアロケートするアロケータを書くことは この場合妥当な選択でしょうか?
socketのテンプレートライブラリを作成するっていう 話はどこにいったの?
boost-sandbox/boost/socketも放置されてるっぽいし
173 :
デフォルトの名無しさん :04/03/08 21:52
#include <iostream> #include <ctime> using namespace std; int main() { std::time_t systime = std::time(0); std::tm *cur = std::localtime(&systime); cout << systime; } 上のようなプログラムを実行すると1078750166と表示されるのですが、 これを2004/3/XX XX:XX というようにするにはどうすれば?
curが持ってる値を使っていろいろ頑張ってください てかC++じゃなくてCの話題だねそれ
std::asctimeとかstrftimeとか
asctimeないしctime 本当にそのフォーマットじゃなきゃいけないのならstrftime あとはリファレンス見てくれ
>>174-176 お答えサンクス。
てぇことはですよ、プログラム中で時刻を使いたい場合は
その文字列から時分秒を求める必要があるンすか?
178 :
こんぴゅー :04/03/08 22:40
1) 3; 2) a=3; 3) d; 注:この直前の文はchar d[10]; 4) ((a=3)>2 || (b=0)<-1); 5) "abcdefg"; 6) printf("%s",string="abcdef"); 注:変数stringは文字型へのポインタ変数 各式の評価値を教えてください(理由もお願いします)
179 :
デフォルトの名無しさん :04/03/08 22:41
>>177 お前が使っているstd::localtimeはいったいなんなのかと(ry
ある人に質問したら、答えがこれだったんですよ。 じゃあ、どうすれば良いですか?
Cのスーパーセットを目指していたとはいえ、 Cの標準関数は別の名前空間にしておくべきではなかったか。
>>180 localtime の引数は何なのか調べればよろしいかと。
もまいら変態、いやもとい大変です!! templateスレで聞こうと思ったのですが下がっているので ここに来ますた。 class CTest { public: void f() const { g(); } void g(){} }; このコードはもちろん通らないのですが このクラスをtemplateにするとconstのチェック が効かなくてコンパイルできてしまいます。 なんでですか?
>>184 クラスtemplateのメンバ関数は、必要になるまで定義が実体化されないから。
たぶん、コンパイルできてるソースからは f() の呼び出しがないんでしょう。
そうですた。ありがとうございますた。
>>170 > 頻繁に構築・解体するコンテナ(例えばループ内の一時変数など)は、 ヒープの分断化を招きますか?
情報足らなさ過ぎ。実測するのが一番。
実測する方法もわからないのなら、そもそも断片化を気にしてもしょうがないし。
190 :
デフォルトの名無しさん :04/03/09 08:11
スタックについてなんですが、大きなサイズのオブジェクトの 配列とかをローカルで宣言するとスタックの浪費になるのでしょうか? ポインタの配列を宣言して、オブジェクト自体はヒープに 作ったほうがいいのでしょうか?
まずはアセンブラやったほうがいいよ
スタックもヒープも同じメモリなのでどちらを使っても メモリの使用量は同じだと思うのですが、スタックというのは 一定の予約された領域なので、大きなオブジェクトをバシバシ 作ってもいいのかと思いまして。(スタックオーバフローとか いうのもあるといいますし...)
細かいことは環境やプログラムの他の部分に依存するが あまりに大きいオブジェクトの配列はスタック上よりヒープに作った方がとりあえず無難。 それよりその用途ならポインタの配列じゃなくて ふつうにオブジェクトの配列を動的に作成すればいいんじゃないの? あとでオブジェクトを一個一個受け渡すのならともかく。
>>194 そうでした。ポインタの配列である必要はないですね。
ありがとうございました。。。
196 :
デフォルトの名無しさん :04/03/09 13:48
placement newについて教えて いただきたいのですが、これってただ コンストラクタを呼んでくれるだけですよね。 であれば new ((void*)pObj) CWidget; なんてせずに単に pObj::CWidget(); としたらいいのになんでわざわざplacement new という構文が必要なのでしょうか? 実際deleteにはplacement delete(?)みたいな ものはなくて pObj::~CWidget(); と書いているのをよく見ますが...
>>196 そのpObjってのが何なのかわからん。
ともかく placement new ってのは
引数で与えられた領域にオブジェクトを生成するためのものだ。
コンストラクタを呼び出すだけってのは見当違い。
pObjというのはCWidget型のポインタです。 すでに確保されたメモリ上の位置をさしています。 >コンストラクタを呼び出すだけってのは見当違い。 ほかにはどんな作業があるのでしょうか?
>pObj::CWidget(); >pObj::~CWidget(); >pObjというのはCWidget型のポインタです。 出典はしらんがこんなコード例が載ってるものを信用するな。 >ほかにはどんな作業があるのでしょうか? 注目してるのはオブジェクトを生成する領域だって言ってるだろ。 つーか通常のインスタンス宣言と new や placement new との違いを本当にわかってるのか?
俺も疑問だ。 class AAA { AAA() {} ~AAA() {} }; charbuf[sizeof(AAA)]; AAA*pa = new(buf) AAA; pa->~AAA(); pa->AAA::AAA(); pa->~AAA(); どっちも同じように走るんだが、何が違うんだろうな? と書いてて思ったんだが、クラスAAAにplacement newがあったら後者はまずいな。
>>199 ありがとうございました。
もう一度出直してきます。
コンストラクタには名前がないから、 標準C++ではその様に直接は呼べないだろう。
そんなわかりにくいか? それともそういう局面自体が想像外なのか? あるオブジェクトを”割り当て済みのメモリ領域に”生成したいときに使うのが placement new だ。 コンストラクタやデストラクタの振る舞いなんかは二の次。 詳しいことは More Effective C++ の第8項を読むといい。
placement newならキャストしなくてもいいとか
>pObj::CWidget(); >pObj::~CWidget(); >pObjというのはCWidget型のポインタです。 っていうかこれ、コンパイル通るの?
だから(標準C++に従うならば)placement newを使うしかない。と思われる
コンストラクタ中からコンストラクタを呼び出しても、一時オブジェクト が作成されるだけで、呼び出しが終わると消滅してしまう。だから placement newを使うか、コンストラクタを呼び出した結果を*thisに 代入しなければならない。 #include <iostream> class sample_class { public: int value; sample_class(int i) { value = i; std::cout << "Ctor(int) called\n"; } sample_class() { sample_class(10); // ダメダメ // new (this) sample_class(10); // *this = sample_class(10); std::cout << "Ctor() called\n"; } ~sample_class() { std::cout << "Dtor() called\n"; } }; int main() { sample_class a; std::cout << a.value << std::endl; }
もしコンストラクタが動的にヒープを確保するようなものだと、 コンストラクタからコンストラクタを呼び出して放置すると メモリリークが起きてしまう。
>>208 ちごた、これは間違い。デストラクタが正しく書かれていれば一時
オブジェクトの消滅時にデストラクタが呼ばれる。
void *operator new(size_t, void *place) みたいなやつはあくまでデフォルトの定義。 それはそれで有用ですけど。 placement な operator new は、 例えばこんな風にオーバーロードして、 どこからメモリを確保するかをコントロールしたりとか けっこういろんなことに使える。 void* operator new(size_t n, Allocator& a) { return a.alloc(n); }
placement delete の構文がないのは明らかな欠陥だよな
なんで?通常のnewと同じように扱えますよ、って考えれば 別になくてもおかしくないじゃん。
すいませんTT 今さらなのですが、間違っていました × pObj::CWidget(); ○ pObj->CWidget(); × pObj::~CWidget(); ○ pObj->~CWidget();
>>212 言っていることが良くわからない。漏れが言いたかったのは、
foo *p = new foo;
delete p;
とやるなら、
foo *p = new(buf) foo;
delete(static_cast<void *>(0)) p;
とか、
foo *p = new(myalloc) foo;
delete(myalloc) p;
みたいにできた方が自然じゃないか、ってこと。
漏れもそれやりたい。
その引数は一体何に使われるんだ? 形だけ見て物を言うと引数つきのデストラクタがないのは不自然みたいな話になるわけだが。
>>216 void operator delete(void *, void *) {}
void operator delete(void *p, Allocator &a)
{
a.dealloc(p);
}
こんな感じで使えばいいと思う。
デストラクタじゃなくて delete だべ。 new はコンストラクタじゃないし、delete はデストラクタじゃないよ。
確かにplacement newにつきまとう、デストラクタ直呼び出しはカッコ悪いな。
そうじゃなくて、 初期化は外部からパラメータ与えてカスタムできる必要があるけど 破棄は(必要なら内部でパラメータを保持していて) 外部からの指定なしにできるべきだという理屈。 そうでないと初期化のパターンすべてについて 破棄を命ずる側がよく知っていなくてはいけなくなるだろ。 この厄介さを考えれば初期化に対する破棄時の仮定は成り立ってもらわんと困る。 #STLのアロケータと同じ類の問題かな
>>220 オブジェクトごとに破棄方法を記録するってこと?
それはそれで意味があるかもしれないが、記法の問題を越えるよな。
それに、C++がデフォでその方法を採用するとは思えないから、
(単純なデストラクタ呼び出しに仮想関数呼び出しを付随させるわけにはいかない)
どちらにしてもdeleteと書くたびに、そのメカニズムを使うかどうかを選択せねばならんし。
いや、そうじゃなくて。
要するに、
単一の破棄手段と多様な初期化手段の両方を実現するには
どの初期化方法に対しても単一の方法で破棄できるようにするか、
それが嫌ならオブジェクト内部に何らかの形で必要な情報を記録するか
どちらかを選ぶしかないってことよ。
>deleteと書くたびに、そのメカニズムを使うかどうかを選択せねばならんし
これこそ引数つきの delete に対して
>>220 で指摘した問題なんだけど……
実際現行のC++はそんなものをサポートしていないわけで
>>222 どうも話がかみ合っていないと思ったら・・・
>単一の破棄手段と多様な初期化手段の両方を実現するには
>>214 は多様な「確保手段」と「開放手段」に似た見た目を与えようとしているのであって、
初期化・破棄についていっているのではない。
開放しちゃうのか?
>>223 確保・解放も含めての話のつもりだったんだけどなあ……。
多様な確保手段に”対応する”多様な解放手段を
常に考慮しなければいけなくなる状況に問題があることはわかってる?
特に解放側から確保側への依存関係を持ち込みたくない状況で。
独自のフレームワークで拡張するのは構わないが、
言語仕様にそんな厄介なものを持ち込まれてはたまらない。
>>225 じゃあ、
foo *a = new foo; /* ヒープ */
foo *b = new(buf) foo; /* スタック */
foo *c = new(fixed_alloc<foo>()) foo; /* 固定サイズのメモリ確保ライブラリ */
general_free(a);
general_free(b);
general_free(c);
これがうまく動作するgeneral_freeが実現できるとでも?
スレの流れ全然読まずに書くが、
>>226 using namespace boost;
shared_ptr<foo> a( new foo );
shared_ptr<foo> b( new (buf) foo, no_op() );
shared_ptr<foo> c( new (fixed_alloc<foo>()) foo, fixed_alloc<foo>::dealocater() );
とかでダメ?
>>226 勝手に話を拡張しないでくれ。
placement new は実際にシステムからメモリを”確保”することは行っていないし、
それに対応する”解放”処理もその意味でのメモリの”解放”は行わないってことは踏まえてるか?
いや、俺も
>>225 で不用意な言い方したんで悪かったと思う。
#placement new でなされる処理をメモリの”確保”と呼ぶのなら
#それに合わせようとしたんだが過度な誤解を与えそうな言い方なのは確かだ。
しかしそこまで基本からはずれた問だと揚げ足取るための例かと邪推してしまうぞ。
ちょっと頭を冷やしてきた。
たとえば、
foo *p = new(myalloc) foo;
p->~foo();
myalloc.dealloc(p);
と書く場合、開放側のコードは確保側に依存しているよな?
(pがmyallocによって確保されたことを期待している)
それを
>>214 の様に書き直したところで依存性は変わらない。
変わるのは見た目だけで、「'new'と書いたんだから'delete'と書きたい」という
自己満足を満たす以上の何者でもない。(templateが絡むと変わってくるが。)
>>225 の言うことは正論で、実行可能だ。(
>>227 氏thx)
けど、ここでは直接関係しない、ということでいいんじゃないだろうか。
>>227 それってオブジェクトの内部にデアロケータへの参照渡してるんだよな?
(クラスの継承関係に縛られないよう関数ポインタ渡すべきだと思うけど)
それって要するに
あるフレームワークに従って
オブジェクトの内部にデアロケートのための情報を保持させるってことだろ?
>>226 だかの placement delete が欲しいと言っている人(達?)の意見は
それは嫌で引数としてアロケータを渡したいと言うもののようだが。
あとついでにshared_ptr は何のために持ち出したか知らないけど。
最後にデストラクタじゃなくて delete 演算子呼んでしまわうから
実際の例としてはまずくない?
お、互いにかみ合ってなかった部分が見えてきて話がまとまって来たな。 もっかいまとめるね。 placement delete 反対派の俺としては、 (とりあえず自動変数としての宣言、 malloc や、引数なしの new のような”生の”メモリ確保は別物として) placement new を行った場合に、 その引数に対応する適切な解放処理を解放側が 常に覚えて置いて解放時に記さなきゃいけないような記述はクライアント側のコードの独立性を下げる。 だから、もしデストラクタ以外にそうした独自の解放処理が必要なら 独自のフレームワークに従ってオブジェクトの内部に必要な情報を保持するなりして対応しろ、 ぶっちゃけ、外部から与えるような形式を言語仕様が認めるような形にはするんじゃない(※)と言っている。 もう一方の主張は、 解放処理に余分な指示を与える前提で(※) どうせ後から解放のための関数呼び出しをするくらいなら 引数つきの delete があった方が構文が統一的になる、というようなものと解釈している。 で、※の部分の前提が目的意識を違わせ、かみ合わなくなっている気がするんだがどうだろね?
あー、そうした方がよさそうだね。 俺も熱くなりすぎていた。 解放時の独自の関数呼び出しがそこまで重要視されることが想像外だったのね(たぶん)、そこは謝っとく。 それじゃ俺も退散するわ。
というかね、コンストラクタの直接呼出しが何で出来ないのかと。 placement new を使えばできてしまうのであれば、 どうせなら直接呼び出せるようにすればいいのに。 構文を統一的にするなら、こっちの方がよっぽどいい。
読んだ。placement delete の話か、なるほど。
C++でplacement delete演算子を"明示的に"呼び出す構文が
ないのは、禿曰く↓↓みたいなテンプレートを用意すればユーザ定義
できるから、という理由だったはず。
template<typename P1, class T>
void Delete( const P1& p, const T* ptr ) {
ptr->~T(); operator delete( p, ptr );
}
俺はplacement newの方も廃止して、アドレスを渡してコンストラクタを
呼び出す構文"だけ"を用意しとくべきだったと思うのでplacement delete自体に
反対だが、現にplacement newがある以上、対称性からplacement deleteを呼ぶ
構文も存在するべきだというのには全面同意する。
>>230 一個目以外はdelete呼ばないよ。継承関係?関係ない。
236 :
デフォルトの名無しさん :04/03/10 03:34
placement_new [] で確保した領域がVCで解放できない...。 #include<iostream> #include<cstdlib> struct XX{ int data; XX(){std::cout << "XX()" << std::endl;} ~XX(){std::cout << "~XX()" << std::endl;} static void* operator new[] (size_t size){ std::cout << "new XX[]" << std::endl; void* p = malloc(size); std::cout << p << std::endl; return p; } static void operator delete[] (void* p){ std::cout << "delete XX[]" << std::endl; free(p); std::cout << p << std::endl; } static void* operator new[] (size_t size,void* mem_p){ std::cout << "new (mem_p) XX[]" << std::endl; mem_p = malloc(size); std::cout << mem_p << std::endl; return mem_p; } static void operator delete[] (void* p,void* mem_p){ std::cout << "delete[] ( p , mem_p )" << std::endl; std::cout << p << std::endl; std::cout << mem_p << std::endl; delete [] p; //エラー!!! -> デストラクタがないときは大丈夫 ,G++3.3.1は大丈夫 } };
int main(){ XX *x = new XX[5]; delete [] x; void* mem_p=0; XX *x2 = new (mem_p) XX[5]; XX::operator delete[] (x2,mem_p); }
それはplacement newとは言わないんじゃないのか? まあそれは置いといて、 static void operator delete[] (void* p,void* mem_p); の時のpとmem_pの値を見てみろ。 おまえがmallocから貰ったポインタはどちらですか?
239 :
デフォルトの名無しさん :04/03/10 04:49
>>238 new(mem_p)[]の中では
mem_pは 003707B9
main関数に戻ったときは
mem_pは 00000000
x2 は 003707BC
従って、
static void operator delete[] (void* p,void* mem_p);
のpにx2を渡してるので不整合が起きるみたいです。
デストラクタがある場合は詰め物?があるようで、xの場合も
delete [] x; //はOK
XX::operator delete[](x); //デストラクタがあるとだめ
XX::operator delete[](x-1);//デストラクタがあるとOK
となってしまいました。
>それはplacement newとは言わないんじゃないのか?
なんか根本的に使い方を間違えてるような気がしてきた...
>>236 void* ひとつを受け取るバージョンは標準ライブラリ<new>で定義されているので、
ユーザーが定義しちゃダメです。
だいたい、
>>237 のソースでは、メモリ確保されていない領域(mem_p=0)
のところにplacement newしちまっているじゃないか。
placement newはすでに領域は確保してあって、そこにオブジェクトを
構築したい時に使う。
>>236 =237がやりたいような、「自分の希望した
*任意の*アドレスにオブジェクトを生成する」わけではない。
class c{...};
void *buf = operater new[](5 * sizeof(c));
c* pc = static_cast<c*>(buf);
for(int i = 0; i < 5; ++i)
new (&pc[i]) c();
...
delete [] buf;
こんな感じ。というか、More Effective C++読もうや。
ちなみに、placement newは以下のコードとみなせる(More Effective C++ Item:8)。 void* operator new(size_t, void* buf) { return buf; } ここのなかで領域確保するのでは*ない*のです。
243 :
デフォルトの名無しさん :04/03/10 10:05
intの符号なし変数をvとして v=0; ~((~v) >> 1) で,intが32ビットなら, 10000000000000000000000000000000 (2) と,最上位が1のビット列になりますよね これと同じ事はshortやcharには通用しないんですか? unsigned short(16bitと仮定)やunsigned char(8bitと仮定)でそれぞれ, 1000000000000000 (2) 10000000 (2) となることを期待したのですが,参照してみると0だと言われます。 もしかして,ビット演算って1word単位でやるのですか? だとすると, 10000000000000000000000000000000 で,右から16ビットだけ読んだ場合も,8ビットだけ読んだ場合も どちらも0となってつじつまは合うんですが。
win2000がたちあがらなくなり、再ISしたら画面が緑。。。画像も悪い。どうしたらいいですか?
>>243 計算途中でintになっちゃうYO
最後に代入する部分で警告でてるはずだが。
>>243 そそ。整数への格上げ。C++でなくCでも同じ。
v=0;
v=~v;
v=v
>>1 ;
v=~v;
ならunsigned shortやunsigned charでも最上位が1になるよ。
249 :
デフォルトの名無しさん :04/03/10 13:11
はじめまして。現在アメリカ在住です。 アメリカの大学でコンピューターサイエンスを 専攻し、昨年卒業したんですが、未だに就職先が 見つかりません。今アメリカではIT業界で職を探すのは 非常に困難です。特に新卒にとっては…。 学校ではJavaでプロジェクトなどやったんですが、 これからはC++に変えたいと考えています。 そこで質問なんですが、C++に将来性はあるのでしょうか? またC++のどのあたりを勉強したら就職に役立つでしょうか? あとOSはRedhatのFedoraを使ってるんですが、 コンパイラーは何がいいんでしょうか? よろしくお願いします。
駄目な奴は何をやっても駄目。
251 :
デフォルトの名無しさん :04/03/10 14:00
言語の問題じゃないと思う。Javaは悪くないし、C++もそれほど良くない。 学者にでもなれば?と思うんだけど。
252 :
デフォルトの名無しさん :04/03/10 14:04
BYTE型の値を、16進ダンプしたいと思っています。 BYTE b=19; cout << hex << b << endl; とやってみたのですが、文字化けしてしまいます。 なんででしょうか?
>>252 BYTEってのは中身は(unsigned) charだろ。つまり文字として出力されてしまう。
intに格上げしる。
cout << hex << (b & 0xff) << endl;
みたいに。
>>253 > cout << hex << (b & 0xff) << endl;
これでは意図が不明確なので、static_cast<int>(b)の方が良いと思う。
int(b)で十分
253さんの方法でいけました。 intにしちゃうと2バイトなので、0xff00みたいになってしまいました。 「0xff」だけで出力したかったのです。
Here is an unko.
260 :
デフォルトの名無しさん :04/03/10 16:29
STLのmapの中味って、二分木ですか? 登録時にバランス化されますか? 登録コストはlog nですか? mapエントリ削除、編集のコストはどうですか? このときも逐一再バランスされますか?
>>251 学者というよりは目先の金ってタイプなもんで…。
Visual C++などのマイクロソフト系に
行きたくないんですが、それでは
就職は難しいのでしょうか?
263 :
デフォルトの名無しさん :04/03/10 19:02
#include <complex> #include <iostream> inline complex<double>& operator+=(complex<double>& c, double dval) { return c += complex<double>(dval); } // ←ここが再帰的な定義になってる? inline complex<double>& operator++(complex<double>& c) { return c += complex<double>(1.0); } int main() { using namespace std; complex<double> purei(0, 2); cout << purei << endl; complex<double> real(2); cout << real << endl; // error ... // by default, only += complex object // ok; overloaded instance purei += 1; cout << purei << endl; ++purei; cout << purei << endl; purei += real; cout << purei << endl; } このコードがgcc-3.3.2では処理途中でアボーンします。 何が間違っているんでしょうか?C++Primerのサンプルコードです。
すっとぼけてました。 エラーメッセージ見逃してました。。。 complex.C:11: error: syntax error before `&' token complex.C:15: error: syntax error before `&' token complex.C: In function `int main()': complex.C:32: error: no match for 'operator++' in '++purei' 普通のシンタックスエラーですね。失礼しました。
>>249 なんで大学卒業しといて
> そこで質問なんですが、C++に将来性はあるのでしょうか?
> またC++のどのあたりを勉強したら就職に役立つでしょうか?
> あとOSはRedhatのFedoraを使ってるんですが、
> コンパイラーは何がいいんでしょうか?
そんなことくらい自分で答えを出せないのか?そりゃ職もないだろう。
>239 デストラクタを起動するために配列のオブジェクトの数が必要なため、 たいていの実装では、数を格納する4Byteを余分に確保する。 そのため、デストラクタのあるオブジェクトのplacement new[]では、 与えるポインタと返されるポインタがずれる。 >241 どうでもいいけど >operater new[](5 * sizeof(c)); >delete [] buf; 個人的に、単なるメモリ確保には operator new(5 * sizeof(c)); operator delete(buf); こっちを押したい
>>265 > 実際の実装はほとんど全て二分木
たいてい赤黒木やね。
>>249 ただの言語ヲタに仕事なんか無ぇよ。
OSの細かいことやらハードウェアやらネットワークやらの勉強をするか、
アプリの対象となるなんらかの専門分野の勉強をしれ。
270 :
デフォルトの名無しさん :04/03/10 22:49
>>267 237の場合、
static void* operator new[] (size_t size,void* mem_p)
の中では size = 24 になってるから
5*sizeof(XX) = 5 * 4 = 20 でなく
24バイト確保せよということですよね?
242で指摘されてるように
new演算子を呼び出す前にこのメモリ分を確保してから呼び出さなきゃいけないとしたら
値が容易には推測できない気がする(コンパイラ、環境、デストラクタの有無)のですが、
何かスマートな方法があるor勘違いをしているのでしょうか?
(More Effective C++は持っていません。スイマセン)
271 :
デフォルトの名無しさん :04/03/10 23:02
* で、半径1の円を30倍にして表示させたいんですが、どんなプログラムになりますか? 勉強しはじめでもわかるぐらいな、簡単な感じでお願いします。
>>269 C++コンパイラ屋として食っていくつもりなのかもよ
274 :
デフォルトの名無しさん :04/03/10 23:31
using boost::mpl::enable_if; template <class T> typename enable_if<boost::is_integral<T>, void>::type foo(T t) {} こんな風に使えるtypename演算子ですが、gccにあるtypeof演算子とは どういった点で異なるんでしょうか?
>>273 その場合でもOSに詳しくなければかなり厳しいだろ。
つーかスレ違いなんだから構うなよ
>>274 typenameは演算子じゃありません。
>>274 月とすっぽんぐらい全然違う.
typenameはtemplate引数で与えられた識別子が型名であることを
コンパイラに明示するためのもの.
一方typeofはインスタンスの型を得るもの.
template<typename T> class C{};
C<int> a;
typeof(a) b; // C<int> b; と同じ
>>269 あんた、なんかいいこと書いてくれましたね。
で、もうちょっと教えてもらいたいんですが、
"アプリの対象となるなんらかの専門分野"って
具体的にどんなものなんでしょうか?
>>262 読んでも去らないんだから、放置するのがベストだな
284 :
デフォルトの名無しさん :04/03/11 01:27
285 :
デフォルトの名無しさん :04/03/11 02:22
あのぉ・・・クラステンプレートのメンバクラステンプレート(と呼べばよいのかな?)を クラススコープの外で定義するにはどうすれば良いのでしょうか? 書き方が分かりません・・・ template<typename T1> class C1{ template<typename T2> class C2; }; // ここでclass C1<T1>::C2<T2>を定義したいのですが書き方が分かりませんヾ(;´Д`)ノ゛
template<typename T1> template<typename T2> class C1<T1>::C2<T2> { ... };
>>286 おぉ,こんな書き方になるんですね.相変わらずC++は奥が深いなぁ・・・
ありがとうございました.ちなみに<T2>は要らないですよね?
これがあると怒られます@MSVC++7.1(無い方が文法にかなってますし)
template<typename T1> template<typename T2> class C1<T1>::C2{/**/};
>>287 > ちなみに<T2>は要らないですよね?
すまんミスった。
>270 1.placement new[]を使わない 2.何も考えずに+4余分に確保する 3.一度試しで作って(要素二個ぐらいで)ずれを調べる 俺が思いつくのはこれぐらいか
290 :
デフォルトの名無しさん :04/03/11 12:23
291 :
デフォルトの名無しさん :04/03/11 14:07
たとえば、 enum Month { January=1,February,March,…,December} という列挙型があるときに 出力をJanuaryとかアルファベットで表示する方法はありますか?
>>291 int January = 1;
という整数型があるときに、
出力をJanuaryとかアルファベットで表示する方法はありますか?
#defineですか?
>>291 #include <iostream>
using namespace std;
enum AAA { BBB, CCC, DDD, };
ostream& operator<< (ostream& o, AAA e) {
switch (e) {
case BBB: o << "BBB"; break;
case CCC: o << "CCC"; break;
case DDD: o << "DDD"; break;
}
return o;
}
int main (int c, char**v) {
cout << BBB << endl << CCC << endl << DDD << endl;
return 0;
}
enum Month { January=1,February,March,…,December}; const char* s[] = { "", "January", 略 }; Month e = 略; cout << s[e] << 略
enumの要素から名前(文字列)を取得する方法はない。 テーブルでも用意してindexで取得するしかない。 範囲外や疎な値を含む場合はmapでも使うといいだろ。 その場合には値->文字列の対応にプリプロセッサの文字列化が使える。
298 :
デフォルトの名無しさん :04/03/11 14:52
ありがとうございました。
C#だとその辺簡単なんだよね
そこでマクロプログラミングですよ
単に、月名の列挙型を12個用意するだけでなく、 INVALIDな列挙値も1つ用意しておく事をお勧めする。 変数はその値で初期化しておくのがベスト。
libcに依存しない、というかlibcをテンプレートライブラリとして 実装したら、C++ってUNIX上でも最強じゃない?動的リンクの コストもゼロ。とろくさいGC付きの仮想マシンも要らない。 OSごとの差異はポリシーとして切り出せれば。
マクロで… #define MONTH M(InvalidMonth) M(January) M(February) M(March) … M(December) #define M(s_) s_ , enum Month { MONTH }; #undef M #define M(s_) #s_ , const char* strMonth[] = { MONTH }; #undef M Month m = March; cout << strMonth[m] << endl;
std::mapでも使った方が簡単。マクロは汚ねー
#include "boost/preprocessor/seq/enum.hpp" #include "boost/preprocessor/seq/for_each.hpp" #include "boost/preprocessor/stringize.hpp" #define CASE_STATEMENT(r, _, elem) case elem: ost << BOOST_PP_STRINGIZE(elem); break; #define PRINTABLE_ENUM(name, memberseq) \ enum name{ BOOST_PP_SEQ_ENUM(memberseq) }; \ ::std::ostream &operator<<(::std::ostream &ost, const name n) {\ switch(n) { \ BOOST_PP_SEQ_FOR_EACH(CASE_STATEMENT, _, memberseq)\ default: ost << int(n); \ } \ return ost; \ } #include <iostream> PRINTABLE_ENUM(Month, (Nullmonth)(January)(February)(March)) int main() { Month m = January; std::cout << m << Month(0) << March; } どうせマクロ使うならこれくらいやらないとな。
すげえ
DirectSoundのラッパーライブラリ(DLL)を作成しています。 一通りのプログラムが完了し、デバッグをしてみたらデストラクタが呼ばれてない事が判明しましました。 "virtual"はもちろん指定しているのですが何か足らない点等があるのでしょうか? 以下にソース(抜粋)を載せておきますので、どうか宜しくお願いします。 //DirectSoundオブジェクトのインターフェイス DECLARE_INTERFACE(ISoundManager) { STDMETHOD_(BOOL, Initialize)(THIS_ HWND, BOOL, DWORD) PURE; //DirectSound初期化処理 STDMETHOD_(void, Release)(THIS) PURE; //DirectSound解放処理 //... }; //DirectSoundオブジェクトを管理するクラス class CSoundManager : public ISoundManager{ private: //メンバ変数 //... public: CSoundManager(void); virtual ~CSoundManager(void); BOOL __stdcall Initialize(HWND, BOOL, DWORD); //DirectSound初期化処理 void __stdcall Release(void); //DirectSound解放処理 //... }
//ISoundManagerインターフェイスを作成する(DLLを使用するアプリが呼び出す) extern "C" BOOL __stdcall CreateSoundManager(ISoundManager** ppSoundMgr) { (*ppSoundMgr) = new CSoundManager; return (*ppSoundMgr) != NULL; } //ISoundManagerインターフェイスを破棄する(DLLを使用するアプリが呼び出す) extern "C" void __stdcall DestroySoundManager(ISoundManager** ppSoundMgr) { delete (*ppSoundMgr); //CSoundManager::~CSoundManager が呼ばれない }
>>310 C++っていうよりWindowsネタな感じだが…
ちゃんとAddRef, Releaseで参照カウントして
Releaseの中でdelete thisすればいいんでないか。
仮想デストラクタは、あくまでも親側のクラスに宣言(定義)されてないと呼べない。
DECLARE_INTERFACEマクロの中身は知らんが、仮想デストラクタが
定義されてないんじゃないか? もしそうなら実装クラスでvirtualつけても無駄。
抜粋は気を付けて欲しいなあ ~ISoundManager() が仮想なのかわからないんだけど……。 CSoundManager のデストラクタが呼ばれてないっていうけど 別のデストラクタは呼ばれてる? そもそもどういう手段でそれを確認したかないとこれだけじゃ判断つきにくいな。 とりあえず基本的な確認事項として ポインタがNULLでないか、 不正なポインタ渡していないか( delete されてもたまたま動いている) なんかはチェックした? それとテストはDLLの形でしてるの? その場合、基本的な単体テストなんかはきちんと通ってるの?
~ISoundManager() がvirtualになってないに一票
追加で1票
審査員だから5票入れとくね
無効票入れとく
エビフライ入れとく
>309 詳細不明な俺マクロをやめろ。 メンバ関数に__stdcallってなに? BOOL返すだけならCreateはポインタを返せよ。 Destroyはポインタのポインタを受け取る必要ないだろ。
319 :
デフォルトの名無しさん :04/03/11 22:45
>>311-319 スレ違いでしたか、失礼しました。
取り合えず、参照カウンタを保持してやることにしました。
あと、ISoundManager::~ISoundManagerを実装すると、
interfaceではなくclassになってしまい、Cで使えなくなってしまうのでちょっと都合が悪かったりします。
ちなみに、DECLARE_INTERFACEは俺マクロでないです。
マイクロのヘッダにあるマクロです。
さておき、レスありがとうございました。
>320 意味がわからん。CSoundManager::~CSoundManager()を実装して、 CSoundManager::Release()から参照カウント方式でdelete this使って 呼び出せ、という話だろ。ISoundManager::~ISoundManager()は 宣言してはいけない。
>>321 ご丁寧にありがとうございます。
質問させて頂いた件ですが、
reinterpret_castを使ってダウンキャストをしてからdeleteしたところきちんとデストラクタが呼ばれるようになりました。
いろいろとお騒がせをしてスミマセンでした。
326 :
デフォルトの名無しさん :04/03/12 00:43
>>323 reinterpret_castを使ったらダウンキャストじゃない
たまたま結果が一致することはあっても
あくまで無保証
本人がもう解決したと言っているのだからほっとけ。
328 :
デフォルトの名無しさん :04/03/12 00:52
COMなんてしらねーよ。 ようするにCでも使えるようにCOMをパクったけど、理解が足りてない、ってか。
COMは考え方が汚くて嫌。例外処理もないし、コンストラクタも デストラクタもない。ただC++でWindowsを自由自在に操るとなる と避けて通れないから仕方ない。COMを全く知らない人でも GUIDなら知っているだろう。 COM+はCOMの欠点が大幅に取り除かれ、だいぶC++との親和性 も良くなっている。但しWindows 2000以降でしか使用できない。
例外はあるだろ
>>331 ま、そうだが、エラーハンドリングはCOMではコードを返すと
いう古い設計を使っているという意味ね。
コンパイラ間で例外の互換性なんてないですよね? 例えば、VC++で作ったexeからBC++で作ったdllのエクスポート関数を呼び出し 内部でthrowされた例外をexeでcatchするなんてできないですよね? コンパイラに関係なく使える例外機構ってないですか?
334 :
デフォルトの名無しさん :04/03/12 18:09
ばかばかしい質問なのですがおながいします。 例えば簡単なプログラムで int main() { int *p=new int(); } と、C++で何のヘッダもインクルードしなくても operator new を呼んでくれるのですが、これは どういうことでしょうか?(環境はVC6.0です)
newが組み込みの演算子だから。+や-だってなんのヘッダも読み込まないだろ。
336 :
デフォルトの名無しさん :04/03/12 18:59
>>335 何嘘教えてんだよ!
>>334 暗黙インクルードファイルに<new>が含まれてるんだよ。
処理系によっては<iostream>も含まれてることもあるよ。
new が <new> とは無関係なのは当然として (placement new は無関係じゃないが)、 <iostream> とかが暗黙にインクルードされる処理系ってあるの?
339 :
デフォルトの名無しさん :04/03/12 20:47
あるファイルにバイナリで書き込んである16or32bit値を読み出そうとしている。 いまリトルで開発中だが、同一のファイルにアクセスするビッグやバイへの ポーティングができるだけ短時間で終わるようにしたい。 性能重視なので「解決」はできるだけ翻訳中に行い、実行環境でのオーバーヘッドを最小限にしたい。 こういうとき、336以外のお前らだったら何を使う?
データが固定なら、読み出すときにエンディアンの変換が必要になる。 データと同じエンディアンの環境ならこの変換が省略されるようにすればよい。 データが固定でなくて良いなら、 データを異なるエンディアンを持つ環境に持っていく際に データを変換すればよい。 これなら、実行時に変換が不要になる。
341 :
デフォルトの名無しさん :04/03/12 21:33
>>340 レスどうも。自分で作るなら屁でもないんだけど、
もう1人の自分が「おめーわアフォか」と煽ってくるんだわ
C++Primerは子供にも分る英語で書かれてて分り易いですね。 C++の勉強よりも英語の勉強に適してるような感じかも。
遅レスだが、placement delete[] についてまとめてみた。
まず結論から。現規格では placement new[]/delete[] は使い難い。
1.
>>236-239 ,267 で指摘されている通り、new T[n] では sizeof(T)*n+x(x≧0)
が第一引数として operator new[] に渡される。
new T[n]の結果は operator new[] の返り値から x だけオフセットされる。
これは placement 版でも同じ。
この x の値は不定であるため、事前に必要な容量を確保しておくことができない。
つまり確保済みの領域にオブジェクトを生成することはできない。
[参考] 5.3.4 - 12
2.
>>210 ,217 のように Allocator を使う場合もオフセットが問題を引き起こす。
placement operator new[] から呼び出されたコンストラクタで例外が
発生した場合には、対応する placement operator delete[] が、
placement operator new[] が返したポインタ値を引数として正しく呼び出される。
しかし、一旦オブジェクトが生成されると、配列形式の placement new expression
が返す値は、placement operator new[] が返した値より不定値分オフセット
されている。
このオブジェクトが占める領域を解放したい場合、現規格では配列形式の
placement delete expression が存在しないため、placement operator delete[] を
直接呼び出す必要がある。
が、オフセットが不定のため plament operator new[] の返した値を引数とする
ことができない。
つまり、Allocator は allocate() が返すポインタ値と deallocate() に渡される
ポインタ値が一致しないことを想定して処理しなければならない。
[参考]
ttp://do.sakura.ne.jp/~junkroom/cgi-bin/megabbs/readres.cgi?bo=lounge&vi=999294620&res=146 結局、メモリ割り当てのコントロールがしたければ、配列を使わず vector を使え、
ということか。
plament operator new[]/delete[]は、 ヒープデバッグ以外の用途に使う事なんてないだろね。 一般PGではなく、STLを拡張したいPGにとっては重要かもしれんけど。
じゃあvectorはどうしているかというと コンストラクタではアロケータで確保したメモリを使って uninitialized_copyまたはuninitialized_fillをしている。 これは実質的には要素ごとにplacement newをしている。 デストラクタでは要素ごとに~T()をしている。 ちなみにuninitialized_copyなどに対応した廃棄用関数は標準関数にはなぜかない。
uninitialized_copyや何やらにはアロケータが渡せないけどいいんだろうか。
347 :
デフォルトの名無しさん :04/03/13 20:51
柴田望洋先生の本からの転載で //複素数クラス class Complex{ double re; double im; public: //コンストラクタ省略 friend double Real(const Complex& x) {return(x.re);} friend double Imag(const Complex& x) {return(x.im);} //中略 Complex& operator+=(Complex& x){ re+=x.re; im+=x.im; return (*this); } Complex& operator-=(Complex& x){ re-=x.re; im-=x.im; return (*this); } friend Complex operator+(const Complex& x,const Complex& y){ return (Complex(x.re+y.re,x.im+y.im)); } //以下省略 というソースなのですが、これに関して質問させて下さい。 friendについてなのですが、Complex& operator+=(Complex& x){〜〜〜}はfriend修飾しなくて良いのでしょうか? 引数の私的部にアクセス出来るようにするのがfriendだと思ったのですが、 Complex& operator+=(Complex& x)は私的部にアクセスしていますよね? どうか解説お願いします。
this返してるってことはメンバ関数だろ? クラスメソッドは firendにする必要ないよ。
ところで何で +=, -= のオペランドだけ定数参照になってないんだ?
350 :
デフォルトの名無しさん :04/03/13 21:30
たとえば、Calcというclassを作ったとして、 そのmember関数、double Calc::function(const double& x)の中身を Calc a; の中では return x*x; Calc b; の中では return x+1; などのようにすることは出来ますか? 派生class作って、それぞれにfunctionを定義するしかないですかね。 外部のfileに関数を沢山定義しておいて、 それをCalcのconstructorに引数として渡すような事がしたいのです。
aとbの差は一体なにさ? 生成された順番?変数の識別子?スコープ?
>外部のfileに関数を沢山定義しておいて、 >それをCalcのconstructorに引数として渡すような事がしたいのです 渡せばいいんじゃないのか
>>348 なるほど。*thisを返す場合には必要ないのですか。
勉強になりました。ありがとうございます。
>>349 すみません。
本に書いてあったソースを写し書きしただけなので、分かりません。
>>347 そのクラスのメンバなら、
引数のであっても直接アクセスできる。
あと、friend つけてクラス内で直接定義してある関数は、
メンバ関数ではなく通常の関数になる
(名前空間はそのクラスの属している名前空間と同じになる)。
operator+= は friend でなくていいのではなく、
friend であってはならない。
356 :
デフォルトの名無しさん :04/03/13 22:00
まあ、フレンドクラスとフレンド関数の違いを理解しろってことだな。 あと、どうしてoperator+を外部関数にするのか、とか。
C++を勉強し始めたばかりです。 本を見ながらDOSで作動するものを作っているのですが、Windowsの(DOSじゃない)を作りたいのですが、全然わかりません。
猫でもわかるプログラミング(C だけど)に行って、 それを C++ 使って書き直してみたら?
普通friendな関数はclass内部には宣言だけにして、外に実装を書かないか?
どちらにしろ普通の関数になることは同じだから、 どうでもいいっちゃぁ、どうでもいいな。
>>346 無名コンストラクタの場合
T* p = _allocator.allocate(size,0);
uninitialized_fill_n(p,size,T());
>>353 最後の一文から判断すると、
class Calc {
double (*func_)(double);
public:
explicit Calc(double (*func)(double)) : func_(func) {;}
double function(double x) { return func_(x); }
};
みたいなことがやりたいのか?(ちなみに double は値渡しがふつう)
言葉通り外部から関数を与えてを実行させたいのなら
オーバーライドを使うのはおかしいと思うんだが。
>>358 C++の基礎がきちんと身につくまではWindowsアプリなんぞ手を出すな
まず今読んでる本をきちんと最後まで読んで理解しろ
それが結局自分のためだぞ
ありがとうございます、がんばってみます。
368 :
デフォルトの名無しさん :04/03/13 23:40
>>367 Win32 APIならC++ではなくCだけで十分
C++が事実上必須になるのはCOM関係
C++が必須なのはMFC
C なんて使ってらんne-
C言語原理主義
371 :
デフォルトの名無しさん :04/03/14 00:26
テンプレートを基底クラスとして継承をやる方法を教えてください。 たとえばリストテンプレートで、 class B: public list<A> のようにやってもコンパイラが受け付けてくれません。
372 :
デフォルトの名無しさん :04/03/14 00:29
#include <list> class A { }; class B : public std::list<A> { }; で試したけど、大丈夫だよ。 コンパイラは何?
>>355 ,356,361,362
解説ありがとうございます。
要するに、
friend指定にすると普通の関数になるということは、つまりthisが破錠してしまう。
だからthisを使いたい場合にはfriend指定をしてはいけない。
ということなのでしょうか?
更にもう1つ質問なのですが、
引数や戻り値をポインタ(参照?)にしている意味はあるのでしょうか?
僕自身Cから入ったもので、関数の引数としてのポインタの用途は実引数を書き換えたい場合しか思い浮かばないのですが、
この場合、実引数を書き換えているようには見えません。
解説お願いします。
375 :
デフォルトの名無しさん :04/03/14 00:32
コンパイラはVisualC++です。 エラーは名前空間のstdを指定していなかっただけでした。 どうもありがとうございました。
>>374 1引数 operator+= はメンバ関数で、
2引数 operator+= は普通の関数だ。
operator+=(Complex& own, Complex& x) とするなら friend 関数でいいんだが、
operator+=(Complex& x) とするならメンバ関数だ。
a += b; と等価な表現は、
前者は operator+=(a, b); で、
後者は a.operator+=(b); だな。
>引数や戻り値をポインタ(参照?)にしている意味はあるのでしょうか?
foo(a += b); とか (a += b) *= c; とかできるように。
>>374 >関数の引数としてのポインタの用途は実引数を書き換えたい場合しか思い浮かばないのですが、
それは「C から入った」とかいう以前の問題のような……。
コピーのコストが高くつくオブジェクトは、コピーを避けるために
const 参照で渡すのが常套手段。
C でも、でかい構造体は const ポインタで渡すのが普通だよ。
>>377 確かに云われてみれば…。気付けなかった自分が恥ずかしいです。
中学3年生の頃からCを勉強して早2年…、Cは大体網羅したと勝手に思っていましたが、全然ダメダメですね。
C++とか云う前に修行し直してきます…。
>>378 ていうかやめれ。おまえには向いてない。
ま、向いてないかどうかはともかく、
>>347 は2ちゃんなんか見てる暇があったら、
とっととまともな入門本を読めってこった。
メンバ関数と非メンバ関数とか、参照とかポインタ渡しとか、
こんなもののはC++の基本中の基本。
こんなレベルでいちいち疑問が浮かぶたびに質問されてたら、
スレがいくつあっても足りん。
347=380だろ?なんだよこのバレバレの自演・・・ C++の前に2chやめれ
ドリーマー登場。
>>364 そういう、関数を渡す方法があったんですか。
いくつか本を読んでみても、
「関数渡し」とかでググってみても無かったんで。
ありがとうございます。
今後、
>>347 みたいな質問/ヤシは初心者スレに誘導したら?
むこうでも「入門書嫁」で終わりそうではあるが。
386 :
デフォルトの名無しさん :04/03/14 06:12
>>374 thisを使いたいかどうかっていうよりも、
クラスのメンバ関数にしたいなら、friendをつけない。
外部関数にしたいときは、単にクラスの外で宣言・定義する。
外部関数にしたいけれど、クラスのprivateメンバにアクセスしたいときは、
friendをつけてクラスの中で宣言する。
まあ、引数をポインタや参照で渡すことも含めて、
この辺のことはEffective C++とかにも書いてあるから、
暇だったら読んでみたら? それ以前にCの理解が不十分な気がするけどね。
std::list<int*> value_list; といった形で値のリストを保持しているのですが、これを後ろから5以上 の場合だけ削除し、5未満が出た場合は中断するといった場合 bool isstop = false; std::list<int*>::iterator it; for (it = value_list.end(); it != value_list.begin(); --it) { if (*it >= 5) { delete *it; value_list.erase(it); } else { isstop = true; break; } } if (!isstop) { it = value_list.begin(); delete *it; value_list.erase(it); } これ以外に一度のforですますような方法はありますか? スレ違いでしたら申し訳ないのですが誘導お願いします。
>>387 そのコードはendを逆参照しているし、無効になった反復子をデクリメントしているからまずい。
特に理由がないなら、標準アルゴリズムを使うべし。
>>387 rbegin(), rend()を使って5未満の要素をfind_ifして、そこから後ろを全て消すというのはどう?
スマートじゃないと思ったらやっぱり別の方法があったんですね。 ありがとうございます。調べてみます。
>>387 こんなもんかな。
//ファンクタを用意
#include <functional>
struct comp_val : public std::binary_function<const int*,int,bool> {
bool operator() ( const int* ptr, int val ) { return *ptr < val; }
};
//後ろから検索して初めて見つかった5未満の要素より後ろのものを削除
value_list.erase( std::find_if( value_list.rbegin(), value_list.rend(),
std::bind2nd(comp_val(),5) ).base(), value_list.end() );
>>393 ああ、要素の破棄もするのか。
訂正
//ファンクタを用意
#include <functional>
struct comp_val : public std::binary_function<const int*,int,bool> {
bool operator() ( const int* ptr, int val ) { return *ptr < val; }
};
struct del_ptr : public std::unary_function<int*> {
void operator() ( int* ptr ) { delete ptr; }
};
//後ろから5未満の要素を検索
std::list<int*>::iterator i=std::find_if( value_list.rbegin(), value_list.rend(),
std::bind2nd(comp_val(),5) ).base();
//要素の破棄
std::for_each( i, list_value.end(), del_ptr() );
//リストの削除
value_list.erase( i, value_list.end() );
これから飯食いに行くんで走り書き。
何か不味かったら誰か突っ込んどいてください。
んじゃ。
↑とりあえず自分で直す ×unary_function<int*> ○unary_function<int*,void> ×std::for_each( i, list_value.end(), del_ptr() ); ○std::for_each( i, value_list.end(), del_ptr() ); んじゃ。
>387 純粋に素朴な疑問なんだが、なんで要素が"int *"なの?
わざわざソースまでご呈示頂いてありがとうございます。
こんな風にできるんですねぇ、まだまだ勉強が足りないと思いました。
>>396 実際にはクラスのポインタを入れてるんですが、簡単のためにint*と
いたしました。
あるclassが存在して、 それと全く同じ機能を持つ別名のclassを作りたいのですが、 どういう風にやるのが最も簡単でしょうか。
class SomeClass { ... }; typedef SomeClass AnotherNameClass; あるいは class AnotherNameClass : public SomeClass { // コンストラクタを全部再定義 };
>>398 もっと条件を絞ってもらわないと、質問があまりにも一般的すぎ。
SomeClassの定義如何では全く同じ機能を持つクラスを派生できない場合もあるし。
>>400 マズい。
コピーコンストラクタと代入オペレータは派生されないから。
s/派生/継承/
template <int n> class Foo { ... }; typedef Foo<0> Bar; typedef Foo<1> Hoge; ってのはどう?
意味分からんが、サブクラス作れ、幾らでも作れるぞ。
>>403 ということは、コピーコンストラクタと代入オペレータをprivateで封印している場合は
何も再定義しなくて使えるってことですよね。
でも、なんでコピーコンストラクタと代入オペレータが継承されない仕様になっているのだろうか。
別のクラスだからな。
えー?コピーコンストラクタとかの話は漏れはわからんけど、 派生側でこんすとらくた定義しとかないと class A { public: A(int) {} }; class B : public A {}; … B obj( 5 ); ってコンパイル通らないよね?
class Bの時点で通らん。
>>407 オブジェクト指向は、ベースクラスの仕様がサブクラスの仕様拡張に
影響されないので良いんだよ。何やっても良い。
>>407 コピーコンストラクタと代入オペレータがprivate宣言されているっつーことは、
SomeClassの性質上、それはやっちゃいけないか、そもそもそういう操作があり得ないからと
考えるのが自然だろな。
さもなくば、SomeClassからfriend宣言されている関数またはクラスのみが、
コピーコンストラクタと代入オペレータを呼び出すことができる。
>>409 コンストラクタは継承されない。自分で明示的に呼び出す必要あり。
C言語は俺に聞け!スレが香ばしい(w ほとんどC++を知らないらしいヤシらが勝手な事言ってるよw
禿本のspecial editionって3rdとの違いは何?両方持ってる人がいたら情報キボン
416 :
デフォルトの名無しさん :04/03/15 00:57
>>399-413 みなさんレスありがとうございます。
実はi)派生させる場合とii)typedefする場合を、
それぞれ試したのですがうまくいかなかった為質問しました。
i)派生させる場合
class A {
private:
double val;
public:
A(const double& rval){val = rval;}
};
class B : public A{};
こうすると、
double val = 0;
B b(val);
が通りません。
B(double&)は存在しなくて、B(const B&)しかないと言われます。
ii)typedefする場合
同じように、constructorまわりでerrorを吐きます。
やはり、constructorの再定義は必要なわけですね。
405さんのも使えそうですね。
>>417 #define temp(x) class x {public:x(){} x(int){}};
temp(hoge)
temp(huga)
>>417 typedefなら出来るはずだが、いったいどんなコンパイラ使ってるんだ?
typedef A B した後にBを引数として、 他のclassのconstructorに渡したのですが、 which is of non-aggregate type というerrorが出ます。 compilerはg++です。 何度もすみません。
もすこし、具体的に書きます。 A or Bのconstructorにはdoubleを渡し、 他のclass CのconstructorにBを渡すようにしてあります。 で、B b(1.0)とした後に、 C c(b)とするとcompileが通るのですが、 C c(B(1.0))とすると通らないのです。 Cのmember関数を呼び出すところで、 which is ...のerrorが出ます。 もしかしたらこのmember関数が悪さをしているのかも知れませんが、 cの宣言の違いで結果が変わるため、 constructorあたりが悪いのかと想像しました。
>>421 > C c(B(1.0))とすると通らないのです。
本当にそれが通らないのか?
double x = 1.0;
C c( B(x) );
c.member( ... );
は通らない( 2行目が、B型の引数xを取ってC型を返す関数cの
宣言と見なされる )が。
class CHoge{ int * hoge; private: CHoge::~CHoge( kill()); CHoge::initial( *hoge = new int[1];); CHoge::kill( delete [] hoge;); }; void ugu(CHoge fuga){ fuga.hoge[0] ++; }; void main(){ CHoge piyo; piyo.initial(); piyo.hoge[0] = 10; ugu(piyo); cout << piyo.hoge[0]; } とすると、デストラクターで元のpiyoのhogeもdeleteされてしまいます。 このような場合、どうすればいいのでしょう?
何だそのおもいっきり文法違反なソースは。 >このような場合、どうすればいいのでしょう? どうなって欲しいのか書いてくれないと答えられない。 ポインタメンバのコピーコンストラクタと代入オペレータは 用途にあわせてきちんと実装する必要がある(何も書かなきゃポインタがそのままコピーされるだけ)。 典型的な処理ならば”スマートポインター”と呼ばれるものが使える。 ついでにいっておくと ugu で引数のオブジェクトを変える目的があるなら コピーでなくて参照で渡すべきだぞ。今はコピー先とメンバを共有してるから書き換えられてるけど
>>421 そのBをAにしたらエラーは消えるか、試しましたか?
427 :
デフォルトの名無しさん :04/03/16 13:05
お願いします。 a.cppで const int a; b.cppで extern const int a; とやったのですが、名前解決が出来ない と言われてリンクできません。 constを外すとできます。 どうしてでしょうか?
>>427 a.cppでも
extern const int a;
とする事。C++ではconstは内部リンケージを持っているので
外からは見えない。
C++は「デフォルトで」constは内部リンケージ・・・・と読み替えてくれ。
>>428 >>429 それだけじゃだめだよ。a.hに
const int a = 7;
とでも書いて初期化し、a.cppとb.cppでa.hをインクルード
~~~~~~~
しなければ。
>>430 それは時と場合による。a.cppとb.cppのどちらかでexternを
つけたconstを初期化しておけばこの場合はよい。
a.cpp
extern const int a = 123;
みたいに。
>>430 >a.cppとb.cppでa.hをインクルード
それだとa.obj、b.objの両方に別々にaが確保されるから
externする意味がないじゃん
433 :
デフォルトの名無しさん :04/03/16 13:49
STGゲームなどの弾の管理をlistで行っているのですが削除のときの方法で質問です。 void FlagCheck() { std::list<SHOOT>::iterator S; for(S = shoot.begin(); S != shoot.end(); S++) { if(T->GetFlag()) { shoot.erase(T++); } else ++T; } } とやっています。 SHOOTは弾が物体にあたったときにflagがtureになるようなクラスです。 一応今は問題なく動いているのですが作るときに色々試した結果たまたま動いただけで あまり理解ができていません。 shoot.erase(T++)をerase(++T)にしたりshoot.erase(T);T++;にするとエラーになってしまいます。 前者は無論理由はわかるのですが後者の理由がよくわかりません。 上の関数に欠点がないか、それとshoot.erase(T);T++;がエラーになってしまう理由を教えていただけないでしょうか。 よろしくお願いします。
みなさんありがとうございます。 constは定義ですでにextern指定 しないといけないんですね。 ところがMFCのAFXTMPL.hという ファイルの中で extern const TCHAR _afxWnd[]; と宣言されていて、これの定義は WINCORE.cppのなかで const TCHAR _afxWnd[] = AFX_WND; とされていて、定義のほうにexternが ついてないのですがこれはどうして でしょうか? なんかわけがわからなくなってきました(TT
>>433 shoot.erase(T++)の実行順序は、
1. Tの値を引数として保存
2. T++を実行
3. 保存された引数をshoot.eraseに渡す(この結果旧Tの指していた要素は消滅する)
だよ。
これがshoot.erase(T); T++;になると:
1. Tの値を引数としてshoot.eraseを実行し、Tの要素が消滅しているため無効になる
2. 無効になってしまったTに対してT++を実行するのは駄目
>>435 なるほど。「保存」ですか。
ひとつ賢くなりました。
ありがとうございました!
>>433 STGなんて作ったことないので想像でしかないけど、
弾なんて生成と破棄が激しそうだからstd::listは
パフォーマンス悪くない?
SHOOT型オブジェクトを配列で用意しておいて、
SHOOT型内に次SHOOT型オブジェクトへのポインタ
とか持たせた埋め込みタイプのリンクリストで
連結したほうが良いような気がするけど。
あ、Allocatorいじってんなら話は別だけど。
まずは正しく作れ。それからプロファイラなどで調べて必要な部分だけ最適化せよ
>>422 通らないのは、c.member()のところです。
>>426 試しましたが、駄目でした。
そうすると他の所の記述が悪いせいでしょうか。
ただ、
C c(B(1.0));
とすると駄目だったのに、
C c = C(B(1.0));
という風に書き換えると走るようになりました。
これは、実質的に同じ表現ではないのですか?
このようにすると、c.member()も通るようになりました。
結論としては、typedefでは駄目なのでしょうか。
>>398 は質問に関する情報を一旦まとめて欲しいなあ。
>>441 まとめます。さらにいくつか試したのも書きます。
■目的■
class Aと全く同じ機能を持ったclass Bを作りたい。
(性質は一緒だが、実世界で概念の異なる物を表現したいため。)
■方法■
一番簡単な方法として、typedef A B;によって、Bを扱えるようにした。
■結果■ (実際にはもう少し複雑なclassを扱っていますが、 内容をかなり省略して書きます。) Cというclassのconstructorに、引数としてBを渡した。 C(const B& rb) { b = new B(rb);} ここで、A(or B)のconstructorはA(const double& rval){ val = rval;} という単純なものである。 copy constructorは、A(const A& rA){ val = rA.val;}である。 また、Cのmember関数としてC::func()を用意した。 このとき、main()の中で、 C c(B(1.0)); c.func(); という記述を行うと、二行目で error: request for member `func' in `c(A)', which is of non-aggregate type `C ()(A)' と出る。(あくまで簡略して書いています。) 1行目は何も怒られない。 そこで、c.func();をcomment outして再compileさせると、 compileは通った。(OS Xのg++です。明日、他の環境も試してみます。) ただし、gdbでデバッグしてやると、 この1行目は何故か読み込まれていなかった。 また、先のをさらに書き換えて、 B b(1.0); C c(b); c.func; としてやるとcompileは通り、 動作も期待通りのものであった。
■結論■ 分かりません。 ■附記■ もっとも単純な構成でtypedefが機能するかを調べるために、 以下のcodeをcompileしたところ問題は生じなかった。 ここに貼り付けると長くなるのでやめるが、 自分で書いた他のcodeで同様のtypedefを行った場合、 先に書いたerrorが生じた。 #include <iostream> using namespace std; class A { private: double val; public: A(const double& rval) : val(rval){;} A(const A& rA) : val(rA.val){;} ~A(){;} A& operator=(const A& rA){val = rA.val;} void print_val(){cout << val << endl;} }; typedef A B;
class C { private: B* b; public: C(const B& rB){b = new B(rB);} C(const C& rC){b = new B(*(rC.b));} ~C(){delete b;} C& operator=(const C& rC){delete b; b = new B(*(rC.b));} void print_val(){b->print_val();} }; int main(){ C c(A(0.1)); C c(B(0.1)); c.print_val(); return 0; } 長文スマソ。
それか、 C c = C(B(1.0); c.func(); でも大丈夫でした。
まこてんの g++ ってバージョンいくつだっけ?
>>447 3.3使ってます。
g++の2.95.2、3.1も試しましたが、
両方とも同様のerrorを吐いています。
念のため、明日はLinuxでやってみるつもりです。
>>444-445 どうして代入演算子のオーバーロードで*thisを返してないのか
わからん。
#include <iostream>
class A {
double val;
public:
A(const double& rval) : val(rval) {}
A(const A& rA) : val(rA.val) {}
A& operator=(const A& rA) {
val = rA.val;
return *this;
}
void print_val() { std::cout << val << std::endl; }
};
typedef A B;
class C {
B* b;
public: C(const B& rB) : b(new B(rB)) {} C(const C& rC) : b(new B(*rC.b)) {} ~C() { delete b; } C& operator=(const C& rC) { delete b; b = new B(*(rC.b)); return *this; } void print_val() { b->print_val(); } }; int main() { C c1(A(0.1)); C c2(B(0.1)); c1.print_val(); c2.print_val(); }
実は C c(B(1.0)); が関数宣言とみなされてるとか。 …と、Effective STL P34 を見てちょぃっと思ってみるテスト。
>434 const 整数型 はC++では基本的に「定数」だから それよりもグローバル変数を使うな。素直に共通ヘッダを作るべし。 どうしてもヘッダファイルを作りたくないなら、まだマシな関数にしろ。
453 :
デフォルトの名無しさん :04/03/16 21:41
class A; void Test(A *a); みたいな関数をツクって それでAをリストなりベクトルなりで管理し、イテレータで操作した場合 Test(&(*q)); // qはイテレータ みたいなやり方ってスマートじゃないですかね。見た目からして…
> error: request for member `func' in `c(A)', which is of non-aggregate type `C ()(A)' おもいっきり、関数として認識されてんじゃねーか。 いいかげんに気付けよ。 C c(A(1.0)); // 1.0で初期化した class A の一時オブジェクトで class C のローカル変数 c を初期化して定義 C c(A(x)); // class C を戻り値とし、 class A の引数を一つ(仮引数名 x で)受け取る関数 c を宣言
>>453 Test(A* a)にヌルを渡すことが無いなら、Test(A& a)のほうがいいかも。
漏れはそもそも > A(const double& rval) が気に食わん。 double程度に、なぜ参照を使うかなぁ。 で A(1.0) なんて書いても、そりゃおかしいんじゃねーの? だって、定数のアドレスを求めようとしてるじゃんかよ。
>>456 上半分は同意.
下半分はconst &をリテラルで初期化したときの挙動を理解していらっしゃらないだけかと.
・・・と思ったけど,Exceptional C++引っ張り出してきて項目46を 読み返してみると,上半分も場合によりけりなのかな? ちょっと混乱してきた.教えて,エロい人!!
ずびばぜん・・・↑のレスは私(457)です.
>>458 最適化でインラインになっちゃえば同じという説も。
俺はそれより
>>356 も言ってるようなoperator+を外に出す方が課題。
どうしても継承したり複雑になってくるとoperator+を外に出したときに問題が出てくる。
部分特殊化が出来ないとoperator+の引数が曖昧になってあらゆる+を奪っちゃったりとか。
>>454 ,456,457
レスどうもです。
そうすると、明示的に書くしかないということですね。
compilerに関数として認識させないように。
typedefは悪くない、と。
462 :
デフォルトの名無しさん :04/03/17 06:45
C c = B(1,0) じゃだめなのか?
, じゃだめだろうなぁー
>>456 プリミティブ型は値渡しが普通っていうのはわかるが、
昨今の32bit環境の場合は
sizeof(int) < sizeof(double)
が普通なわけで。
doubleの場合は参照渡しの方が良くない?
>>464 sizeof(int) と 値渡し/参照渡し の間に何の関係が??
どっちかってとsizeof(double*) < doubleのほうが関係あると思うがな。
const 参照に定数(リテラル)を渡せるのは C++ の仕様なんだけどな。 まぁ、それはともかく、わざわざ参照を使う理由が分からないのは同意。
ちなみにboost::call_traits<T>::param_typeの実装を見てみると is_arithmetic<T> == true && sizeof(T) <= sizeof(void*)のときは値渡しで それ以外なら参照渡しという実装だった.@1.31.0 (もちろんpointer渡しはpointer渡しで)
398が抱えてる問題って、Effective STLの6項にあった問題と同じかな?
ありゃスマン、既出だったか
472 :
デフォルトの名無しさん :04/03/17 21:15
お願いします。 C++というかC標準ライブラリの関数(strcpyとかatoiとか...)の 使い方ってみなさんどうして学習したんですか? C++標準ライブラリのリファレンスってよくありますが、Cのって 見かけないんですが... スレ違いかも知れないのですが宜しくおながいします。
info libc
help
俺もヘルプ
みなさんどうもありがとう。 いろいろあるんですね。 めちゃくちゃ参考になりました。。。
>>472 てかK&Rの付録がまとまってて非常に良いと思われ
LSI-C試食版のライブラリリファレンスにお世話になりました。 Vzで、常に開いてたような気がするなあ。
関数の宣言をするところで void buy()とint buy() voidとintの違いってなんですか? よくわからないです。
釣や領収書を期待するならば int buy()
返り血を浴びたいなら int buy()
釣りはいらねぇぜなら void buy()
戻り値がを返すならint、他ならvoidってことしょうか? 全部intなら問題ないってことですか?
返り値とは何かを調べてきたら?
それはどんな関数かによる。 商品とお金を渡しておつりが欲しいなら戻り値を考慮すべきだし、 関数が成功したか否かが欲しいならboolだし、っていうかC++の 質問じゃないじゃん。
いろいろ試してみます。 ありがとうございました。 C++の本を見ながら試していたので、ここのスレでいいのかとおもいました。
今更なんだけど、 -- aaa.h -- #include "bbb.h" class A { B bbbb; }; -- bbb.h -- #include "aaa.h" class B { A aaaa; }; これだと例えばbbb.h側でクラスAが定義されていないとか認識されちゃうんだけど、 どうしたらいいでせう。#ifndef・#define〜#endifでは囲ってます。
>>490 認識以前に、もしできても無限に大きな構造体にする気ですか?
ポインタや参照でなら、前方宣言
class B; // これ
class A {
B * bbb;
};
とか、まとめて
class A {
class B * bbb;
};
ならできるが。
>>491 あ、そうか。確かに無限大サイズになってまうですね。なるほど。
・・・それで片方だけポインタ使っとけば問題ないかなと思って
↓こんなの試してみたんだけどエラーでてしまいました。
-- aaa.h --
#include "bbb.h"
class B;
class A {
B *bbbb;
};
-- bbb.h --
#include "aaa.h"
class B : public A { // Aは定義されていない
};
これも同じような問題あるですか?
あ、いや。↑のはコンパイル通りますた。無問題ですた。スマソ。
>>491 どうもThanXです〜。
>>493 bbb.h は class A の宣言の後にインクルードすべし。
>>494 あれやっぱ動かないと思ってたらincludeの位置が問題だったか。
ありがd
ただ、class A内のB型ポインタからclass Bの適当なメンバにアクセスを
させようとした途端、class AからはBが見えないため、
また未定義のエラーが出てきてしまいますね。
クラス間の相互アクセスはどうがんばってもできないのでせうか。
>>495 -- aaa.h --
class B;
class A {
B *bbbb;
void hoge();
}
-- bbb.h --
#include "aaa.h"
class B {
A *aaaa;
};
-- aaa.cpp --
#include "aaa.h"
#include "bbb.h" // class Bを実際に使うのに必要
void A::hoge()
{
// bbbb->aaaaが使える
}
>>496 そっか、そうすれば可能なのか。かなり勉強になったよ。ありがとう!
498 :
デフォルトの名無しさん :04/03/19 16:14
おねがいします。 コンストラクタは明示的に呼べないのでしょうか? 例えば今 class CTest{ public: int m_nData; CTest():m_nData(0){}; CTest(int n){m_nData=n;} void Init(int n); }; というクラスがあったとして メンバ関数Init()を void CTest::Init(int n){ CTest::CTest(n); } と実装してもちゃんとnが設定されません。 int main() { CTest a; a.Init(5); printf("%d\n",a.m_nData);// ←0のまま } なんででしょう。。。
>>498 >コンストラクタは明示的に呼べないのでしょうか?
呼べません。
Initでコンストラクタを呼ぶ代わりに、
Initで実際の初期化をして、コンストラクタでInitを呼ぶのがいいでしょう。
>>499 ありがとうございます。そうしますです。。。
>>500 ちなみにコンストラクタを明示的に呼ぶとどうなるかと
言うと、そのコンストラクタで一時オブジェクトが作成され、
一時オブジェクトが不要になった時点で削除されるから。
*thisにその一時オブジェクトを代入するか、placement new
を使えばできない事もないが、お勧めしない。
>>498 質問の回答じゃないけど
>CTest():m_nData(0){};
>CTest(int n){m_nData=n;}
これって
CTest(int n = 0): m_nData(n) {}
でいいんじゃないかな。
コンストラクタを明示的に呼び出すとカタストロフィ。 #include <iostream> class A { int* p; public: A(int i = 0) : p(new int[i]) { std::cout << "Ctor(" << i << ")\n"; } ~A() { std::cout << std::hex << p << "\n"; delete p; std::cout << "Dtor\n"; } void Init(int i = 0) { delete p; *this = A(i); std::cout << "Init(" << i << ")\n"; } }; int main() { A a(10); a.Init(5); }
>>503 それはまともなoperator=を実装していないのが悪いんじゃないか?
this->CTest::CTest(n)で呼べたりしない?
>>504 しかしこれでもアカン。危険すぎ。
#include <iostream>
class A {
int* p;
public:
A(int i = 0) : p(new int[i]) { std::cout << "Ctor(" << i << ")\n"; }
~A() { std::cout << std::hex << p << "\n"; delete p; std::cout << "Dtor\n"; }
void Init(int i = 0) { *this = A(i); std::cout << "Init(" << i << ")\n"; }
A& operator=(const A& ca) {
delete p;
p = ca.p;
return *this;
}
};
int main()
{
A a(10);
a.Init(5);
}
>>506 設計がおかしい。それだとまともにコピーできない。
class A {
int *p;
std::size_t size;
public:
A(int i = 0) : p(new int[i]) {}
~A() {delete []p;}
A &operator=(const A &ca) {
idelete []p; p = new int[ca.size]; std::copy(ca.p, ca.p+ca.size, p); return *this;
}
void Init(int i = 0) {*this = A(i);}
};
これで(例外安全は別にして)問題ないはずだが?
>>507 ありがd。やはり明示的にコンストラクタを呼び出すのはやめます。。。
>>507 横やりスマソ。
A(int i = 0) : p(new int[i]), size(i) {}
ですよね。
>>508 いや、operaotor= を正しく書けば明示的にコンストラクタを
呼び出しても良いという例かと。この場合は。
スルーかよぅ this->CTest::CTest(n)だと 一時オブジェクトじゃなくちゃんと呼ばれてる見たいなんだが。 でも仮想関数が絡むとらえらい事なるからどっちにしろ使えねーなぁ。
>>512 void CTest::Init(int n)
{
this->CTest::CTest(n);
}
よ?
VC7.1では通ったけど、他では通らんのかね?
>>513 取り敢えずMinGW(gcc3.3.3)ではエラー。
今標準で該当部分を探している所。
#include <iostream> using namespace std; int main() { int num1, sum=0; cout << "何個の数字の和を求めますか?\n"; cin >> num1; if(num1 >= 1 && num1 <= 10){ cout << "数値を" << num1 << "個入力してください。\n"; int pok[num1-1]; for(int i=0; i<=num1-1; i++){ cin >> pok[i]; sum = sum + pok[i]; } cout << "合計値は" << sum << "です。\n"; } else cout << "数値が正しくありません\n"; return 0; } と入力して、ユーザーが指定した数の和を求めようと思うのだが pok[num1]のところで「サイズを指定してください」とエラーがでます。 cin >> num1 で入力されたサイズを作りたい場合はどうすればよいのですか?
>>516 配列変数のサイズはコンパイル時に確定していなければならない。
int pok[num1-1]; ではなく
std::vector<int> pok(num1); だな。(要 #include <vector>)
あとnum1-1は一個少なく確保されてメモリ破壊ネタだね。
int pok[num1-1]; のところ勘違いしてました…… std::bector<int〜〜 とやるのですね。 どうもありがとうございます。
なぜかgccだと通るな $ gcc test.c && ./a size:100 400 #include <stdio.h> int main() { int i; scanf("size:%d", &i); int arr[i]; printf("%d\n", sizeof(arr)); return 0; }
>>519 現行のC++規格的には通らないが、C99では通るしな。
>>497 B を操作する inline 関数を実装したいときには、
A の宣言部の直後に include する。
朝このスレを見て伸びてないとガックリする。
#include <iostream.h> class Book{ string name; int thicness; // mm string color; public: Book(string,int,string); }; Book :: Book(string r_name,int r_thicness,string r_color){ name = r_name; thicness = r_thicness; color = r_color; cout<<name<<"が作成されました。"<<endl; } int main(void){ Book mine[16]("ある本",20,"青"); // エラーになる getchar(); return 0; } 上の様に、オブジェクト配列にコンストラクターを適用するにはどうすればいいんでしょうか? 『{}』を使ってみたりもしましたがよくわかりませんでした。わかる方は、ご教授お願いします。
>523 朝だからしょうがない。
#include <vector> std::vector< Book > mine( 16 , Book("ある本",20,"青") ); あとは、余計かもしれないけど。 ×<iostream.h> → ○<iostream> で名前空間指定しる。 コンストラクタでは初期化リストを使え。 #include <string> #include <cstdio> が足りない。
>>524 new を使ってもできそう。
ただ delete[] するのが面倒ですが。
#include <iostream> // std::cout, std::endl
#include <string> // std::string
#include <cstdio> // getchar()
using namespace std;
class Book {
string name;
int thicness; // mm
string color;
public:
Book(string r_name, int r_thicness, string r_color)
: name(r_name), thicness(r_thicness), color(r_color)
{ cout << name << "が作成されました." << endl; }
};
int main()
{
Book* mine = new Book[16]("ある本", 20, "青");
getchar();
delete[] mine;
return 0;
}
528 :
デフォルトの名無しさん :04/03/20 13:45
g++ ではできたよ。環境依存?
g++ の拡張機能だろ。
531 :
デフォルトの名無しさん :04/03/20 13:49
>>524 コンストラクタは呼ばれるが、引数を与えることはできない。
>>530 その通りみたいですね。
ISO/IEC 14882:1998 にも
void* operator new(std::size_t) throw(std::bad_alloc);
void* operator new[](std::size_t) throw(std::bad_alloc);
しか載ってませんでした。
-pedanticオプションつけたらコンパイルできなかったし。
一応補足。 本当に配列の要素をコンストラクタで初期化したい場合は初期化リストで明示的にやるしかない。 Book mine[2] = { Book("Book",20,"Blue"), Book("Book",20,"Blue") }; で、単に何らかの値で初期化しておきたい場合には、デフォルトコンストラクタを使うこともできる。 配列の初期化に初期化子を用いない場合、デフォルトコンストラクタがその初期化に用いられる。 class Book ではユーザ定義のコンストラクタが存在するため、デフォルトコンストラクタも明示的に 定義する必要がある。
#include <string> #include <iostream> using namespace std; class Book { string name; int thickness; // mm string color; public: Book(string,int,string); Book(); // default constructor ~Book(); }; Book::Book(string r_name,int r_thickness,string r_color):name(r_name),thickness(r_thickness),color(r_color) { cout << "(\"" << name << "\"," << thickness << ",\"" << color << "\") is constructing" << endl; } Book::Book():name("A book"),thickness(20),color("Blue") { cout << "(\"" << name << "\"," << thickness << ",\"" << color << "\") is constructing" << endl; } Book::~Book() { cout << name << " is destructing" << endl; } int main(void) { Book mine[2]={ Book("A Book",20,"Blue"), Book("A Book",20,"Blue") }; Book mine2[3]; return 0; }
>>532 > その通りみたいですね。
> ISO/IEC 14882:1998 にも
> void* operator new(std::size_t) throw(std::bad_alloc);
> void* operator new[](std::size_t) throw(std::bad_alloc);
> しか載ってませんでした。
それは allocation function の話であって、new expression とはまた別の話だと思われ。
依然として↓は OK なわけで。
Book* = new Book("A book", 20, "Blue");
長いんでコピペしないけど、5.3.4 New の 15 だと思う。
グローバル関数版のgetline()はどのヘッダに含まれますか?
>>538 <iostream>かと思ってたました
thanks alot !!
>>539 ちょっと待て。
istream& getline(istream& strm, string& str)
の事だよな。念のため。
>>540 第3引数にchar型のパラメータがあったかもしれないすが・・
ちなみに、リターン値の参照は第1引数と同じ参照ですか?
>>541 istream& getline(istream& strm, string& str, char delim)
というのもある。
参照は同じなので、getline(cin, str) >> ss; なんて書き方も
できる。
544 :
デフォルトの名無しさん :04/03/21 16:46
リンクリストについての質問なのですが、 class ABC{ public: int data; void func(); ABC *next; //最後の場合は自分をさす }; な感じの単方向リンクリストで最初から最後まで回すときなんですが ABC *lp; while(lp->next != lp) { lp->func(); lp = lp->next; } lp->func(); のように現在使ってる本に書かれていました。 上のように簡単な処理ならいいのですがもう少し複雑になったときに whileを終えたあとのリスト最後の要素のlp->func();の部分がスマートじゃありません。 何かいい方法はあるでしょうか? while(1) { lp->func(); if(lp->next == lp) break; lp = lp->next; } というのは考え付いたのですが何か不都合とかは起きてしまいますか? どなたかアドバイスよろしくお願いします。
>> 最後の場合は自分をさす 最後の場合はNULLじゃね?
あと、見た目をスマートにしたかったら、 リストとイテレータに分けるべきだろうね
>>545 その本では自分を指すようにしてました。
NULLでもいいのですが同じかなァと思いまして。
>>546 質問では宣言とか余分なものが入って長くなっちゃうので
イテレータを入れてませんが実際には使ってます。
> イテレータを入れてませんが実際には使ってます。 イテレータって何のことを言ってるかわかってるのか? で、 ABC* lp; do{ ABC& current = *lp; lp = lp->next; current.func(); } while( );
>>547 > その本では自分を指すようにしてました。
マジか ?
その本の名前プリーズ。
>>547 リンク手繰っていくときにバグがあると
自分自身をポイントすると無限ループに、
NULLならエラーでとまってくれるので
どっちでもいいならNULLにしといたほうがいいよ。
デバッガでも終端であることを認識しやすいし。
あとどちらが一般的かといえばNULLの方。
>>548 あ、ちょいと勘違いしてました。
すいません…
>>549 C言語アルゴリズム徹底入門 柏原正三著
の「動的な双方向リンクリスト」の項です。
>>550 なるほど。ありがとうございます。
NULLで行きます。
>>550 て言うか、自分を指す方になんかメリットあるのかなぁ。
俺は、初めて聞いたよ。
>>550 >NULLならエラーでとまってくれるので
そんな保障は何処にもないが?
純粋にどちらが安全か、という意味でいうなら
自分自身を指している方が安全。
ただループするだけであって、未定義動作をするわけではない。
>>554 変なところに突っ込むね。
エラーでとまってくれない環境があるなら教えてくれ。
その環境で開発するときには注意するよ。
> そんな保障は何処にもないが? 「NULLなら止まってくれる環境がたくさんあるので」 なら満足してくれるかい?
おまいら釣りにひっかからないでください
釣りではなく、こうしてそこそこ展開させるためのネタ投下では。
便乗レスで申し訳ありませんが
>>548 さんの
ABC* lp;
do{ ABC& current = *lp; lp = lp->next; current.func(); } while( );
の意味が理解できません。
ABC& currentというのはどのようなものなのでしょうか
>>559 参照型、この場合は lp が指すオブジェクトのエイリアスと
なる。lp = lp->next として lp の値が変わっても、参照型は
変化しない。
別にここを
ABC* currentp = lp; lp = lp->next; currentp->func();
と書いてもいい。これなら理解しやすいだろう。
ヘッダを特定のnamespaceに閉じ込めることはできますが、 リンクされるライブラリの方を特定のnamespaceの中に入れるには どうしたらいいのでしょうか? 具体的な問題は、 「namespace A」に置かれるクラスとライブラリa.hとa.lib、 a.hとa.libをリンクして作られるライブラリb.hとb.lib、があり、 このb.hとb.libを、namespace Aで作られるライブラリCでも利用したいということです。 DLLであれば、それぞれスタティックリンクされるため、このような問題は起きませんが、 スタティックリンクだと、ライブラリCのビルドモデルが変わったり、 一部の仕様が変わると問題が起きます。 構造的にはこのような感じにしたいのです。 namespace A{ ファイルアクセスクラス(b.libを作った時とは変更されている) namespace B{ namespace A{ ファイルアクセスクラス } } } 「ファイルアクセスクラス」を同じファイルでも別の実体としてリンクしたい。
>>561 いみわからん。
特に、
> リンクされるライブラリの方を特定のnamespaceの中に入れる
> ビルドモデルが変わったり
> 「namespace A」に置かれるクラスとライブラリ
> namespace B{
> 同じファイル
> 別の実体としてリンク
563 :
デフォルトの名無しさん : :04/03/21 19:09
new のオーバーロードして メモリ確保時のファイル、行番号を 管理できるようにするものを作っているのですが、 #include <new> void* operator new( size_t size , const char *file , unsigned line ); とnewをオーバーロードして 呼び出し側で char hoge = new( _FILE_ , __LINE__ )char; と書いてコンパイルしたところ 下のようなワーニングメッセージが出てしまいます。 warning C4291: 'void *__cdecl operator new(unsigned int,const char *,unsigned int)' : 初期化コードが例外をスローすると、'new' 演算子を使用しているとメモリを解放しません。 これのなにがまずいのでしょうか?
>>562 すみません。
まず、namespace Aで作られる大型ライブラリCがありまして、
そのライブラリCの一部のファイルを利用したBというライブラリを作ったところ、
このライブラリBを、元の大型ライブラリCでも利用したいということになったのです。
>>563 operator delete が定義してないからだろ。
>544 最後のnextにNULLを入れれば while(lp != NULL) { lp->func(); lp = lp->next; } でいーんじゃない? 最後のリンクに自分を入れるから余分なものが必要になっちゃってるのでは…?
>>563 Effective C++の第10項をよく読んでみよう。
>>555 > エラーでとまってくれない環境があるなら教えてくれ。
GBA とかドリームキャストとか。あと組み込み系も TLB なかったり、
アドレス 0 に ROM がマッピングされてたりするので、読み出しても
ふつーにデータが返ってきたりする。(書き込みは無視される)
でも NULL 入れとけというのは同意だけど。多くの環境だとそれで落ちるし、
実機上ではダメでもエミュレータでならトラップ掛けられる場合も多い。
>>554 > ただループするだけであって、未定義動作をするわけではない。
いずれにしても、リリースする段階で残っていたらアウトっつー類のバグだ。
テスト段階で検出しないとマズい。
>>566 >最後のリンクに自分を入れるから余分なものが必要になっちゃってるのでは…?
それでは比較の操作が1回余分に発生する。
>>568 >テスト段階で検出しないとマズい。
未定義である以上、実行時の結果だけでバグでないと
保障することはできない。
テストの時、たまたま予想通りの動作をしていたらどうする?
ウワァァァァァァヽ(`Д´)ノァァァァァァン! C++の話題にしてくれよ!実装依存の話は聞きたくない!
このスレにはGBAとかドリームキャストとか組み込み系のプログラマが多い。 それらの人たちにとっても意味のある議論をしなければならない。 それが分からない厨房は帰れ。
>それでは比較の操作が1回余分に発生する。 確かにそうだな… というかよくそんなレスを思いついたものだ
>>571 それはあなたの脳内だけに留めてください。お願いです。
>>572 俺もそう思った。確かに間違ってはいないが。
574 :
デフォルトの名無しさん :04/03/21 20:17
>>570 NULLの安全性(若しくは有用性?)の話は十分にgenericな話題
空想論に走るのを防止する目的で要求しだい実例を挙げているだけ
そこはスルーしててもちゃんと通じる話だよ?
これらの話を理解したうえで、NULLにする、しないを選択すればいいんじゃないかなあ 「本に書いてあったから」なんて理由で使うのはどうかと思う
つか全然C++じゃないな。むしろCだ。
C++ならNULLではなく0で議論して欲しいナァ・・・・ まあどちらでも同じなんだけど。
>>576 578
だってもともとが「C言語アルゴリズム徹底入門」から出た質問だもの
端からスレ違いだって
580 :
デフォルトの名無しさん :04/03/21 20:46
NULLを使わず0を使う方針をとった場合、ドキュメント中の「ヌルポインタの値」はどう書きますか? ポインタを返す関数の仕様を「〜の場合は0を返す」と書くことになるんでしょうか?
>>580 素直にNULLでいいじゃん。そこで「0でも同じなんですけど!」
と反論しても空しいし。
>>580 俺だったら
>>580 さんのようにすると思う。と言うかしている。
大抵のC++処理系は #define NULL 0 としてあるが、そうで
ない処理系もあるだろうから、移植性を重視するならNULL
は撤廃した方がいいよ。
>>582 C++ではNULLは0って規格で決まってるんじゃなかったっけ?
585 :
デフォルトの名無しさん :04/03/21 21:06
>>580 国内では「空ポインタ」と訳すのが標準のはず
>>581 そうすると、例の関数の戻り値をテストするコードはNULLを使うのが正しいと感じます。
関数の仕様にそう書いてあれば、それを読んだユーザーが == NULL でテストするのは自然なことです。
これはNULLを使わないと言う方針に反してしまうのです。
だからといって、ドキュメント中に0じゃぁさすがに伝わりにくいんじゃないか、と思うわけで。
#include <iostream> #include <iomanip> struct X { int a, b; }; int X::*c; int X::*d = 0; template <class T> struct Y { union { T* e; unsigned char* f; }; };
template <class T> inline void dump(T* p) { Y<T> y; y.e = p; for(std::size_t i = 0; i < sizeof(T); i++) { std::cout << std::hex << std::setw(2) << std::setfill('0') << int(*y.f++) << ' '; } std::cout << std::endl; }
int main() { dump(&c); dump(&d); static int X::*c; static int X::*d = 0; dump(&c); dump(&d); return 0; }
587=588=589だが、もまいらの処理系ではどんな結果になる?
>>586 他にも回避策はある。(lp == NULL) で比較するのではなく (!lp)
とすれば。
>>590 MinGW(gcc3.3.3)の実行結果。
ff ff ff ff
ff ff ff ff
ff ff ff ff
ff ff ff ff
VC7.1ではこうなる。 00 00 00 00 ff ff ff ff 00 00 00 00 ff ff ff ff というかメンバへのポインタの値を直接参照してもあまり 意味がないような。
これからCを始めようと考えているんだけど・・・。 いきなりじゃぁ、ちょっと訳解らんw テンプレのサイト回ってきます・・・。
>>596 Cなんですか?C++の間違いじゃないんですか?
>>596 それはいきなりすぎます。
まずはキスから始めた方がよいのではないでしょうか?
はじめての化学兵器
>>597 え?CとC++って、違うんですか?
てっきり、似たようなものだと・・・。
>>598 そっちの「C」じゃ無いってw
C++ は C を強化した言語で、 C++ 的に組んだプログラムは C とは全く違うものになる。 C 的に組んだプログラムは さほど変わらないけどね。
>>601 > え?CとC++って、違うんですか?
> てっきり、似たようなものだと・・・。
似たようなものであり、違うものです。
つーか「似たような」という表現は通常、異なる物同士に対して使う形容なわけで、
この質問はちょいと変ではないかと。
C++の記述はなんか読みにくいので漏れはC的に組んでるがみなさんはC++を使うときいかように?
>>604 Cの記述はなんか読みにくいので漏れはC++的に組んでまつ。
C++初心者で、Cをやった経験がない人なら、C++でいきなり 始める方が良い。Cで一度ポインタに関する変な癖が付いて しまうと、そこから脱却してC++らしい考え方を身に付けるの は骨が折れるぞ。
ポインタの使い方を誤って、メモリが使い物にならなくなることってあるのですか?
あります。気を付けないと火を吹くこともあるので 十分注意してください。説明書にも但し書きがあるはずです。
初心者に妙なこと吹き込むスレはここですか?
Helpみたら「ポインタの 1 つがアドレス 0x00408000 のメモリを壊してしまったようです。どうなっているか調べる方法はありますか。 」というのがありました。 そのアドレスを壊しちゃうと、その場所はもう使えない?? 壊してばかりいると、64Mのメモリが10Mとかになっちゃうのですか…?
>>610 C++の勉強はやめて、Cの勉強しなさい。
あまりいろんなアドレスを壊しちゃうと 次第にOSの使えるメモリが少なくなっていきます。 やりすぎるとWindowsの起動にも支障をきたすようになりますよ。
>>612 >やりすぎるとWindowsの起動にも支障をきたすようになりますよ。
デバイスドライバに関わるプログラムでも組めばそうですが、
普通のアプリを作っている限りにおいては、バッファの不正書込みで
OSの挙動がおかしくなる事はないですが・・・。
WindowsCEやWindows3.xはヤバイかもしれないけど。
HD アクセスを行う処理が変になって、
HD に過負荷をかけて壊してしまうことはあるかもしれない。
>>610 その場合の「壊す」というのは、物理的に壊すのではなく、
そこの値を勝手に変更してしまうことを指す。
いろいろ教えてくださりありがとうございます。 一回再起動すれば元通りになるということでしょうか? 普通にポインタの勉強でいろいろいじってる分には物理的に壊れることないでしょうか? もし壊れることあるなら、試行錯誤できないでう。。。
うそをうそと見抜けない人と ネタにマジレスをする人が集まるスレはここですか?
>>615 それを言うなら昔のDOS環境でのCは今より遙かに危険だったぞ。
ディスプレイに規格外の同期信号が入ると今のディスプレイなら
勝手に阻止してくれるが、昔のはそのままディスプレイから煙を
吹いて逝ってしまう事があったからな。
滅多な事ではハードウェアにダメージを与える事はできないと思わ
れ。但しデバイスドライバを作っている場合は変なコマンドをデバイ
スに送って壊してしまう事があるかもしれない。クロック周波数とか
HDDにコマンドを送るような時。
>>615 ほとんどないから、試行錯誤してヨシ。
そのプログラムの挙動がおかしくなるだけ。
そんな場合はそのプログラムを強制終了すればいいだけ。
場合によっては強制終了が出来なくなる場合もあるが、
ほとんどまれなので、遠慮なくメモリを破壊して
Windowsカーネルのメモリ保護機能を楽しんでいい。
ありがとございます。 心置きなく試行錯誤できます。
620 :
デフォルトの名無しさん :04/03/22 22:25
>>619 まず壊しても誰にも怒られないマシンを持て
びくびくおどおどしてちゃ何も試せないだろ
因みに俺は実用と実験用に別々のマシンを使ってる
氏なれたら困るマシンで怪しいことは一切しない
このスレネタ師が一日中張り付いてるな
ゴキブリとネタ師は1匹見つけたら30匹はいると思え。
623 :
デフォルトの名無しさん :04/03/22 23:20
#include <iostream> #include <cstdlib> #include <ctime> using namespace std; int main() { int nn[4]; srand(time(NULL)); cout << "0〜9の中から4個ランダムに選ぶ" << '\n'; for (int i=0; i<=3; i++){ nn[i] = rand() % 10; cout << nn[i] << ' '; } return 0; } 1〜9までの間からランダムに4個選ぶのを作ったんだけど、0,7,9になる確率が多いようなのは気のせい??
625 :
デフォルトの名無しさん :04/03/22 23:21
Effective C++のオンライン版をこっそり全部見られるところってない?
>>624 ありがとうございます。 前者のを試してみたら、最初の数が常に8になってしまいました。
後者は難しくて理解できないさ。
うーむ・・・
C++ならboost::random使えや。
631 :
デフォルトの名無しさん :04/03/23 00:03
文字列(半角10文字以下・dogなど)を10回入力、アルファベット順に表示させるものですが、これからどう作ればいいですか?読み込みとかが良く分からないです /*読み込み*/ for(tate=0;tate<=kaisu;tate++){ for(yoko=0;yoko<=MAX;yoko++){ gets(moji); moji[tate][yoko]=atoi(moji); } } for(tate=0;tate<kaisu;tate++){ for(yoko=0;yoko<MAX;yoko++){ printf("%s",moji[yoko][tate]); printf("\n"); } } } /*ソート*/ for(i=0;i<kaisu;i++){ for(j=i+1;j<kaisu;j++){ if(moji[i]>moji[j]){ temp=moji[i]; moji[i]=moji[j]; moji[j]=temp; } } } /*表示*/ for(i=0;i<kaisu;i++){ printf("%s\n",moji[i]); } return(0); }
#include <iostream> #include <cstdlib> #include <ctime> using namespace std; int main() { int nn[4]; srand(time(NULL)); cout << "1〜9まで\n"; for (int i=0; i<=3; i++){ nn[i] = 1 + (9.0 * rand() / (RAND_MAX+1.0)); } for (int j=0; j<=3; j++){ nn[j] = 1 + (9.0 * rand() / (RAND_MAX+1.0)); cout << nn[j] << '\n'; } return 0; } 2かいランダムに発生させたら、最初の文字が8じゃなくなりました。
633 :
デフォルトの名無しさん :04/03/23 11:59
お願いします。 例えばある関数からダイアログを表示するとき void foo() { CDialog dlg; dlg.DoModal(); } と書くのと void foo() { CDialog* pDlg=new CDialog(); dlg.DoModal(); delete pDlg; } と書くのとがありますが、どうやって使い分けるのでしょう? また同様にクラス内でも変数として宣言してしまう 場合と、ポインタとして宣言してコンストラクタ等で newする場合がありますが、どう使い分ければいいのでしょうか?
>>633 前者でできるんだったらとりあえずそれでやっとけ。
class hoge{ int* fuga hoge(int i){ new int fuga[i];} ~hoge(){delete [] fuga;} }; int main(){ for(int i = 0; i < 5; i++){ hoge fuga(i); } return 0; } このようにすると、まずhoge(0)と初期化され、 その後hoge(1)..というようにhoge(5)まで初期化されますが、 その際にデストラクターが呼び出されずにメモリリークしますか?
>>635 しない。
(public:が抜けてるけど。)
>>633 漏れが new で作る場合はむしろモードレス
>>633 補足しておく。
>どうやって使い分けるのでしょう?
ダイアログ(変数)の生存期間によって使い分ける。
>>637 が言ってるのもそういうことね。
特定のブロック内だけ(この場合foo()の中)でいいのならば自動変数として確保する。
任意のタイミングで生成・破棄したい場合に new/delete の組を使う。
別に下の例の方でも構わないといえば構わないが、いちいちメモリを確保、解放するのが面倒だし、無駄。
さらに例外のことを考えると自動変数にするのが良い。
>また同様にクラス内でも(以下略)
ポインタにしといてコンストラクタで new する場合ってのはあんまりないんじゃなかろうか。
一応思いつくのはこんな感じ。
1.可変長配列の場合
2.NULL であることに意味がある、NULL を表現する必要がある場合
(この場合、コンストラクタではむしろ NULL 初期化する方が多いかも)
3.(ポインタを通して)1つのインスタンスを共有する可能性がある場合
(単純にコンストラクタで new 使って生成したりしないような気もするが)
結局のところ
>>633 で正解だと思われ。
>>635 fuga の生存期間は for 文の {} の中だけなので、ループが回るたびに、fuga は生成され破棄される。
つか、試してみればいいじゃないか。
ところで、
×hoge(int i){ new int fuga[i];}
○hoge(int i){ fuga = new int[i];}
だよな?
訂正
×結局のところ
>>633 で正解だと思われ。
×結局のところ
>>634 で正解だと思われ。
4.Pimpl イディオム >633 ものすごくオブジェクトのサイズがでかくて、スタックに積むのが不安なとき、とか? そんな糞設計ないと思うが。
>>634-637 -638-640
今帰ってきました。遅れてすみません。
みなさん丁寧にどうもありがとう。
よくわかりました。もっと勉強してきますです。
数が変化するオブジェクトを管理するにはどうやるのがいいでしょうか? 自分で調べた・聞いた結果としましては、 STLはどれも重くて生成・削除が激しいものにはきつい。 このスレを見てたところリスト構造というのがあり、少なくともSTLよりは ずっとイイみたいなので今はこれを使っています。 あとは普通に最大数の配列を用意しておいてフラグなどのtrue/falseで 最初から最後までまわす方法ですが、さすがに要素が多いとキツイかと思ってましたが 某所に「今のPCの性能はいいからいくらでも問題ない」みたいなことがかいてありました。 しかしメモリを節約するに越したことはないですし… 何かいい方法がありましたら教えていただけないでしょうか。 よろしくお願いします。
STLとは何か判ってますか?
>>642 >数が変化するオブジェクトを管理するにはどうやるのがいいでしょうか?
>自分で調べた・聞いた結果としましては、
>STLはどれも重くて生成・削除が激しいものにはきつい。
お前は、オブジェクトという言葉を使うのさえ10年早い。
STLが何故重いのか、どれぐらい重いのかを説明できるか?
646 :
デフォルトの名無しさん :04/03/24 11:09
未来のC++プログラミングは全ての実装をヘッダファイルで行い、 アプリケーション中、ただ一つのmain.cppでは、 コンフィギュレーションの類いを記すだけとなる、 という話は本当ですか?
C++に未来なんてないので嘘です。
>>642 srd::list使えば?
リスト構造ですよ。ちなみにこれ、STLね。
>>648 STLはどれも重くて生成・削除が激しいものにはきつい。
そんなものをすすめるあなたは荒らしですね。
荒らしは死んでください。
全部テンプレートなので循環しても大丈夫ですヨ(w
> ただ一つのmain.cppでは、 > コンフィギュレーションの類いを記すだけとなる コンフィギュレーションもファイルから読み込みますから
C#みたいに1つのファイルに関数の中身記述するのはいやだな。
>>649 は、本気で言ってるのかな?
生成・削除が激しい場合はそもそも動的な確保を頻繁にやらないでしょ。
STL云々より、設計の進め方自体が間違っていると思うのだが。
それをSTLのせいにしたあげく2chで質問をしているって感じですかねw
ひょっとしてstd::vectorなどに、「サイズやインデックス管理が一切必要ない」
という理想を求めてますか?そんな要求はそもそも無茶ですけど。
プログラマは皆それ理解した上でSTLを使っているのですが、
>>649 はそうではないようですね。
C++の限界という奴ですね。失望しました。
>>642 マジレスしとく
>STLはどれも重くて生成・削除が激しいものにはきつい。
何処で誰に聞いたのかは知らないが、十中八九あなたの勘違い/読み間違い。
正しくは、コンテナによっては、アイテムの追加挿入削除にコストがかかるものと
そうでないものとがあるということ。このことは別にSTLのコンテナに限らない。
配列やSTLのvectorは前者の代表で、リスト構造は後者の代表。
なおSTLにもリストは用意されている。
どうやらあなたは基本的な用語や概念の理解が不十分のようです。
もう一度基礎をしっかり勉強することをお勧めします。
そうすれば、とんちんかんな質問をして、あきれられたり煽られたりすることも
なくなるでしょう。
>>655 言語の仕様の問題ではなく各プログラマの使うアルゴリズムの問題だって事に気づかず、
C++のせいにする人は、C++開発力だけでなくプログラミング能力自体が未熟といえます。
STLのコンテナが遅い? ベースとなっているデータ構造をご存じですか?まあそもそも STLのコンテナが保証しているのはO値だけでコンテナの実現 方法までは規定してないけど。 仮にstd::vectorが配列、std::listがポインタ、std::setが赤黒木 だとするとそれに十分見合う速度は出ていると思います。 これでも遅くて使い物にならないのなら一切new/deleteを含む アロケータを使用しない独自のコンテナを自作すべきです。 またはtraditionalなC式のイテレータを持たないデータ構造に するか。その場合配列を除いて<algorithm>は使用不可になっ てしまいますが。
ここは初心者の些細な一言にヒステリックに力いっぱい反論するスレですか?
ちと訂正。 ×std::listがポインタ ○std::listが双方向リスト
おい、ちょっとまておまいら。 649!=642で、649はどうみても荒氏だろ。
STLに関する評価をしているサイトは多々ありますが、 その文章を的確に理解している人は少ないようです。 「STLの主たる目的はメモリリークを回避するためのものであり、 実行パフォーマンスを向上するためのものではない。」 という文章から読者はどのように解釈するでしょうか? STLはパフォーマンスが悪い、等とはどこにも書かれていません。 かといってSTLはパフォーマンスが良いとも書かれていません。 パフォーマンスを向上させる責任はあくまでもプログラマにあります。
663 :
デフォルトの名無しさん :04/03/24 15:07
STLかー。結構がんばってはいるけど普通に遅いよな。 俺の書いたコンテナのコードのほうが20%〜300%速いし。 STLの存在価値は速度ではなくアルゴリズムに疎いショボコーダでも そこそこの質と速度のコードが書けるようになるって事だから 盲信したり拒絶したりするのはどうかと思うよ。
>>663 またまた痛いのが来たな(w
作ったというコンテナは、STLと同じテンプレート(汎用)コンテナなのか?
それとも、特定オブジェクトに最適化して可植性を犠牲にしたコンテナ(あくまで自称)なのか?
>>663 それは言えてる。「盲信したり拒絶したり」しないで、STLの
性能と便利さを天秤にかけた後にプログラムに使用するか
どうか決定すればよいだけの話。
それを言うなら、C++の標準入出力ライブラリなんて、Cの
stdio.hより禿げしく重いし遅いものがたくさんある。速度は
度外視して便利さを追求したものならstd::stringstreamなん
てものもある。これらは継承によって構築されているので
ほとんどインターフェースが共通していて覚えやすい。
STLは継承は使用していないが、コンテナにクラスのポインタ
を入れられるので多態性を表現するのにも使える。
>C++の標準入出力ライブラリなんて、Cのstdio.hより禿げしく重いし遅いものがたくさんある。 STLとiosクラス群は全く別の物です。 同列に論じている時点でどうかと思われます。
標準入出力もテンプレートライブラリで実装すればいいのに。
「STLはダメ」とか言ってる時点で失格です。 自作コンテナ賞賛の時点で失格です。 出直しましょう。 結論から言えば、自作コンテナなどという物は一切必要ありません。 私も駆け出しの頃、メモリ管理を覚える勉強がてら コンテナ(自称)を作ってSTLと競わせて独りよがりな優越感に浸ったりしてました。 結局STLだけで必要十分という結論に達しました。
std::vector が遅いとかいっているやつは、 reserve や insert のことを何も知らず、ただ push_back のみを利用して 評価しているだけのような気がする。
自作コンテナ派は痛いよ、ホントw
>>669 私もそう思います。
ただし、STLのstd::stringは曲者です。
std::string::reserve()の挙動がVC++とgccで異なります。
gccのstd::string::reserve()は恐ろしい事に何もしないみたいです。
つまり、サイズが多目にある事を前提にしたコードを
VC++環境で書くとgccに持っていった時悲惨な目に遭います(泣
>>663 >STLかー。結構がんばってはいるけど普通に遅いよな。
>俺の書いたコンテナのコードのほうが20%〜300%速いし。
STLを盲信したり拒絶したりしないのは評価できるが、300%速くなった時点で、
何か疑問に思うことは無かったのですか?
自分を盲信したり拒絶したりしないほうがいいと思います。
今日はえらくスレレベルが低いな、もともと低いけど。
お目出度い自作コンテナ厨が御来訪でつか?w
早く
>>668 にみたいに卒業しないとな。精進しろよw
以降、STLの効率については Efficient C++ を読んだ上でお願いします。
STLといってもコンパイラや実装によって違うのでは? だれかベンチ取ってないの? 自作コンテナとやらと比べたベンチはあるんでしょ?
えーとつまりSTLではなくリスト構造を自分で作ったほうが 速いということでいいんでしょうか。 自分で作る場合はポインタ配列をnewして NULLをセットすればいいんでしょうか。 動作が安定したら将来的には高速化を考えています。 アセンブラコードで高速化するといいと聞いたのですが アセンブラコードからnewを呼ぶ事も可能ですか? よろしくお願いします。
>>676 悪いことは言わん。その程度の理解しかしてないのならおとなしくSTLを使っとけ。
>>676 >自分で作る場合はポインタ配列をnewしてNULLをセットすればいいんでしょうか。
素だとするととんでもないやっちゃな(w
ひょっとしてリア厨かな?
工房だともうちょい知能が高いような気がする。
コンテナなんて実装すんのつまんねーし面倒くせーよ。馬鹿しかやらねー。 と思っているからSTLを使っています。
>>677 確かに理解の度合いは低いかもしれませんが、
一度決めた方法以外のものを他の人が押し付けるのはよくないと思います。
質問には答えてくれないのでしょうか。
>>676 >えーとつまりSTLではなくリスト構造を自分で作ったほうが
>速いということでいいんでしょうか。
測ってみろ。
>自分で作る場合はポインタ配列をnewして
>NULLをセットすればいいんでしょうか。
違う。
>動作が安定したら将来的には高速化を考えています。
>アセンブラコードで高速化するといいと聞いたのですが
>アセンブラコードからnewを呼ぶ事も可能ですか?
可能だ。
Unko* unko = new Unko[100];ポインタ配列をnewして unko = NULL;NULLをセット >>動作が安定したら しません。
ぎゃー!
>>680 だから、君の理解の度合いで自力でコンテナ実装するのは不可能。
一から勉強しなおすか、とりあえず出来合いのものを利用するしかない。
つか、多分STLも使えないと思う。それこそstd::vectorでひたすらpush_back()
で、やっぱりリア厨か。
>>680 決めてしまったなら思い直せ。言えるのはそれだけだ。
我々は沢村の誕生を見た。
お前らリア厨を馬鹿にしすぎ。 ってか、「リア厨」ってむやみに言うな。
>>ってか、 >>ってか、 >>ってか、
>>684 std::back_inserterとかstd::back_insert_iteratorを(ry
(;´Д`)「STLがうまく使えないや・・・。」 ↓ (心理学用語としての)合理化 ↓ (゚∀゚)「STLは使い物にならないね!」 こういうのは典型的なアフォ。氏ね。
691 :
デフォルトの名無しさん :04/03/24 20:19
>>690 なんだ、その程度のヤシにマジレスしていたのか。我ながら
情けない。
char unum[3]; cin >> unum; cout << unum[5] << '\n'; 入力時に”123456789"って9桁入力しても cout << unum[5] << '\n';で反映されちゃうんですが、これが反映されない方法ってありますか?
>>693 ちょっと待て、一体何がしたいのか教えてくれ…
入力長を制限したいのか、それとも本気でunum[5]を使いたいのか
>>693 #include <iostream>
#include <iomanip>
int main()
{
char unum[3];
std::cin.get(unum, 3);
std::cout << unum << '\n';
}
英数字を3文字しか入力できないようにしたいんです。 ifを使って5文字目が何もなかったら処理をしようかと思ったのに、入力したものが反映されてしまいます。
>>693 OK、おまいはまず'\0'というものを知るべきだ
うーもう一度配列のページ見てきます……
>>693 char unum[3];
って宣言したとき、安全にアクセス可能なのは
unum[4]までよ、しかもunum[4]に書き込みは言語道断
その値も何が入ってるかわかったもんじゃない
つまり、unum[4]はforループかなにかで
「ちょっとオーバーしちゃった。てへへ」な用途にしか使えない。
umin[5]以降のアクセスは超絶的未意義何があっても文句は言えない。
まあつまるところ、普段はunum[0]からunum[3]までにしておけと言うことです。
ぐふっ。一個ずつずれてる… char unum[3]のときumun[n]のnが 0-2 安全にアクセス可能 3 アクセスは可能、書き込み不可、値は不定 4以降 未定義 に修正しておくんなまし
>>699-700 式として見ると、unum[3]は未定義じゃあないかな。unum+3を逆参照していることになる訳だから。
unum+3だけであれば安全だけどね。
あともう一つ。unum+3は「ちょっとオーバーしちゃった。てへへ」な用途以外にも、
イテレータの終端としての重要な役割がある。
702 :
デフォルトの名無しさん :04/03/24 21:46
char unum[3]はアドレスを得ることが可能なだけじゃねーの??
char unum[3]じゃ定義だろうがアホ>俺 unum[3]の間違い
アドレスが有効であることを保証する、だったかなあ つまり char* p = &unum[2]; p++; のとき &p = &unum[3]; を保証する、みたいな
>>702 >>701 に対して書いているのかな?そうだとしたら補足しておく。
>>701 で言いたかったのは、char unum[3];という宣言があったとき、*(unum + 3)のシンタックスシュガー
としてのunum[3]は未定義じゃないか、ということ。[]演算子は、ポインタのインクリメントだけでなく、
逆参照を行うのだから、配列の末尾+1の場合は未定義になると思うのだけど。
sizeof( unum[3] )
char c c ='0' c = '\0' c = 0 全部違う値ですか?
>>707 確実に言える事は c = '0' だけは違うって事かな。
それにしても春厨が出没してからというもの、質問の質が 下がったな。それともいきなりC++から始めたのでCの知識 が足りない奴が増えたのか。 std::cinからの入力はなるべくstd::stringを使ってくれよ。Cの 悪夢に戻りたくねー。
しばらく見ない間に偉くレベルの低いスレになったもんだな おまいらもいい加減放置というものを覚えてくだちい
質問のレベルが低いのは、ネットでフリーのコンパイラをダウン、 入門サイトを渡り歩いてベンキョーしてるやつが増えたからでしょ。 それだけプログラミングの敷居が下がったってこと。 あいてするのが面倒なら、スルーするか、初心者スレに誘導したらいいでしょ。
>>705 違う。
>>700 にレスしたの。
割り込まれるとは思わなかったからレスアンカーは省略した。
なんか偽者が暴れてるみたいで… まずなぜこの質問したかというとこのスレの上の方に STGゲームの弾みたいな生成・削除が激しいものはSTLより リンクリストがいいのでは?と書かれていたからです。 あとはサイトをまわってもたいていはSTLは重いから使わない方がよい(便利ではあるが) とありましたので… なぜあれほどたたかれたのか理由はよくわからないのですが返答よろしくお願いします
STLつかうと一気にメモリーの消費量が10倍に?!
100倍でしょ??
>>714 ログ読んで判らんのなら初心者スレにでも逝けば?
初心者禁止なんですか?
今のマシンでvectorつかったぐらいで重くなるゲームってすごいね
>>714 std::listって知ってるか?
あとリンクリストって何かわかってるか?
>>715 環境によるだろ。
俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力
ランタイムを使用するようにして使っているが、例えばstd::vectorを
使っても使わない時と比べ10Kほどしか増えない。
これはメモリサイズにもそのまま言えると思う。
>>642 vectorで大量に多摩オブジェクト配列を確保しておく。
多摩オブジェクトにメンバ変数に使用・未使用のフラグを入れておく。
新規に多摩が必要になった場合は、
アルゴリズムのupper_bound()で未使用の多摩オブジェクトを探し出して再利用。
使い終わったらフラグを未使用状態にセット。
多摩の同時出現最大数は制限すべきだし、実際制限しないとヤバイ。
>>723 すげえ。ダイナミックリンクしといてファイルサイズもメモリサイズも
増えないとかいってるよ。この人。
C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。 とかいうエラーが出るんだけどこれってどうすればいいのですか?
ネットワークプログラミング相談室以上に殺伐としたスレッドですね。
>>714 STLで生成・削除が激しいから遅いという理由はおかしい
だが、バッドノウハウを吸収したいなら「タスクシステム」で検索してみなさい
「やねうらお」でもいい
>>729 VCスレに行け。
その前にそのエラーでそのままググれ。
リンクリストでも生成・削除が激しいと重くなるよ C++の宿命だからな コンシューマ機でよくやるオブジェクトのサイズを全部同じにしてしまうという荒業もある ただのはいれつ のようだ
>>729 リビルドしてみれ。それでも駄目ならプリコンパイル済ヘッダを使わない設定にする。
>>733 C++じゃなくてOSのメモリマネージャの宿命かと。
そんなわけでプログラマ自身がメモリマネージャに就任しなければならない。
メモリマネージャに就任したPGからの会見コメント
↓
736 :
デフォルトの名無しさん :04/03/24 23:43
>>729 #include "stdafx.h"
後死ね。
一度荒れだすと際限がないな。
>>737 言葉が悪いな。それで教えているつもりか。
まぁヒントぐらいにはなったな。
うむごくろう。
何度も出たネタにマジレスする奴も出てくるから今度からテンプレに入れてくれ
春〜Spring〜♪
----------------- ここから再開 -----------------
744 名前: デフォルトの名無しさん 投稿日: 04/03/25 14:30
同じ関数名を持つ複数のライブラリを扱うにはどうしたらいいのでしょうか?
ライブラリAにもBにもinit()という関数があり、両方使う必要が出てきました。
ヘッダの方はnamespaceに置きましたが、
namespace His_Lib{
#include "his.h"
}
namespace Her_Lib{
#include "her.h"
}
ライブラリをリンクするときにエラーになります。区別するにはどうしたらいいのでしょうか。
745 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 14:39
::で解決した?
746 名前: デフォルトの名無しさん 投稿日: 04/03/25 14:40
>>745 747 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 14:43
どうしようもありません
748 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 14:43
>>744 どっちかのライブラリを変更して再コンパイルすることはできる状況なの?
どっちも変更できなくても、Windows の DLL だとまあ何とかできる。
749 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 15:03
>>748 ソースがあれば変更すればいいのですが、ソースがないのです。
スタティックリンクするライブラリだけなので・・・
750 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 15:10
>749
>748はWinの場合なら、
それぞれ別のバイナリ(DLL)としてリンクして、
GetProcAddressでアドレス取得して使えってことでしょ
751 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 15:36
>744
まさに、グローバル名前空間を浸食する二つのライブラリが衝突した瞬間ですな。
namespace はこうならないように予防するためのもので、対処するためのものじゃないです。
で、多重定義になる以上、
どうやっても同じバイナリに二つのライブラリを入れることは無理かと。
752 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 15:55
スタティックか。じゃあムリだね。
オブジェクトファイルを取り出してバイナリエディットで関数名変える
ぐらいしか手はないかと。
753 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 16:28
C++ にはある文字 ch がそのロケールにおける数字かどうか判別する方法として、
std::isdigit テンプレート関数がありますが、 ch をそのロケールで対応する
数値に変換する関数というのはあるのでしょうか?
std::locale lc;
if( std::isdigit( ch, lc ) )
{
// 数字に変換するには?
}
754 名前: 753 [sage] 投稿日: 04/03/25 16:52
最初は、純粋に '0' (wchar_t なら L'0' )を引けばいいかなーと
思っていたのですが、
std::locale lc( "japanese");
isdigit( L'1', lc ) // 全角1
が true を返すので、どうしたもんかーとか思っているわけです。
755 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 17:09
>>753 std::num_putかな?
ようわからん。
756 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 17:12
std::num_get?
757 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 17:30
>>750 全然違う
758 名前: 753 [sage] 投稿日: 04/03/25 18:02
>>755 >>756 num_get は、いちいち、stream を作成しないといけない上に、
あろうことか VC++7.1 では wchar_t の num_get を用いると、
例外で落ちます。
また、数字1文字だけを数値に変換したいのに、わざわざ num_get を使うのも、
気が引けます。
759 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 19:17
>>758 一文字だけでいいのなら
ch-'0';
ただしロケールとかは完全に無視してるけど。
複数の文字なら。
int result;std::string buf;
std::istringstream(buf) >> result;
760 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 19:34
>>759 ふりだしにもどんな
761 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 20:46
>>744 それぞれのスタティックライブラリをラップするDLLを自作しれ
762 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 21:03
class A {
public:
A(const char* name) : name_(name) {}
~A(){}
private:
const char* name_;
};
class B {
public:
B() {
a.insert(new A("aaa"));
a.insert(new A("bbb"));
}
~B(){}
private:
std::vector<A*> a;
};
~B(){}でaの要素を開放する必要ありますか?
763 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 21:11
だまって boost::shared_ptr 使っとけ。
要素が文字列だけなら string でいいけど。
つーか vector に一引数の insert はないんだが
764 名前: 762 [sage] 投稿日: 04/03/25 21:51
>>763 レスありがd。使ったことないけど、チャレンジしてみます。
a.push_back(new A("hoge"));のまちがいです^^;
765 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 22:20
>>762 ある
766 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/25 23:05
そもそもvector<A>じゃだめなの?
767 名前: デフォルトの名無しさん 投稿日: 04/03/26 00:07
> また、テンプレートライブラリ(STL含む)に関する質問は
> 専用の別スレへどうぞ。
> 過去スレ、関連スレ、関連リンクなどはこちら
>>2-13
768 名前: 762 [sage] 投稿日: 04/03/26 00:18
勉強のためゆくゆくはAbstractFactoryとかPrototypeパターンを使用するつもりなので。
#include <boost/shared_ptr.hpp>
typedef boost::shared_ptr<A*> APtr;
class B {
public:
B() {
a.insert(APtr(new A("aaa")));
a.insert(APtr(new A("bbb")));
}
~B(){}
private:
std::vector<APtr> a;
};
でコンストラクタ呼ばれました。便利ですね。
追加質問ですが、自分で、deleteするのが面倒ならば、
常に、new をshared_ptrで包んだ方がいいですか?何か弊害ありますか?
769 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/26 00:20
>>766 それはまあ、実際のコードではAは抽象クラスで...
みたいになっているのではないかな。
770 名前: 762 [sage] 投稿日: 04/03/26 00:42
デストラクタですた。失礼。
それと、a.push_backです。これまた失礼しました。
771 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/26 00:45
>>768 そうですね。shared_ptrで包まずに書けばメモリリークします。
772 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/26 00:47
> 追加質問ですが、自分で、deleteするのが面倒ならば、
> 常に、new をshared_ptrで包んだ方がいいですか?何か弊害ありますか?
むしろ、
shared_ptr を使うなら
・自分で delete してはいけない。
・常に new を shared_ptr で包まなければいけない。
さらに、 shared_ptr のテンポラリオブジェクトは作らないほうがいい。
773 名前: 753 [sage] 投稿日: 04/03/26 08:29 結局、以下のようなものを作りました。やれやれ。 template< typename CharT > struct todigit_impl { static inline int cvt( ChatT ch, std::locale const & lc ) { CharT a[] = { ch, '\0' }; std::locale old = std::locale::global( lc ); int i = atoi( a ); std::locale::global( old ); return i; }; // wchar_t 版を特殊化 ... template< typename CharT > inline int todigit( CharT ch, std::locale const & lc ) { return todigit_impl< CharT >::cvt( ch, lc ); } 774 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/26 15:36 標準Cライブラリにも 「数字1文字」→「数値」ってなかったけか?なんか以外だ。 775 名前: 774 [sage] 投稿日: 04/03/26 15:37 ×以外 → ○意外
776 名前: Help me please! 投稿日: 04/03/26 16:56 どなたかお助けください。 以下の様に動いているプログラムで、sub()の中で再度ファイルを オープン・クローズしてますが、それをやらないで例えばoutを引数として 渡して、実際にはプログラムのいろいろな所からよく呼び出されるsub() を実行したいと思っているのですが、out を引数としてプロトタイプの 中で宣言するとエラーが起こってしまいます。なにかよい方法はあります でしょうか。 よろしくお願いします。 #include <stdio.h> #include <fstream.h> void sub() { ofstream out; out.open("log.txt", ios::app); out << "sub executed" << endl; out.close(); } void main() { ofstream out; out.open("log.txt", ios::app); out << "log started" << endl; sub(); out.close(); }
777 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/26 16:58 void sub(ostream &out); 778 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/26 17:13 古いヘッダ使うな 779 名前: Help me please! [sage] 投稿日: 04/03/26 17:19 777さん ありがとうございます。それでうまく行きました。 ofstream は渡せないかと思って、voidにキャストしたりして わけがわからなくなっておりました。レファレンスすれば よかったのですね。
>>755 亀レスになるがポインタでもええよ。要するにofstreamオブジェクト
をローカル変数と見なして(というか実際ローカル変数)、そのスコー
プが外れないように注意すればよい。
VC++7.1付属STLやSTLPortのstringは 参照カウンタ方式じゃないようです。 g++3.2.2では参照カウンタ方式の様です。 パフォーマンス的にどうなんでしょう。 スレッド安全とか言い出すとコピーした方が 早いって事でしょうか?
boost::shared_ptrも参照カウント方式だけどスレッドセーフ。 あまり関係なさそう。 copy-on-writeはC++では当たり前のように使われる最適化手法 だな。
759 :
auto_ptrの質問 :04/03/30 11:20
std::auto_ptr() に operator!() や operator T*() が無いのは何故でしょうか。 暗黙の変換による予期せぬ動作を避けるためですか? 生ポインタを使った既存コードを、例外フリーにするため auto_ptr に変更中ですが、 p => p.get() の書き換えが大量に必要になるため、以下のラッパークラスで処理する ことを考えています。 template<class T> class my_auto_ptr : public std::auto_ptr<T> { public: explicit my_auto_ptr(T* p = 0) : std::auto_ptr<T>(p) {} bool operator!() const { return get() == NULL; } operator T*() const { return get(); } }; これで問題が起こるケースは、my_auto_ptr<T> p(...); delete p; にて二重デリート、 が思いつきますが、他にありますでしょうか。
>>759 >これで問題が起こるケースは、my_auto_ptr<T> p(...); delete p; にて二重デリート、
operator deleteをprivateにしてみては?
>他にありますでしょうか
printf("%d", p);
は
printf("%d", (T*)p);
としないとmy_auto_ptrのインスタンスが渡されますね。
ModernC++Designの7.スマートポインタでそこら辺を触れているので 一読をお勧めします。個人的には、関数にポインタを渡すときにgetと releaseの二つが可能なのであって、勝手にgetを呼び出してしまうのは 危険なような気がします。まあ、関数にreleaseして渡すぐらいなら auto_ptr引数にするって発想もあるんだろうけど。 書き換えの手間って言ってもコンパイルエラーを直すだけでは? それ以前に"auto_ptrを使う=newを利用する"なんでしょうけど そんなにnewを使いまくるってのもいかがなものかと。
>>760-761 ありがとうございました。printf() の場合には気付いていませんでした。
operator delete()をprivateにするのは良いアイデアですね。
新たに書き起こすならば、素直にauto_ptrを使い、get/release を使いますが、
今回は、既存のコードの変更行数を少なくする(ただし安全を満たす範囲内で)が重要なのです。
たしかにコンパイルエラーの箇所を get() 利用に直すだけで済むのですが、変更行数が多いと
工程管理上、派生する問題が大きくなるので避けたいという、政治的な動機です。
手動で書き換えても、暗黙変換させても、どちらにしても実際のバイナリコード変化量は変わら
ないというのは承知しています。
>>758 勝手に話に割り込みますが、何を持ってスレッドセーフとなるのでしょうか。
shared_ptrを見てもロックをかけてるようには見えないのですが。
マルチプロセッサなんかでカウントの増加と減少が同時に起こったりはしないのですか?
>>763 > shared_ptrを見てもロックをかけてるようには見えないのですが。
boost/detail/shared_count.hpp を BOOST_HAS_THREADS で検索しる。
本当に初歩的な質問で恐縮なのですが,,。 当方、VC++6でダイアログベースのプログラムを組んでいて ある特定のキーが押されたかを判定したいのですが, ダイアログにコントロールを乗せるとキーが押されたというメッセージがうまく届かないらしいのです。 何かいい解決方法はないでしょうか。,
スレ違いです
>765 わたしはVC++など買える身分でないので、お答えできません。 相応しい人がいるスレに移動してください。
>>764 あ、、、
こういうことやらなきゃいけないだろうとは思っていたけど、
これだと汎用性無くなっちゃいますよね。
そんなマイナーな環境を使うことが無い自分には知ったこっちゃ無い話ではあるけど。
こういう排他制御の標準も決めるべきだよなぁ。
765です。 完全にすれ違いだったようですね お騒がせしました。
771 :
デフォルトの名無しさん :04/04/01 01:01
ファイル出入力が失敗したときに詳細を報告するため、以下のようなコードを思いつきました。 try { errno = 0; std::ofstream output( ... ); output.exceptions( std::ios::badbit | std::ios::failbit ); ... output.close(); } catch( std::exceptions const& e ) { throw std::runtime_error( ( errno != 0 ) ? std::strerror( errno ) : e.what() ); } そこで質問なんですけど、C++例外処理とerrnoの親和性ってどうなんでしょうか? とりあえず、ファイルが開けなかったりする単純なケースでは上手く動いてくれているみたいです。 上のようなコードでとんちんかんなエラーを報告してしまわないか、少し心配です。
>>771 C++の標準ライブラリはerrnoに一切関知しない。だから
Cのstdio.hと同等な結果を得ようとするならばerrnoは自前で
セットする必要がある。それは例外が投げられた後である。
逆にCのライブラリを呼んでerrnoがセットされたら、該当する
C++の例外を投げるように設計する。
>>760 > operator deleteをprivateにしてみては?
やってみたら、期待した効果がありませんでした。
my_auto_ptr<T> p;
delete p; // no error
delete &p; // error by private operator my_auto_ptr<T>::delete().
前者に対して、errorになることを期待したのですが、甘かった。
774 :
デフォルトの名無しさん :04/04/03 13:40
C++ を学習し始めたが、本によって書き方(言語仕様)が違ったり、コンパイラを変えるとコンパイルエラー を起こしたりするな。 本によって、#include <iostream.h> の .h や using namespace std; があったりなかったりするな。 コンパイラによっては、.h がないとインクルードできなかったり、using namespace std; があると std の識別子が認識できずエラーになったり、string のオブジェクトを使うとエラーになって、試しに #include の .h を取り除くと通ったりとか、cout の書式整形用の識別子を認識できずエラーになったり してめちゃくちゃやのお。 正しい C++ を学習するには正しい本と正しいコンパイラを選ばなければならないか。
いつ頃のstandardや実装に基づいて書かれたものかを意識しないと dでもない目にあうと思う。特にC++は。
>>774 本はまずはプログラミング言語C++第3版。
<iostream.h>は古い規格(1989年以前)の書き方だね。
コンパイラは、たとえばVisual C++ 6.0はその1989以前のもの。
Visual C++ 7.1は現行規格対応。
>>776 VC6はそこまでは古くもない気もするが、というか
1989じゃなくて1999かな。
とりあえずさ、春休みの厨房・工房といえども、 まともにC++使えるようになりたいんなら、 入門書とEffective C++くらいは目に通しておこうや。 適当にサイトみてメチャクチャなプログラム書き出して、 2chで質問してるやつがここ数日多すぎるよ...。
>>779 んな感じだな。
まじめに勉強する気があったら「プログラミング言語C++ 3rd」は手元においておけ。
値は張るがC++を学ぶ以上、必須だ。
大抵の疑問はこれ見れば解決するし。
ポインタを格納するlistコンテナをポインタの値ではなく、ポインタの参照先の値でソートしたい場合はどのようにすればよいのでしょうか。 ポインタの配列にこだわっているのはポリモーフィズムを使用したいためです。 例えば以下の例ではCTestオブジェクトへのポインタの値でソートするのではなく、CTestのm_Numメンバの値でソートしたい場合どのようにすればよいのでしょう。 自分で調べたなかではgreaterがつかえそうなきがするのですが、greater自体を良く知らないもので.... やはりソート処理を独自に一から組むしかないのでしょうか、せっかくlist::sort()が用意されているのに自分で一から組むのはかっこ悪いし、どうかよろしくおねがいします。
#include <iostream> #include <list> using namespace std; class CTest { int m_Num; public: int GetNum() const { return m_Num; } void SetNum( int Num ) { m_Num = Num; } bool operator>( const CTest& obj ) { return m_Num > obj.GetNum(); } bool operator<( const CTest& obj ) { return m_Num < obj.GetNum(); } }; void main() { list< CTest* > l_pTests; for ( int i = 0; i < 10; ++i ) { CTest* pTest = new CTest; pTest->SetNum(rand()); l_pTests.push_back(pTest); } l_pTests.sort(); // ポインタの値ではなく、m_Numの値でソート出来るようにしたい list< CTest* >::iterator itCur, itEnd = l_pTests.end(); for ( itCur = l_pTests.begin(); itCur != itEnd; ++itCur ) { cout << (*itCur) << ' ' << (*itCur)->GetNum() << endl; delete (*itCur); } getchar(); }
struct sorter { bool operator ()(const CTest *lhs, const CTest *rhs) const { return *lhs < *rhs; } }; l_pTests.sort(sorter()); CTest::operator<()()をconstにしないと、このままじゃ通らないけどな。
すいません解決しました。 class CLapTest { public: CTest*m_pTest; bool operator>( const CLapTest& obj ) { return m_pTest->GetNum() > obj.m_pTest->GetNum(); } bool operator<( const CLapTest& obj ) { return m_pTest->GetNum() < obj.m_pTest->GetNum(); } }; void main() { list< CLapTest > l_LapTests; for ( int i = 0; i < 10; ++i ) { CLapTest LapTest; LapTest.m_pTest = new CTest; LapTest.m_pTest->SetNum(rand()); l_LapTests.push_back(LapTest); } l_LapTests.sort(); list< CLapTest >::iterator itCur, itEnd = l_LapTests.end(); for ( itCur = l_LapTests.begin(); itCur != itEnd; ++itCur ) { cout << (*itCur).m_pTest->GetNum() << endl; delete (*itCur).m_pTest; } getchar(); }
>783 ありがとうございました、そちらの方法で組んで行こうと思います。
>783さんの方法で試してみたのですが、私の環境VC++6.0だと次のコンパイルエラーが発生してしまいました。 error C2664: 'void __thiscall std::list<class CTest *,class std::allocator<class CTest *> >::sort(struct std::greater<class CTest *>)' : 1 番目の引数を 'struct sorter' から 'st ruct std::greater<class CTest *>' に変換できません。 (新しい機能 ; ヘルプを参照) なのでsorterを次のように変更してコンパイルエラーは解消することが出来ましたが、l_pTests.sort( sorter() );を実行しても"キタ━━━━(゚∀゚)━━━━ッ!"が表示されず思うようにソートしてくれません。 struct sorter : public std::greater<class CTest *> { bool operator()(const CTest *lhs, const CTest *rhs) const { assert(!"キタ━━━━(゚∀゚)━━━━ッ!!"); return *lhs < *rhs; } }; VC++6.0では無理なのでしょうか、それともエラーの修正方法が間違っているのでしょうか?
operator(const Ctest...)ではなく、 operator >(const CTest&, const CTest&) を定義しとけ。
別に関数オブジェクト作るほど気合いれなくても、単なる捨て関数でええんじゃ? namespace { bool Compare(CTest* lhs,CTest* rhs,){ return lhs->GetNum() < rhs->GetNum(); } } // main内 l_pTests.sort(Compare); これでとりあえず動くんでない?
私の環境で>788さんの方法をやると次のエラーが出てしまいだめでした。 error C2664: 'void __thiscall std::list<class CTest *,class std::allocator<class CTest *> >::sort(struct std::greater<class CTest *>)' : 1 番目の引数を 'bool (class CTest *,cl ass CTest *)' から 'struct std::greater<class CTest *>' に変換できません。 (新しい機能 ; ヘルプを参照) コンストラクタはソース型を持てません、またはコンストラクタのオーバーロード レゾリューションがあいまいです。 >787さんの方法でやってもだめでした。 bool operator>(const CTest& lhs, const CTest& rhs) { cout << "キタ━━━━(゚∀゚)━━━━ッ!!" << endl; // 表示されない return lhs.GetNum() > rhs.GetNum(); } bool operator<(const CTest& lhs, const CTest& rhs) { cout << "キタ━━━━(゚∀゚)━━━━ッ!!" << endl; // 表示されない return lhs.GetNum() < rhs.GetNum(); } 協力してくださりありがとうございました。
ていうか、VC6でlist::sort()は難しいのかもしれないけど std::sort()にlistのbegin()とend()を渡してみたら? 比較関数/関数オブジェクトは他の人が書いてるのをそのまま使って。
ああそうか。ポインタのlistか。 operator >(const CTest*, const CTest*)って定義できたっけか? std::greater< CTest * >を定義しちまう手もあるかも。
>>790 std::sortはRandomAccessIteratorを要求する。
>>971 >operator >(const CTest*, const CTest*)って定義できたっけか?
できない
>std::greater< CTest * >を定義しちまう手もあるかも。
できたとしても好ましくないかと。
じゃあ、std::list< boost::shared_ptr<CTest> >にする手だな。 (boost::shared_ptr自体、std::greater<boost::shared_ptr<T> >を 定義してるけどナ)
>793さんの方法は敷居が高そうなので、今現在は身の程をわきまえて>784の方法で取りあえずしのぐことにしました。 今回のことでC++をまだまだ理解できてないなと痛感しましたので、「プログラミング言語C++ 3rd」を買って勉強することにしました。 そんでもって.NETにさっさと移行したいとも思います。 どうもありがとうございました。
実はlistではなくsetを使っても良い処理だったり。
>「プログラミング言語C++ 3rd」を買って勉強することにしました。 から >そんでもって.NETにさっさと移行したいとも思います へなぜ至るのかよくわからん
あー、.NETってVS.NETのことか だったら勘違いした、すまん
#include <vector> #include <algorithm> using namespace std; struct TEST; struct test_compared : public binary_function<TEST*, TEST*, bool> { bool operator()(const TEST*& x, const TEST*& y) const { ユーザー定義の処理 } }; int main() { vector<TEST> array; ・・(なんらかの処理)・・ sort(array.begin(), array.end(), test_compared()); ・・(以下省略) }
修正しとく。 ×vector<TEST> array; ↓ ○vector<TEST*> array;
> bool operator()(const TEST*& x, const TEST*& y) const ここもまちがってるぞ。
まちがいというより、ただの別表現。
>>801 まちがってるって事は、
コンパイル通らないorランタイムエラー発生って事?
是非、模範的な記述方法をお教えくださいな。
#include <list> #include <iostream> using namespace std; class CTest { private: int m_Num; public: explicit CTest(int num) : m_Num(num) {} int getNum() const { return m_Num; } }; struct CTCompare : public binary_function<CTest*, CTest*, bool> { bool operator()(const CTest* lhs, const CTest* rhs) const { return lhs->getNum() < rhs->getNum(); } }; int main(int argc, char* argv[]){ list<CTest*> ctests; for (int i = 0; i < 10; ++i) { ctests.push_back(new CTest(rand())); } ctests.sort(CTCompare()); list<CTest*>::iterator end(ctests.end()); for (list<CTest*>::iterator it(ctests.begin()); it != end; ++it) { cout << (*it)->getNum() << endl; } return 0; } //自分でdeleteしてね(w
>>804 なるほど、std::less<int*>などはそもそも間違ってるって事ですね。
template<class _Ty>
struct less : binary_function<_Ty, _Ty, bool> {
bool operator()(const _Ty& _X, const _Ty& _Y) const
{return (_X < _Y); }
};
上のテンプレート(VC6のもの)を参考にしてポインタ型を当てはめてみたんですが、
単なる無意味なアドレス比較に相当するstd::less<int*>などは、
本来エラーが発生しなければいけないって事ですね?
つまり、コンパイラが間違っているorテンプレートが不正って事でOK?
で、模範的な記述に修正すると以下のようにすべきって事ですね。
template<class _Ty>
struct less : binary_function<_Ty, _Ty, bool> {
bool operator()(const _Ty _X, const _Ty _Y) const
{return (_X < _Y); }
};
>>805 >模範的な記述に修正すると以下のようにすべきって事ですね。
んなこたーない。
つか、やめれ。コピー処理が大量発生する。
>805 ポインタのリファレンスを取るオーバーヘッドが無駄だなぁってことで >804な感じ
>>798 リファレンスによる実行時のオーバヘッドについては多分ないんだろうけど、
人間様がソース見たときにギョッとするオーバヘッドはあるな、確実にw
>>809 ポインタ位の小さなオブジェクトであれば、わざわざリファレンスにするまでもないと思うし、
むしろ逆に逆参照を2回しなければならない分オーバヘッドは増えるような気がする。
コンパイラが値渡しに最適化するかもしれないけど。
というかこれくらいならまずインライン化されるでしょう. そのためのfunctorなわけですし.
>オーバヘッドは増えるような気がする。 それは参照がオーバヘッドを生ずると言う意味か? それは違うと思うが・・・。
813 :
デフォルトの名無しさん :04/04/06 15:30
>>812 > それは参照がオーバヘッドを生ずると言う意味か?
リファレンスはポインタを用いて実装されているだろうし、参照渡しされたポインタそのものを
更に逆参照しているわけだから、ポインタを値渡しするよりはオーバヘッドは大きくなるはず。
>>813 だったら、参照先を変更できず、また、
参照を使う場合に必ず初期化しなければいけないのは何故?
私的見解だが、コンパイラにとって参照は単なる変数のエイリアスだと思うが?
我々がインスタンスをもった変数と思っているものは
コンパイラにとっては所詮アドレスにすぎず、
同じアドレスと解釈される変数が増えただけという認識なのだが。
リファレンスがポインタで実装されているという明文化された規格などが
あるようであれば教えて欲しい。
>814 関数の引数としての参照がどの変数のエイリアスなのか コンパイル時に決定できると?(インライン化される場合を除いて)
>>815 ん?
その関数に渡される変数は、そもそもコンパイル時にアドレスが決まるの?
どのアドレス位置で変数用メモリが確保されるかは、スタックの状態次第じゃないの?
>>816 int i;
int &r =i;
上の場合は確かに
>我々がインスタンスをもった変数と思っているものは
>コンパイラにとっては所詮アドレスにすぎず、
>同じアドレスと解釈される変数が増えただけという認識なのだが。
この通りだとは思うのですが,
void f(int & r){ r = 2; }
この場合は,rがどの変数のエイリアスであるかは実行時まで分からないですから
void f(int *const p){ *p = 2; }
とまったく等価(インターフェイスの差異を除いて)であり,
従って参照のdereferenceのオーバーヘッドがかかると思うのですが,どうなんでしょう?
>>817 実行時まで分からないことが、
どうしてオーバーヘッドになると思うの?
逆参照は何も参照変数だけじゃなくて
普通の変数でも普通に行われてるのでは?
void f(int& r): void f(int i): 上2つは、オーバヘッドは同じ。32ビットだから。 OK?
>>818 assembleも読めないC++初心者なので,何か大きな勘違いをしているのかも知れないのですが
>逆参照は何も参照変数だけじゃなくて
>普通の変数でも普通に行われてるのでは?
確かにそうだと思います.ですが,例えば819さんの例では
(関数の呼び出しの部分「だけ」に関しては819さんの言うとおりだと思います)
void f(int i/*スタックにiが置かれそのアドレスが引き渡される*/){
i; // 引き渡されたアドレスをdereferenceして値iを得る
}
void f(const int & r/*スタックにint*が置かれそのアドレスが引き渡される*/){
r; // 引き渡されたアドレスをdereferenceしてint*の値を得て,
//さらにそのint*をdereferenceして(参照の場合ここが余計にかかる)intの値を得る.
}
こういうイメージだったのですが何か間違っているのでしょうか?
>>818 > 逆参照は何も参照変数だけじゃなくて普通の変数でも普通に行われてるのでは?
参照の場合は逆参照が1つ余計に必要になり、それがオーバヘッドになるということじゃないの?
Tへの参照を引数に取る関数は、Tへのポインタを引数に取る関数としてコンパイルされるとすると、
Tへのポインタ型の仮引数を読んで、更にそのTへのポインタ型の値を逆参照する必要がある。
それに対して、T型を値渡しで引数に取る関数は仮引数を読むだけでいい。
明らかに1回の余計な逆参照が生じている。逆参照の存在が問題なのではなく、その回数が問題になる。
> 実行時まで分からないことが、どうしてオーバーヘッドになると思うの?
実行時まで判らないのは、生成されるコードではなくて参照されるオブジェクトの位置でしょ。
参照が前述の様な実装をされているとすれば、引き渡されるポインタの値。
それが違うことによって、実行速度が変化するとは思えない。
ぶっちゃけ参照は常に逆参照されるポインタです、みたいなことが 禿の本に書いてあったような気がする
gccは$を識別子として使えるけど、VCではどうなん?
あ、さげてしまた。
>>820 間違ってないと思いますよ。
以下VS.net2003での最適化無しの場合です。
アセンブラ読めなくてもなんとなくわかってもらえるかと。
void test(int& a)
{
printf("a:%d", a);
}
mov eax,dword ptr [a]
mov ecx,dword ptr [eax]
push ecx
push offset string "a:%d"
call _printf
add esp,8
void test(int a)
{
printf("a:%d", a);
}
mov eax,dword ptr [a]
push eax
push offset string "a:%d"
call _printf
add esp,8
>>826 VC++6.0で確認したが
f(int a){ printf("a:%d", aaa); }
f(int& a){ printf("a:%d", aaa); }
f(int* a){ printf("a:%d", *aaa);}
がいずれも同じコードになった。
全く同じだった。VS.NETは違うんだね。
以下、混合モードから抜粋。
3つとも一緒だったの1つだけ貼る。
push ebp
mov ebp,esp
sub esp,40h
push ebx
push esi
push edi
lea edi,[ebp-40h]
mov ecx,10h
mov eax,0CCCCCCCCh
rep stos dword ptr [edi]
mov eax,dword ptr [ebp+8]
push eax
push offset string "a:%d" (0043d01c)
call printf (00408900)
add esp,8
>>822 ぶっちゃけ、参照だけじゃなく変数はすべて逆参照されるポインタ
その本の内容は言葉足らず。もしくは間違っている。
>>828 > ぶっちゃけ、参照だけじゃなく変数はすべて逆参照されるポインタ
その主張でレジスタ上の変数はどう説明されるのでしょう?
最適化によって発生したレジスタ変数は、逆参照の手間が省かれた変数・・かな? 何にせよ、参照変数オーバヘッド伝説は 糸冬 了。
> 最適化によって発生したレジスタ変数は、逆参照の手間が省かれた変数・・かな? 関数の引数で、値渡しならレジスタに乗るものが参照渡しだと乗せられない。 現実的な差があるだろ。
>>827 って同じコードになるわけないと思うんだけど
>>832 VC++6.0持ってない?
私に確認するより、デバッグで混合モードを見て頂けると有難いのだが。
違っているのを報告してもらえれば万事解決。
834 :
デフォルトの名無しさん :04/04/07 00:12
>>827 それだと最適化されてるかなんか勘違いしてると思う。
その出力コードだとたとえばポインタ版だと
aのアドレスではなくaの中身がスタックに直接積まれてるので
関数内でaのアドレスが参照できないよ。
ちなみにVC++6.0では、引数の積み上げ方は違ってた。投稿の制約上、改行を一部変えた。 void Func1(int aaa){printf("a:%d", aaa); } void Func2(int* aaa){printf("a:%d", *aaa);}void Func3(int& aaa){printf("a:%d", aaa);} int main(){ int num = 100;int* p_num = # Func1(num);Func2(&num);Func2(p_num);Func3(num); return 0; } =====以下、混合モードの表示====== 34: Func1(num); 00401185 mov ecx,dword ptr [ebp-4] 00401188 push ecx 00401189 call @ILT+25(Func1) (0040101e) 0040118E add esp,4 35: Func2(&num); 00401191 lea edx,[ebp-4] 00401194 push edx 00401195 call @ILT+40(Func2) (0040102d) 0040119A add esp,4 36: Func2(p_num); 0040119D mov eax,dword ptr [ebp-8] 004011A0 push eax 004011A1 call @ILT+40(Func2) (0040102d) 004011A6 add esp,4 37: Func3(num); 004011A9 lea ecx,[ebp-4] 004011AC push ecx 004011AD call @ILT+10(Func3) (0040100f) 004011B2 add esp,4
>>834 (;´Д`)私に言われても・・・。
VC++.NET版を張ってくれるヤシは居らんかね?
.net2003の最適化無しだとポインタ版と参照版は同じコードになるよ。 void test(int* a) { printf("%p:%d", a, *a); } mov eax,dword ptr [a] mov ecx,dword ptr [eax] push ecx mov edx,dword ptr [a] push edx push offset string "%p:%d" call _printf add esp,0Ch
正直、こんなオーバヘッドよりも ロジックとかアルゴリズムの方が 実行速度にはるかに影響を与えている罠。
840 :
デフォルトの名無しさん :04/04/07 01:09
827の修正します。スマソ。(´・ω・`) あらたにvoid Func4(int*& aaa);も追加して試してみた。 3つ一緒というのは間違いでした。 同じだったのは、void Func2(int* aaa)とvoid Func3(int& aaa)。 void Func1(int aaa)はコードが1つ少ない。 void Func4(int*& aaa);はコードが1つ多い。 よって、VC6.0++では、 1.(int ) 2.(int* )、(int&) 同等 3.(int*& ) の順番にコードが短い。お騒がせしました。
>>834 >なんか勘違いしてると思う。
その通りだったみたいです。失礼しました。
GCC、VC6.0、VC.NETいずれの場合も
int* int& が同じコードを吐くという事でよろしいでしょうか?
実際、int*とint&はどのコンパイラでもほぼ同じ扱いと仮定してかまわないけれど、 inline関数で&で受けるもの(特にconst&)は、うまく最適化される場合もあった気がする。 *で受けると配列かどうかわからないけど、&で受けると配列ではないことがわかるから。
843 :
デフォルトの名無しさん :04/04/07 12:20
クラス内で文字列定数を定義したい場合どうするんですか? static const char* str[] = { "a", "b", "c" }; は駄目でした。
//宣言 class Hoge{ static const char* str[]; }; //定義 const char *Hoge::str[] = {"a","b","c"}; だったか。
>>844 なんか別のスレでも同じような回答をしたばかりなのだが・・・
クラス宣言内で初期化できるのは static constな整数だけ。
それも即値でしか初期化できない。
これ以外の静的メンバは必ずクラス宣言外で定義が必要だし、
そこで初期化するしかない。
なお、クラス宣言内で初期化した static constな整数には実体がない。
実体が必要になるときは、これまたクラス宣言外で定義が必要。
以上禿本から要約。
>>845 ,846
どうも親切に。質問する前に他スレも読みますね。
class A { public: template<class T> T* func() { return (T*)NULL; } }; template<typename T> T* func() { return (T*)NULL; } A a; int* p1 = func<int>(); // (1)OK int* p2 = a.func<int>(); // (2)error C2062: 型 'int' は不要です。 (1)が良くて(2)がダメな理由がわかりません。 なぜメンバ関数だとダメなのでしょうか?
class Aの方の template<class T> は template<typename T> です。 どっちでも同じですけど。
書き忘れました。VC++6.0 SP6です。
VC6でテンプレートをがんばるなヨー 諸般の事情があるなら別だけどさ、SP6入れてるってことは遊びだろ?
VC++ .NET 2003では通りました. 851さんのおっしゃるとおりVC6でテンプレートを使うのはお勧めできません.
>>851-852 VC++6.0のテンプレートってバグバグなんですかorz
だれか2003くれないかな・・・
VC7.0の最適化は、ツボにはまると最悪です。 それ考えるとVC6.0の方がまだマシだとおもふ。
int* p2 = a.template func<int>(); とやってもだめか?本来は冗長な書き方だが。
>>855 error C2951: テンプレートの宣言はグローバル スコープまたは名前空間スコープでだけ可能です。
error C2059: 構文エラー : 'newline'
と出ました。
つーか、NULLポインタ渡すだけなのになぜ、テンプレートつかうのかと。 普通にNULLいれればいじゃん。
>>858 例として挙げただけで、実際とは違います。
860 :
デフォルトの名無しさん :04/04/08 12:46
ちょっと掴み所のない質問かもしれませんがよろしくお願いします。 MIDIアプリで、 txtに変換されたMIDIデータを読みこんで、設定した伴奏を自動で(txtで)付け加え、 それをMIDIに戻す、というのを作ろうとしています。 伴奏を付け加えるのは何とかできそうなんですが、 肝心のMIDIデータの吸い出し方が判りません。 良い本やHPなど紹介して頂ければと思います。よろしくお願いします。
スレ違い。 ハイ、次の方どうぞ
862 :
デフォルトの名無しさん :04/04/08 18:05
string から vector<char> にデータを写す時の定石的な書き方ってありますか? memcpy で普通にコピーみたいな感じでしょうか?
>>861 判らないからってそそういう言い方はないだろう。
ま、俺もわからんけど。
>>862 vector<char> c;
string s;
c.assign(s.begin(), s.end());
>864 そうか、vector<char> -> string とまったく逆に書けばよかったんですね… ありがとうございました
おいおい、すれ違いの質問を「立派な質問」かよw
本物のバカみたいだから放置していいんじゃないかな。
>>862 ちなみにmemcpyを使うなら下の書き方かな?
vector<char> v;
string s;
v.resize(s.size());
memcpy(&v[0], s.c_str(), s.size());
>>869 s.c_str()よりは、&s[0]のほうがいいかも?
>>870 stringは要素が連続した領域に格納されることが保証されているの?
vectorは問題ないはずだけどね。
>>871 保証されてなかったら、string::c_str()なんて関数を公開しない罠。
むしろ、vectorじゃないか?保証がないのは。
>>872 EffectiveSTLだったか何かにvectorの連続性は保証されるって書いてあったと思うぞ。
>871 私も疑問に思ったので標準を漁りました. まず,周知の通りvectorは&v[0]で取れるメモリの連続性は保証されています. 一方でstringは内部表現が連続したメモリであることは保証されていません. (標準の21には空間の連続性に対する表明が見つかりませんでした) また,Effective STLの第16項も同様に言っています. そして,string::c_strは必ずしも内部表現の配列の先頭を返すとは限らないようです. (標準21.3.6) >872 むしろ内部の連続性が保証されていないのでc_strを公開している,というのが正しいようです.
875 :
デフォルトの名無しさん :04/04/08 21:32
いや、stringの内部でどう並んでるかは何の保証もない。 c_strは、内部表現を得るための物ではなく、 stringと意味的に等しい物を得る物だよ。
std::string は参照カウントで実装されうる品
ん?ということは,c_strをmemcpyに引き渡すという行為はかなり無駄な行為なのかも知れませんねw c_strが中でstringの内部表現をコピーしているのかも知れませんから.(ここは実装依存でしょう) というわけでおとなしくiteratorを使うのが良いのでしょう.>864
例えばforループの中である処理をやっていて、 キーが何か押された場合別の処理に進む方法っていうのは何かありませんか?
879 :
デフォルトの名無しさん :04/04/08 22:08
>>874 >むしろ内部の連続性が保証されていないのでc_strを公開している,というのが正しいようです
では、どんな時にc_str()を使うのか教えていただきたい。
cのヌル終端文字列だからc_str()って名前なんじゃないかと思うのですが・・・。
つまり、C標準関数やその他の関数のconst char*引数に使うための代物では?
保証されないという事は、stringの文字列バッファの中身をCの関数に渡しちゃダメって事ですよね。
vecorのような1つの要素が大きな容量である配列の連続性が保証されていて、
stringのような1つの要素が1バイトである配列の連続性が保証されていないのは知りませんでした。
明らかな連続性を前提にしているから明記してないだけだとばかり思ってました。
そうであれば、stringから従来型のchar[]へ、バッファコピーする際の推奨されるコピー方法は何でしょうか?
>>879 std::stringの内部表現がCの文字列と全く互換性がない場合にはc_str()が互換性のあるものに
コンバートしてそれを返すだけ。よってstrcpy等のソース側にはc_str()を渡せる
881 :
デフォルトの名無しさん :04/04/08 22:23
お前ら
basic_string<charT>::operator [](int index)はdata()[index]を返す。[21.3.4 1] data()はcharT *を返す。イテレータではなく連続した領域へのポインタである。[21.3.6 4] つーことは(s.size() > 0なら) &s[0] は s.data() と同等であり、連続した領域の 先頭アドレスが得られるはずだな。
>>880 回答ありがとうございました。
今までどおりc_str()でconst char*に使う事にします。
iteratorではC関数に渡すときアドレスが連続じゃないかもしれないみたいなので。
>>872 std::ropeにもc_str()があるわけだが。
むむむ?いつの間に標準にropeが入ったんでしょうか?
>>885 どこに標準の話をしていると書いてあるよ?
>>879 > stringから従来型のchar[]へ、バッファコピーする際の推奨されるコピー方法
そらやっぱり string::copy() なんじゃないの?
888 :
デフォルトの名無しさん :04/04/09 02:02
Effective STLの日本語正誤表orここは気をつけたほうがいいというアドバイスないっすか? ピアソン覗いたら英語しかないっす・・・。 (というかピアソンは用意してないっす) 当方、本の間違いに気づけるほど力ないっす(´・ω・`)
>>886 >『std::』rope
って書いてあるからじゃ? 標準じゃなきゃ、std内には入れられないんじゃなかったっけ?
だからいつのまに標準に、と聞いてるのかと。
>>889 STLportとかSGI STLじゃん。知らんのか?標準ではなくても
std::に入っている。
891 :
デフォルトの名無しさん :04/04/09 04:49
892 :
デフォルトの名無しさん :04/04/09 07:46
SetTimerをC言語のコンソールアプリで使う方法を教えてください。
SetTimer(NULL,NULL,FUNC,100); としてもFUNCが全くコールバックされません。何故でしょうか?
SetTimer(NULL,NULL,FUNC,100); としてもFUNCが全くコールバックされません。何故でしょうか?
>>892 というより、スレの趣旨が判らないほどに理解が混乱しているのなら、
むやみに質問を書き込まずに冷静に頭を整理した方がいいよ。
897 :
デフォルトの名無しさん :04/04/09 08:03
すいません、API専用のスレがあるとは知りませんでした。
898 :
デフォルトの名無しさん :04/04/09 09:50
BCBでいうところの__closureみたいなことをやりたくて考えてみました。 で、できたのが次のような方法。実験はVC6で行いました。 【定義】 typedef void (CObject::*METHOD_HANDLER)(CObject *Sender); // たとえばメインフレームクラス class CMainFrame : public CFrameWnd { : private: void MainFrameHandler(int Hoge); : }; 【使うとき】 CObject *pInstance; METHOD_HANDLER pHandler; int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { : : pInstance = this; pHandler = (METHOD_HANDLER)&CMainFrame::MainFrameHandler; } で、使うときはこんな具合。 pInstance->*pHandler(5963); 一応意図した動作はしていますが、こんなんで大丈夫なんでしょうか。 インスタンスとオフセット情報さえあれば型は何でもいいのかな?
ごめん、ちょっと間違えた。 ×typedef void (CObject::*METHOD_HANDLER)(CObject *Sender); ↓ ○typedef void (CObject::*METHOD_HANDLER)(int Hoge);
>>889-890 標準ではないものがstd名前空間に入っていることは、規格上あり得ない。
なので std::rope という表現ができること自体、規格違反。
889が正しい。
>>900 ならお前はSTLportは一切使うな。これでOK。
STLportって標準外のも含んでるんじゃなかった? ハッシュコンテナとかC++標準じゃないよね?
>>903 STLportはSGI STLを改良し続けて、事実上のフリーソフトに
なっている。だからstd::ropeやstd::hash_map、std::slistや
std::identity、std::project(他にもたくさん)を含んでいる。これ
はSGI STL直系のSTLである事を示している。
それらは標準外である事は十も承知だし、移植性を問題に
する場合は一切使ってないが(というかあまり使わないよね)、
どうも
>>900 は俺がそれらの標準外のコンテナや関数オブジェクト
を標準であると勘違いしていると思いこんでいるらしく、しつこく
規格違反だとかstdに入れるべきでないとか的はずれなレス
ばかり返しやがる。
随分と標準がお好きなようだな
>>900 は。
> また、テンプレートライブラリ(STL含む)に関する質問は > 専用の別スレへどうぞ。 ここって 結構ピュアなC++スレでしょ?ちがったっけ?
参照にオーバーヘッドはないとか主張してた厨だろ
>>904 なんか論点をあさっての方向に勘違いしてねぇか?
現状のSTLportがどうなってるかなんてのは問題じゃなくて、単に
「標準C++で規定されてないものをstd名前空間に入れるのは行儀悪い」
ってだけの話だろ?
>>907 おいおい、俺のレスをちゃんと読んでから書いてるのか?
「標準C++で規定されてないものをstd名前空間に入れるのは行儀悪い」
という点については否定してないだろ。
STLportの行儀悪さについては「十も承知」とちゃんと書いてるだろ。
何が言いたいんだよ。
>901=>904=>908=>910 (・∀・)ニヤニヤ
もうどっちでもいいからC++の話しようぜ?
>>912 次スレまではこの流れでキボンヌ。(ワラ
>>913 同意(w
ここまでベタな (・∀・)ニヤニヤ はあんまりいないしね。
春も終わっちゃうから最後のお楽しみ。
で、rope.c_str() で何が言いたかったの?
>>915 「百も承知」と書いて欲しかったのかよ。完全な重箱の隅を突く
アホだな。
>>914 何がニヤニヤだよ。反論できないだけだろ知障。
プラットホームをまたいでコーディングするPGにとって 標準STLの正しい理解は極めて重要。 たまに病的なまでに規格に詳しい人もいるが、 まあ、みんなに良い知識を提供してくれるのだから歓迎すべきだね。
テンプレートライブラリがなけりゃC++を使えないような香具師が わかったような口を利くな。
( ゚д゚)<
たまに居るよな、テンプレートを使わず自力でリストを準備したりする輩。 で、破滅的なソースを書いて、プロジェクトから外される。 そして、あとを引きついだ人間が酷い目にあう、と。 アフォプロジェクトの黄金パターンだな。
>901の流れはどうつながってるの? 漏れの印象では>916>918ときてるように思ったんだが
というか、だれか
>>898 にレスしてやれ。
ここまでスルーされているのも泣ける。
"C++プログラミング言語 第3版"に出てくる 練習問題の模範解答みたいなものって、どっかにありますか?
>>923 え?知らないのか?
「プログラミング言語C++:ソリューション」、アジソン・ウェスレィ/アスキー、
ISBN4-7561-3136-0
英語名は「C++ Solutions Companion to The C++ Programming Language,
Third Edition、author: David Vandevoorde」だから適当にぐぐると
PDFやCHMぐらいは落ちてるかも。(できるだけ買おう)
925 :
デフォルトの名無しさん :04/04/10 15:35
相互参照はどうすれば可能なのでしょうか? (試したコード:エラー) struct B; struct A { void test(B& b){b.hello();} }; struct B { void test(A& a){} void hello(){} }; int main(){}
struct B; struct A { void test(B& b); }; struct B { void test(A& a){} void hello(){} }; void A::test(B& b){b.hello();} これでどーよ?
>>926 できました!
void A::test(B& b){b.hello();}
をBの定義の後に記述すればよいのですね。
規格書とかEffective STLとか手元にあるんだけど The C++ Standard Libraryも手元にあったほうが良いのかなぁ?
Effective C++ の46項の、enum値をコピー不可クラスにすることでランタイム時チェックから コンパイル時チェックにするっていうのは、初めはすげーと思ったけど、めんどくさすぎで 現実的ではなさすぎ。 なんかうまいこと簡単にやってくれるようなクラステンプレートみたいなもんはないかね? boost::noncopyable使うだろう、というところで俺の頭はパンクした。
930 :
デフォルトの名無しさん :04/04/10 20:54
初めて大きいプログラムを作り始め、複数ソースで作っています。 そこで変数の宣言についての質問なのですが、 Aというクラスがあり、A.cpp内でしか使われない変数というのは Aのプライベートメンバ変数として宣言するのがいいのか、それともA.cppの中で グローバル変数(staticをつけて)として宣言した方がいいのでしょうか。 Aオブジェクトが複数存在する可能性がある場合はグローバル変数として宣言するしかないと思いますが、 ひとつしか存在しない場合はどちらも同じような気がします。 どなたかアドバイスよろしくお願いします。
static でクラス変数にしたらいんでない?
あ、そんな方法が… すいません。激しく出直してきます。 ちなみにstaticで解決できるわけですが、A.cppのグローバル変数とどちらがよいか、 というのはありますか?
そりゃまぁ、オブジェクト指向したいならグローバル変数はなるべく避けるべきだろうね。
>>930 逆だよ。グローバル変数だとインスタンスが複数になるときに困る。
>932 リンカからみた名前空間を汚染したいかどうか。
936 :
デフォルトの名無しさん :04/04/10 22:16
Vector配列を数字の小さい順にソートする関数はありますか?
std::sort()
VC C++ Standard Edisionでの ソリューションエクスプローラの項目が表示メニューを見ても 見つかりませんでした。 どこにあるのか教えてください。
>>938 すれ立てるまでも無い・・・の100か?だったらVC6にはソリューションエクスプローラは無い。
つーかスレ違い
>>939 ありがとうございました。
そしてスレ違いごめんなさい
>935 930にstatic付き、って書いてあるよ。 まあC++的には無名名前空間だろうけど。 >932 基本的にクラスに関係するものならクラスの中に入れるべきだが、 何か理由があって、ヘッダに宣言を書きたくない場合はソースに埋め込む。
というか、どっちでもいいときはスコープは小さい方にしとけ。 これはもう格言だから。 #たとえば、「インスタンスが一個しかない」という前提を忘れた時に #まとめて不幸がやってくるだろ?
それならばインスタンスが1個しかできないような コーディングをしない方が悪いと思うが。
>>943-944 だから、「たとえば」の話。
それに、Singletonだからグローバルの方がいいって話にはならんでしょ。
( ´-`).。oO(俺の質問は華麗にスルーですかそうですか (つwT))
えっと・・・あの・・・できれば私のも・・・ だいたい分かっている(つもり)なんですが役に立つでしょうか? 5000円(でしたっけ?)は結構大きい出費なので
>947 あった方が良いかなんて人それぞれだろ 何が必要なのか、人に聞くのもいいがちったあ自分でも考えろや それでも分からんのなら、このスレに出てきた書籍全部買え
便乗質問で申し訳ありませんが、
グローバル変数を使ったときにインスタンスが複数になった場合の不都合とは
具体的にどのようなものなのでしょうか?
自分はC++とDirectXでゲームを作っておりまして、
頂点バッファ・テクスチャへのポインタなどをA.cppのstatic変数として宣言しております。
(staticメンバにしたほうがよいというのはこのスレをみて知りました…)
それでAの関数であるDraw();内で使っています。
これは複数でも単体でも今のところ不都合はありません。
>>942 さんの格言通りこれからコーディングしなおすつもりではありますが
これから何かで使うかもしれないので複数になると出る不都合を教えていただけないでしょうか?
よろしくお願いします。
>>941 そうだね。C++的には無名空間。
staticは推奨されてないからね。
なんでstaticを使わないことを推奨されてるのかは、知らない。
誰か教えて。
ヘッダに書きたくないときは pimpl にすればよろし。
>>947 948の言うとおり。
928がどんな奴なのかわからないと、
無いよりあった方が良いとしか言えない。
俺は持ってないけどな。
動的配列をvectorであてて vector<int> a(N); なんか操作 delete a? とdeleteする時はどうすればいいのでしょうか?
内部で管理しているメモリはデストラクタで解放されるから何もせんでいい。 new したポインタを要素にしているという話なら(おすすめしないが) それぞれの要素を注意深く手動で解放しないといかん
例を見るに、そこまで判っていないんじゃないかと。 int i; として delete i; はしないだろ? と言っておく。 int *pInt = new int; としたら delete int; が必要。 vector<int>という型(クラス)なので、 vector<int> a; にdeleteはいらない。 OK? >953
>>953 つーか、初心者を剽窃したいなら初心者スレに逝けよ。
957 :
デフォルトの名無しさん :04/04/11 13:03
初心者を剽窃アゲ
958 :
デフォルトの名無しさん :04/04/11 14:56
辞書で調べてみたけど全然意味が違うな。
>>949 「グローバル変数はどこからでも誰にでも参照も変更できる」
ということは、つまりプログラムを修正したい場合、*全*ソース
コードを舐め回して影響が無いかどうかをチェックする必要が
あるということ。プログラムの規模が大きくなればなるほど、
この影響は無視できなくなる。
staticにすれば、影響範囲はClassの中だけにとどまる。
ローカルにすれば、関数内だけにとどまる。
というか、オブジェクト指向でいくんなら、
もはやグローバルという用語は忘れて
「Publicか」「Privateか」という思考に切り替えた方がいいよ。
ちょっと聞きたいんだけど vector<void*> v; 色々 vector<vector<void*>::iterator> v2; for (vector<void*>::iterator it = v.begin(); it != v.end(); ++it) { if ( /* it はもう必要ないなら*/ ) { v2.push_back(it); delete (*it); } } for (vector<vector<void*>::iterator>::iterator it = v2.begin(); it != v2.end(); ++it) v.erase(*it); っていうコードなんだけど、もっと綺麗に書く方法ないかな?
Borland C++ 5.5インストールしたんだけどどうすりゃいいの? .cppってファイル作ってどうすりゃいいの? もうわかんない…
>>960 typedef vector<void*>::iterator iterator;
iterator const end = v.end();
iterator end_of_the_held = v.begin();
for (iterator it = v.begin(); it != end; ++it)
{
if ( /* it はもう必要ないなら*/ )
{
delete *it;
}
else
{
*end_of_the_held = *it;
++end_of_the_held;
}
}
v.erase(end_of_the_held, end);
std::vector<void*>をboost::shared_ptrで包む。
template<typename T>struct deleter{void operator()(T *p){delete p;}}; const iterator mid = partition(v.begin(), v.end(), /* まだ必要 */); for_each(mid, v.end(), deleter<void>()); v.erase(mid, v.end());
>>956 >剽窃:他人の作品・学説などを自分のものとして発表すること。
つまり、初心者がどっかで書いてたものをぱくったって言いたいのかな?w
>>965 必要かどうかの判定が *it ではなく it を使っているとしたら、そうはできないよね。
標榜あたりと勘違い?
>>968 「あたり」じゃなくて「そのもの」だと思われ。
970 :
デフォルトの名無しさん :04/04/11 23:10
質問970:LPVOID*型を引数とする関数について int func(LPVOID*) { ? } このようなLPVOID*型を引数にもち、そのポインタのポインタに 何らかの4バイトの結果を入れ、戻り値としてint型を返す関数が あったとします。 LPVOID pbuf; func((LPVOID*)&pbuf);//戻り値は無視する。 このように使えばその後で wsprintf(buf, "%d", *(DWORD*)pbuf); のようにして4バイトの値を得ることができました。 そこで、LPVOID pbuf;と宣言していたものを、LPDWORD pbuf; とだけ変更してもうまくいきました。 DWORD *pbuf;とだけ変更した場合もうまくいきました。 DWORD pbuf[1];とだけ変更した場合もうまくいくと思ったのですが、 wsprintf(buf, "%d", *(DWORD*)pbuf);の結果が他の宣言の場合と 異なり、予想外だったのです。 func関数にはメモリの実体のポインタのポインタを指定すれば いいようなんですが、なぜDWORD pbuf[1];とするとうまくいかなかった のでしょうか?
>>970 DWORD * pbuf;に対してのsizeof(pbuf)と、
DWORD pbuf[1];に対してのsizeof(pbuf)は
それぞれ幾つ?
>>970 func(LPVOID* pp)は、*(DWORD *)pp = 値 みたいな書き換えをしてるんだよな?
つまり、呼出元が渡したポインタ自身を書き換えると。
で、DWORD pbuf[1]; して、それを func((LPVOID*)&pbuf);として、
funcがポインタのつもりで書き換えてるんだよな?
でもこの場合pbufはポインタではないので
(LPVOID*)&pbuf は、 ポインタではなく最初の要素のアドレスを返す)
この場合のみアドレスではなく要素を書き換えていることになる感じ。
ちなみにLPVOIDとかLPDWORDとかはC++ではなくMicrosoftなどの勝手typedefだし
c-style cast前提なのはC++ではなくCの流儀だな。
973 :
デフォルトの名無しさん :04/04/11 23:41
>>971 ありがとうございます。
DWORD * pbuf;に対してのsizeof(pbuf)はポインタのサイズだから普通は4。
DWORD pbuf[1];に対してのsizeof(pbuf)もポインタのサイズだから普通は4。
これで間違いないでしょうか?
>>973 >DWORD pbuf[1];に対してのsizeof(pbuf)もポインタのサイズだから普通は4。
違う。DWORD一個のサイズ。まあ4というのは一緒だがたまたまだな。
Win64なんかだとポインタのサイズは8だったり。
なに的外れなことやってんの?
Cスレ逝けば?
誰だ名前空間なんて作ったのは。 おかげでバッティングだらけじゃないか。 なんでみんなstdなんだよヽ(`Д´)ノ
>>977 なんだなんだ?using namespace std; 厨が暴れているぞ。
980 :
デフォルトの名無しさん :04/04/14 23:45
コンソール出力を同時にファイルへ書き出す方法ってありますか? C言語限定で。
Cスレ逝けば?
String s = "str1"+"str2"; みたいな書き方を実現する方法ってあるでしょうか? String s = (String)"str1"+"str2"; しか思いつかないのです
String s = "str1" "str2";
>>983 右辺の型が任意の場合だと、キャストしかないですかね
>>984 多分。
s += str2;でいいじゃん
>>985 そのケースのみならそれでも良いのですが
どうもjavaの癖がついてしまっていろいろ面倒なのです。
スッキリしました。感謝。
>>984 任意の型の文字列化にキャストって……どの程度一般的な型を想定してる?
もっと広範な用途で任意の型と文字列ベースのやり取りするなら std::stringstream が使える。
構文は不格好になるし牛刀な感じはあるが、標準ライブラリの範囲であれば他にない。
キャスト式で見た目きれいに書きたいのなら boost::lexical_cast 使ってみるのも。
そろそろ次スレよろ。
cppllとってる人っている?
新聞かよ
>>989 cppll読んでるけどしたらばのcppll BBSもなかなか面白い。
>>989 アーカイブで読めるし無理に購読しようとは思わん。
下手に投稿しちゃうとスパム来るようになるし・・・
>>993 それよりFree News ServerとかIEでftpやる時にメールアドレスが
まともに登録されているとスパムが来るようになる罠。
次スレ立ててきまつ
comp.lang.c++.moderatedとかGotW読んでる人はいませんですかそうですか・・・
そろそろ千取り合戦か…
999
1000!!!!!!!!!!!!!!!
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。