1 名前:デフォルトの名無しさん [2010/03/05(金) 16:51:13 ] エスケープシーケンスやWin32APIなどの環境依存なものでもOK。 ただしその場合、質問者は必ず環境を書きましょう。 ※sage禁止です(と代々スレに書いてありますが自己判断で)。 【前スレ】 【初心者歓迎】C/C++室 Ver.71【環境依存OK】 pc12.2ch.net/test/read.cgi/tech/1264774545/ 【アップローダー】(質問が長い時はココ使うと便利) kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/joyful.htm codepad.org/ (コンパイルもできるし出力結果も得られるのでお勧め) ◆ソースのインデントについて 半角空白やTABでのインデントはスレに貼ると無くなります。 そのため、アップローダーに上げるのも手ですが直接貼る場合は、 全角空白か に置換すると見栄えだけはよくなります。
201 名前:デフォルトの名無しさん mailto:sage [2010/03/26(金) 23:07:45 ] Scoped Allocatorなら組み込みでも使えそうな予感
202 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 02:28:15 ] >>199 gccもそんなだったはず あとPODのときは要素数領域を確保しないとかあった気がする
203 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 06:41:37 ] PODじゃないけどデストラクタがない場合ってどうなんだろ? 確かめた事無いや
204 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 06:51:18 ] placement newのデストラクタがない場合?クラスが動的に領域を確保する 物じゃなければデストラクタを意図的に呼び出さなくても実害はなかったと思う 推奨されないけど
205 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 06:55:36 ] こんな感じか class A { int i; }; class B { int* p; public: B() : p(new int[100]) {} ~B() { delete[] p; } }; int main() { char c[1000]; A* ap = new (c) A; // ap->~A(); // 無くても実害はない B* bp = new (c) B; bp->~B(); // ないとメモリリークする }
206 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 07:29:32 ] いや、そういう話じゃなくて、 配列newで要素数を格納するのはデストラクタ呼ぶループのためだから (new側は要素数が分かるので特に必要はないはず) デストラクタがなければPODじゃなくても配列newで要素数分確保する必然性はないよね、と まあ確保しても実害は無いから自分で配列newを実装する場合は無条件で確保すればいいんだけど デフォルトではどうなってんのかな、と
207 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 08:25:35 ] >>206 じゃあこういう事か ちなみにCodeGuard掛けてみたが何のエラーも出なかったので恐らく 問題ないと思われる class A { int i; }; int main() { char c[1000]; A* ap = new (c) A[100]; // ap->~A(); // なくても実害はない }
208 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:09:46 ] いや、どう見ても>>203 が言いたいのは struct NonPod { int x; NonPod(): x(rand()) {} virtual int f() { return x; } }; みたいなものを new NonPod[n]; した時に、要素数を記録する領域を確保するのかどうか、だろ。
209 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:11:50 ] >>208 要素数は記録しない placement newの配列版で確保した領域を delete[] で解放しようとすると 鼻から悪魔
210 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:14:01 ] だから、>>203 の意図に placement new は関係ないっての
211 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:16:24 ] >>199 ,>>202-203 の流れだからな
212 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:17:48 ] もうひとつ。 どの処理系かも明記せずに「記録しない」なんて言い切るな。 思いっきり処理系依存だってことは皆わかってるんだから。
213 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:19:30 ] >>212 鼻から悪魔って規格票に書いてあるじゃん という事は要素数は記録しない
214 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:33:33 ] は?
215 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:35:28 ] >>214 >>209 お前さんも頭悪いな
216 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:36:15 ] つまり、華から悪魔と規格票に書いてない場合は 「要素数を必ず記録する」と書いてあるってーのか。 そもそも俺は「未定義」と書いてあるものは見た覚えがあるが 「華から悪魔」なんて書いてある規格は見たこと無いけどな。
217 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:38:35 ] >>216 だから「未定義の振る舞い」undefined behaviorだっつーの
218 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:38:59 ] >>213 どういう理屈だよw
219 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:39:27 ] つまり int * p = new int[n]; だと、要素数がどこにも記録されない、と規格のどこかに書いてあるのか? だから delete p[] ではなく delete p をしても見て意義動作ではないと。 ふーん。
220 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:40:22 ] >>219 馬鹿発見 placement newの配列版だと言ってるだろーが アホか
221 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:42:14 ] >>213 >>216 未定義の振る舞いである == 要素数を記録しない ってか? お花畑に住んでいるって幸せ?
222 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:44:24 ] 要素数を記録したら未定義の振る舞いにならないだろうが
223 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:45:14 ] だいたいplacement newはヒープ領域とは何の関係もないだろ
224 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:48:42 ] >>222-223 >>210-211 を10回読み直してみたらどう?
225 名前:デフォルトの名無しさん [2010/03/27(土) 14:49:53 ] >>222 勝手に決め付けるなよ
226 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 14:54:43 ] 知るかい 俺はあくまでもplacement newの配列版について話をしてるんだ
227 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 15:15:00 ] だから、てめーは「最初っからずーーっと」ズレたことしか言ってねーんだよ。 てめー「だけ」がズレてんだよ。 何が「俺はあくまでも」だ。 >>199 及び>>202-203 において、 「operator new[]()がPOD時は要素数の領域を確保しないが非POD時は確保する」話が出てる で>>203 が「じゃあデストラクタの無い非PODなら(operator new[]の動作は)どうなっているのか」 という疑問を出している。 なのに>>204-205 だの>>207 だの、完璧に論点がわかってない書き込みをしている。 >>206 で「そうじゃなくて」と指摘されているにもかかわらず、ズレまくり。 (言っとくが、>>197-206 の流れの中には俺の書き込みは一つも無い) しかも、「未定義動作である」とは「要素数を記録しないことである」という 他人には理解不能な理屈まで持ち出して。 >>203 はおそらく「(規格では何も決められていないだろうが) 個々の処理系ではどうなんだろう?」という疑問を出しただけなのに 勝手に「要素数を記録することが規格で決められている」ということにして。
228 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 15:17:21 ] あ、↑の「operator new[]()の動作」というのは違うか。 new[]演算子が「要素数分の領域を多めにoperator new()に要求する」が正しいかな。
229 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 15:19:50 ] >>226 今読み返してみたが、>>206 が「そうじゃなくて」と言っている内容の 「配列new」を勝手に「配置new」と読み替えてないか?
230 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 17:01:50 ] デフォルトではどうなってんだろ、ってんだから 明らかにplacement newではないだろ
231 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 20:53:10 ] 説明能力の無い人間がついうっかり自己評価高かったりすると、 そこら中の人間を馬鹿馬鹿言って暮らさなきゃいけないからたいへんだ。
232 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 22:35:11 ] 理解能力が足りない奴の方が始末に負えないけど
233 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 22:38:41 ] どっちもどっちだ
234 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 22:48:53 ] 無駄にプライドだけ高いから本当に邪魔
235 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 22:57:20 ] 人を変えようと思ったらまず自分が変わらにゃならんよ 自分が変わらずに他人を変えようと思っても、百万年掛けても1ミリも変わらないと思え
236 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 23:33:49 ] なんかすげー必死に張り付いてる奴が居るね。
237 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 23:48:13 ] というか分かってない奴1人だけだろ 人のせいにする前に周りをよく見ろと
238 名前:デフォルトの名無しさん mailto:sage [2010/03/27(土) 23:52:39 ] >>229 がズバリ核心を突いてるな
239 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 01:47:39 ] すみません.環境依存の質問なのですが longやintのサイズが64bitや32bitで変わる例はよく見るのですが shortやlong longが変わる実例ってあるのでしょうか? よろしくお願いします
240 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 02:21:23 ] >>239 short は -32,767 〜 +32,767 を表現できることが保証されている → 16bit 以上 long long は -9,223,372,036,854,775,807 〜 +9,223,372,036,854,775,807 を表現できることが保証されている → 64bit 以上 それ以外は決められていないから変わるかもしれない 実例は…… short が4バイトなコンパイラを自分で作ればいい
241 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 03:30:55 ] >>203 コンストラクタ・コピーコンストラクタ・代入演算子を定義したクラスで試してみた。 少なくともcodepadのgccは、デストラクタの有無のみ見てるみたい。 ttp://codepad.org/VXfU6shz
242 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 03:43:49 ] >>239 charのサイズが9ビットとか32ビットという環境は実在するので、たぶん shortやlong longもそれなりに変なサイズになると思う。 一般的なWindows/Linux/Macの開発環境では、64ビットターゲットであろ うと 16bit short、64bit long long しか見たことないね。
243 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 04:29:53 ] >>240 >>242 これは困りました・・・ ともあれ参考になりました ありがとうございます.
244 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 08:30:09 ] 困る・・・のか? stdint.h の int16_t, int64_t を使えばいいという話ではないのか
245 名前:デフォルトの名無しさん [2010/03/28(日) 15:29:14 ] C++でのメモリ確保について教えて下さい。 要素数が変動する配列の塊の為の領域を膨大な数確保するとします。 データ1[70] データ2[1] データ3[36] データ4[12] ・ ・ ・ そしてそれらを管理するアドレスの配列を作ります。 データ1の開始アドレス データ2の開始アドレス データ3の開始アドレス データ4の開始アドレス ・ ・ ・ このとき、領域確保はひとつずつnewとかで確保したほうがいいのでしょうか? それとも巨大な領域を自分で確保し、その中に隙間を詰めるようにデータを詰め込んでいく 管理クラスを自作するほうがいいのでしょうか? 前者のほうが簡単そうではあるんですが、C++の動作の知識があまりなくて以下の不安があります。 ・膨大な数こまごまと領域確保することで何らかの処理負荷が発生しないか? ・もしも適当に確保出来る空き領域見つけて確保する場合、隙間がまばらになって メモリが断片化され、本来可能な確保量よりも確保出来る容量が少なくなってしまわないか? データ領域は数万から最悪数百万個単位で確保し、頻繁に消したり、追加するとします。 宜しくお願いします。
246 名前:245 [2010/03/28(日) 15:32:43 ] なお、vectorなどの存在は知っているのですが、その場合、準備している容量を超えた場合、 領域の再確保によってデータのアドレスが変わってしまいます。 プログラムはデータのアドレスを記憶して情報をやり取りする部分が多いのでvectorは考えていません。
247 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 15:38:42 ] >>245 データは単独でnewすればかまわない。よっぽど多い場合はプールなどを使うが、たいていの場合はnewで事足りる。 そこへのポインタをvectorに保持すればいい。ポインタだけを保持するならベクターの伸張じの問題は関係なくなる。 vectorに直接ポインタを入れるとdeleteが面倒なのでshared_ptrを使うのが楽だ。
248 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 15:43:19 ] int main() { int *p = new int; cout << p << endl; p = new int; cout << p << endl; delete p; return 0; } は間違ってますか? 最初のpはリークになる?
249 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 15:46:00 ] >>248 リークする。 2回newでdelete1回だから確実。
250 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 15:49:13 ] >>245 データの要素数に関する統計情報がないことには、 newで十分としか言えない。 ただ、要素数より余分に確保して、決まったサイズの倍数に揃えることで、 一般的には断片化を減らすことはできると思う。
251 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 15:49:15 ] >>249 即レスありがとうございます。 同じ変数は使いまわししないのが基本ですか?
252 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 15:58:57 ] >>251 うん。 使いまわしても一切メリットがないばかりか、読みにくいし最適化の妨害になる。
253 名前:245 [2010/03/28(日) 16:10:23 ] >>247 有難うございます。ただやはり不安なのは、OSから見てプログラムがメモリのここからここまでを使用したいと予約(newで確保)すると思うのですが、 その予約した領域のデータ(ここからここまで)を保持しないといけないと思うのですが、最悪数百万個のデータを確保する場合、 前者では開始(アドレス+終了アドレス)*数百万個分のメモリを占有してしまい、後者だと(開始アドレス+終了アドレス)の一個のみで済み 前者だとそれだけでメガ単位のメモリ消費してしまわないのでしょうか? >>250 有難うございます。なるほど、例えば要素数を10区切りで判定してその区切りで確保することにより、 一度開放されて歯抜けになった領域に新しいデータがすっぽりはまる可能性が高まるということですね? 参考にします。
254 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 16:17:03 ] >>253 ヒープの管理領域のこと?100万でも10数メガだしwindowsなら問題ないだろう。 それよりもヒープの最大サイズを気にしたほうが良くないかな。
255 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 16:22:51 ] >>253 先ずは愚直に作ってみたら? それを動かしてみれば問題点もより判り易いだろうしデバッガで追うなどして知見を得られるチャンスも増える。 始めから高性能を目指したら、デバッグの段階で二進も三進もいかなくなるぞ。
256 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 16:34:33 ] データは後ろに追加するだけなわけ? それならdequeを使うといいよ。 dequeは後ろに追加するだけならメモリの再配置は起こらない。
257 名前:245 [2010/03/28(日) 16:48:23 ] >>256 有難うございます。 データ群の中間から抜いたりも行いますが、別の箇所では使えるかも知れません。 >>254 >>255 有難うございます。 実験的というか自分のプログラム技術の向上の為のトレーニングを兼ねて以下の仕様にしようとおもいます。 ・メモリプールで大きな領域を確保する。 この領域を超える場合は段階的に追加確保する。 ・要素数は5個、10個、15個などの単位で確保する。 これは開放により歯抜けになったところにすっぽりはまりやすくするため。 またメモリプール使用により他のアプリケーションによる妨害がなくなり よりはまりやすくなる。
258 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 17:05:40 ] vector<T*> data; deque<T> pool; queue<T*> recycle; を用意して、 ・データは基本的にpoolから取ってきてdataにアドレスを入れて使う ・使い終わったデータはdataから削除してrecycleにアドレスを入れる ・recycleにデータが残ってる場合はpoolを無視してrecycleからdataにアドレスを移す こんな感じでいいんじゃない
259 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 17:14:24 ] メモリプールって汎用化するより目的別に頭ひねってそのつど最適化した方が良くね?
260 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 17:15:09 ] >>257 技術を向上させたいと思うなら先にこれを読んでおけ。 ja.wikipedia.org/wiki/%E6%9C%80%E9%81%A9%E5%8C%96_%28%E6%83%85%E5%A0%B1%E5%B7%A5%E5%AD%A6%29 不安や想像をもとにコードを複雑化させるのは優れた技術者のすることではない。
261 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 17:18:00 ] 有難うと言いながら、>255を無視してて笑える。
262 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 17:18:46 ] 百万単位でnew/deleteが頻繁に行われたらそりゃ試すまでもなくパフォーマンス落ちるわ
263 名前:デフォルトの名無しさん mailto:sage [2010/03/28(日) 23:09:23 ] だいたい、何を学習したくてそんなもん作ろうと思ったのか 百万のオーダーだと、メモリ云々よりレスポンスのほうが問題になりそうだが
264 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 10:22:58 ] 百万単位でnew/deleteを頻繁に行うプログラムって何? どこかの人気サーバーでも扱ってんのかな?
265 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 13:26:29 ] プリコンパイル済みヘッダーを使う際、中に defineで中身が変化するテンプレートを入れても 問題ないでしょうか? やはり読み込み方によっては問題あり?
266 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 19:04:37 ] newに対してdelete[]はしちゃいけないもの? もしくはポインタの中身を何らかの方法で単体か配列か区別する方法は無いものですか?
267 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 19:10:31 ] コンパイル前にノーマルnew/deleateを配列new/deleteに置換えるスクリプト走らせればいい。
268 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 19:10:40 ] >>266 単体ならスマートポインタを、配列ならSTLコンテナを使えばそんな心配は要りません。 つーか、JavaScriptの悪夢の再現になるからポイント先が配列かどうかを判定するなんてことは考えない方がいい。
269 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 19:11:21 ] >>266 > newに対してdelete[]はしちゃいけないもの? だめ。未定義の動作。鼻から悪魔が出るかも。 > もしくはポインタの中身を何らかの方法で単体か配列か区別する方法は無いものですか? ない。 T* p = new T; T* p = new T[10]; T a(0); T* p = &a; pがこの3つのどれなのかすら判定不可能。
270 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 19:14:08 ] > 配列ならSTLコンテナを使えば boost::shared_arrayってのもあるぜよ!
271 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 22:05:27 ] boostのプールって纏めてとる→足りなくなったらまた纏めてとる→まとめて破棄ってしてるの? 最後のまとめて破棄をしなかったら延々とメモリ食付していくのかな?
272 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 22:10:18 ] make_sieve内のfree(sieve)で死ぬんけど何が原因? kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/10555.txt 環境 コンパイラ:VS2008 OS:XP SP3 その他:BCCだとエラーを吐かない 今気づいたけど終了時にprimesを開放してないのは気にしないで・・・
273 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 22:40:24 ] >>272 Error 00001. 0x130610 (Thread 0x0EEC): Access overrun: Attempt to access 4 byte(s) at 0x00B8F550+4000, that is at offset 0+4000 in heap block 0x00B8F550 which is only 4001 bytes long. | sieve1.c line 27: | if(sieve==NULL) exit(1); | |> for(i=0;i<=limit;i++) sieve[i]=0; | for(i=4;i<=limit;i+=2) sieve[i]=1; | for(i=3;i<=limit/2;i+=2){ Call Tree: 0x0040123C(=sieve1.exe:0x01:00023C) sieve1.c#27 0x004011A3(=sieve1.exe:0x01:0001A3) sieve1.c#13 0x32AD8D9E(=CC32100MT.DLL:0x01:0D7D9E) The memory block (0x00B8F550) [size: 4001 bytes] was allocated with malloc | sieve1.c line 24: | void make_sieve(int limit){ | int i,j,idx,cnt; |> int *sieve=(int*)malloc(sizeof(int)*limit+1); | if(sieve==NULL) exit(1); | Call Tree: 0x0040121A(=sieve1.exe:0x01:00021A) sieve1.c#24 0x004011A3(=sieve1.exe:0x01:0001A3) sieve1.c#13 0x32AD8D9E(=CC32100MT.DLL:0x01:0D7D9E) なんか一杯エラー出る 範囲外をアクセスしてるみたいだね
274 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 22:41:25 ] はーん malloc(sizeof(int)*(limit+1)); の間違いじゃねーの?
275 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 22:47:02 ] int x = 0xXXXXXXXX; unsigned int y = static_cast<unsigned int>(x); このキャストで最上位ビットは標準で必ず維持されますか?
276 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 22:59:13 ] >>273-274 それだ!!指摘されるまで気づかなかった俺アホすぎるw サンクス
277 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 23:27:22 ] >>265 プリコンパイルヘッダーをインクルードする前に、意味のある文を書いてはだめ。 だからdefineによる変更はできない。
278 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 23:49:30 ] >>265 例えばVCではこんな制限がある。 ttp://msdn.microsoft.com/ja-jp/library/fey8ayyf.aspx defineを変更するたびプリコンパイルをやり直せばいいんじゃない?
279 名前:デフォルトの名無しさん mailto:sage [2010/03/29(月) 23:55:26 ] 別人だが横レス。 つまりプリコンパイルヘッダを複数用意しろ、と?
280 名前:デフォルトの名無しさん mailto:sage [2010/03/30(火) 01:14:17 ] プリコンパイル使うのをやめるという方法もある
281 名前:デフォルトの名無しさん mailto:sage [2010/03/30(火) 01:41:18 ] プロジェクトのフォルダ構成でいいやり方ないかな boostをマネしようかと思ったけどソース見てもboostがどういうルールでやってるのかわからんかった・・・
282 名前:デフォルトの名無しさん mailto:sage [2010/03/30(火) 02:11:54 ] >>281 今がどんな構成で、それの何が気に入らないのか述べよ。
283 名前:デフォルトの名無しさん [2010/03/30(火) 15:53:11 ] WindowsでCPUの周波数を取得する方法を教えてください
284 名前:デフォルトの名無しさん mailto:sage [2010/03/30(火) 16:20:33 ] T& GetT(); T const& GetT() このようにメンバ関数の返り値がconstと非constのオーバーロードは可能なのでしょうか?
285 名前:デフォルトの名無しさん mailto:sage [2010/03/30(火) 19:31:15 ] T& GetT(); T const& GetT() const; これなら可能。 obj.GetT() として objがconstならば後者が、 そうでなければ前者が呼ばれる。
286 名前:デフォルトの名無しさん mailto:sage [2010/03/30(火) 21:07:04 ] >>277-278 やはり問題がありそうですね。 実際使ってるのはBCBなんで、VCを真似して 専用のヘッダー作って同一になるようにしときます。 ありがとう。
287 名前:デフォルトの名無しさん mailto:sage [2010/03/30(火) 22:07:09 ] char (*a)[4] = new char[10][4]; のdeleteはdelete(a)、それともdelete [] (a)? 自分delete [] (a)と思うんだけど、どう? delete(a)だとメモリリークにならないの? これでも全て開放されるの
288 名前:デフォルトの名無しさん mailto:sage [2010/03/31(水) 00:52:34 ] >>287 delete[]を使いましょう new char[10][4]; の10は変数でもよく、char (*)[4]、つまりchar型の 要素数4の配列へのポインタを配列確保する演算子なので、deleteは []を付けないとメモリリークします、というより未定義の動作です
289 名前:デフォルトの名無しさん mailto:sage [2010/03/31(水) 17:26:59 ] C/C++について基本的な事かもしれませんが、ポインタと配列について質問させて下さい。 int[] a; int* p1 = a; はわかるのですが、 int* p2, p3; p2 = a; *p3 = a; の違いがいまひとつはっきり理解できません。 また、次のようにした時、ポインタはどこのアドレスを指すのか想像がつきません‥ p2 = &a; *p3 = &a; よろしく御指南のほどお願いいたします。
290 名前:デフォルトの名無しさん mailto:sage [2010/03/31(水) 18:12:46 ] >>289 aがint型の配列だとして、 p2はaのアドレスをintのポインタからアクセスできるように コピーしている正常な記述。 *p3は、確保もされていないどこかの領域を指す不定なポインタに、aから取得できるアドレス値を 書き込んでいる不正な記述。 &aの方は、多分処理系が把握しているどこかのアドレスをそれぞれコピーしたり 不正な書き込みをしようとしているっていうかヤメロ
291 名前:デフォルトの名無しさん mailto:sage [2010/03/31(水) 18:16:07 ] int *p2 ,p3 ってint型ポインタp2とint型変数p3の確保じゃないか?
292 名前:デフォルトの名無しさん mailto:sage [2010/03/31(水) 18:20:08 ] >>289 そのコードは、いくつかコンパイルが通らないところがある。 > int* p2, p3; あとこれもp2がintへのポインタ、p3がintになるC/C++の罠。 p2 = a; ポインタが指すアドレスを変えるのはこれ。 p2 = &a; これはポインタへのポインタみたいなことになる。 *p3のように間接参照演算子をつけると、ポインタが指すアドレスを参照する。 つまり、*p3=aのような代入は、ポインタのアドレスを変えるのではなく、ポインタが指すメモリ(変数)の値を変える事になる。
293 名前:デフォルトの名無しさん mailto:sage [2010/03/31(水) 18:50:32 ] >>289 基本的な事と前置きがあり、たまに誤解して覚えてる人、また間違った説明をする人がいるので 念のためついでに書いておくと、 C/C++ には、例えば 「intのポインター"型"」 のような物は存在しない。これ重要。 あくまで、「int として扱われる、どこかのメモリ領域を指すポインタ」 であって、これは型じゃない。 つまり読み方として、その例は 「int*」 の 「p2」 でなく、「int」 の 「*p2」。 実際の用法については >>292 氏のレスを参照してもらうとして、老婆心だけどメモしておくと、 そもそも変数の宣言は、 int x; とあったとき、最初の int は(例えば整数が32bitだとすると)、「intとして扱う、4バイトの領域」 という意味でしかなく、 まだこの瞬間には物理的にどこかのアドレスには何も確保されていない。 そして次に x と、変数名が来たとき、 どこかにメモリが4バイト分確保され、それをあらわす名前として x が割り当てられている、という動きになる。 これを踏まえて、 int *y; は、最初の int で int として扱う4バイトの領域という型が宣言され、その次の * は、ワイルドカードの * と似た意味で、 「どこかのアドレス」 という意思を表している。 つまり int * だ。 で、しかしこれだけだと流石にその後扱えないので、その次でこれ自体に名前を求めている。これが y 。 そんな訳で、この例の場合、型としてはあくまで int。 そして変数として、それはポインタと宣言されているって意味の記述になるから、 int* z; ではなく、 int *z; でなければならない。 こんな基礎。
294 名前:デフォルトの名無しさん mailto:sage [2010/03/31(水) 18:56:39 ] もう一つ追記しておくと、つまり int x; は、どこか物理的な格納先が割り当てられたもので、それを指す名前が x という意味であり、 int *y; は、どこだかわからない(どこでもいい = *)格納先を示すもので、それを指す名前が y って事。 そしてどちらかも型としては int 。 ・・・って、 でも実際には int のポインター型 みたいに扱えないと不便なので、まるで型のように振舞ってはいるんだけど。キャストとか。
295 名前:デフォルトの名無しさん mailto:sage [2010/03/31(水) 18:58:08 ] 仕様書にpointer typeは出てきますが。
296 名前:デフォルトの名無しさん mailto:sage [2010/03/31(水) 19:02:50 ] 自殺してくる
297 名前:デフォルトの名無しさん mailto:sage [2010/03/31(水) 19:03:07 ] C++では int[] a; 表記OKになったんだ これはint配列を指すポインタ aを表すの? まさか参照じゃないよね
298 名前:デフォルトの名無しさん mailto:sage [2010/03/31(水) 19:05:23 ] Java臭いな
299 名前:デフォルトの名無しさん mailto:sage [2010/03/31(水) 19:07:03 ] どこかのスレで「ポインタ」と「ポインタが指す先」を「宝箱の地図」と「宝箱」で解説しているのを思い出した。 int x; // 「int型の宝箱」 int* y; // 「int型の宝箱」の地図 y = &x; // &でxの地図を取得してyに代入 *y = 10; // 地図であるyが指す宝箱への代入
300 名前:デフォルトの名無しさん mailto:sage [2010/03/31(水) 19:25:24 ] >>293 型が無いって断言しちゃうのはあれだけど、大体言いたいことは合ってる。 何々型の、何々 って記法で、何々=変数名の方を修飾する・・・例えばポインタをあらわす*や配列を表す[5] のようなものは、 なんて言ったらいいのかな・・・ 型の宣言が2段構えになってるようなイメージで捉えればいいんじゃないかな。 ただJavaやC#のような言語の場合は、その辺すっきりまとめて全部同じような型としちゃう傾向があるから、 そっちと混同すると混乱する可能性はあるような気がする