[表示 : 全て 最新50 1-99 101- 201- 301- 401- 501- 601- 701- 801- 2chのread.cgiへ]
Update time : 07/16 11:48 / Filesize : 200 KB / Number-of Response : 824
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

C++相談室 part61



1 名前:デフォルトの名無しさん mailto:sage [2008/03/09(日) 19:37:43 ]
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレに
お願いします。

55 名前:デフォルトの名無しさん mailto:sage [2008/03/13(木) 00:24:47 ]
it->first != key
lower_boundの戻り値はpairじゃないよな。確かキーだよな。

ソート基準がデフォのlessならこうか。

if(it != map.end() || !(key < *it)) {
//found
} else {
//not found
}

56 名前:デフォルトの名無しさん mailto:sage [2008/03/13(木) 00:26:26 ]
||じゃなくて&&だわ

if(it != map.end() && !(key < *it)) {
//found
} else {
//not found
}



57 名前:デフォルトの名無しさん mailto:sage [2008/03/13(木) 00:37:32 ]
>>55
lower_bound()の戻り値はpairだよ。
・・・というより、map<k, v>::value_typeがpair<k, v>だ、と説明するほうが、根本的で適切かな。
std::コンテナ::iteiratorは、std::コンテナ::value_typeのポインタ的に動作するわけだから。

>>53-54
「厳密には」こう書くべき。
if (it == map.end() || map.key_comp()(key, it->first) {

58 名前:デフォルトの名無しさん mailto:sage [2008/03/13(木) 00:38:36 ]
ごめん訂正。
- map<k, v>::value_typeがpair<k, v>
+ map<k, v>::value_typeがpair<const k, v>

59 名前:デフォルトの名無しさん mailto:sage [2008/03/13(木) 00:46:26 ]
>>57
ああ、そうだね。elementの型がpairだた。スマソ。

60 名前:デフォルトの名無しさん [2008/03/16(日) 05:51:19 ]
テスト

61 名前:デフォルトの名無しさん [2008/03/16(日) 05:55:48 ]
class B;

class A
{
B b;
};

class B
{
A a;
};

と書いたところ、
エラー出ます><。
どう対処すればいいですか?


62 名前:デフォルトの名無しさん mailto:sage [2008/03/16(日) 06:04:28 ]
よく考えようぜ。
A の中に B がある。
その B の中に A がある。
その A の中に B が・・・

あり得ない。


とりあえず何をしたいのか整理しよう。
大抵の場合は、

1. クラス設計を変更する。
2. a と b のどちらかを参照にする。

のどちらかになる。

63 名前:デフォルトの名無しさん mailto:sage [2008/03/16(日) 06:31:59 ]
haskellを使う



64 名前:デフォルトの名無しさん mailto:sage [2008/03/16(日) 07:41:30 ]
>>61
Aの中に持ちたいのはBそのものじゃなくて、Bの参照なんじゃね?

65 名前:デフォルトの名無しさん mailto:sage [2008/03/16(日) 15:02:01 ]
>>62
循環して持ちたいのはよくあること。
やるなら>>64のようにすればいい。

同じような質問見つけてきたんで参考にどうぞ。
www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=36231&forum=7

66 名前:デフォルトの名無しさん mailto:sage [2008/03/16(日) 15:45:33 ]
62にそう書いてるじゃん

67 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 03:49:28 ]
くだらない質問で申し訳ないのだけど、どなたか教えてください
クラスのコンストラクタで関数名の後ろにつけている初期化みたいなものの意味を教えてください

hoge::test() : a(0),b(0),c(0)
{
...
}

この場合だとa=0,b=0,c=0?
だとしたらなぜ...のところに書かないのですか?

68 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 04:07:50 ]
test

69 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 04:11:10 ]
test()じゃエラー出ると思う

hoge::hoge() : a(0),b(0),c(0)
{
...
}
のことだよね
aが変数だと問題ない?けど

aがクラスの場合、aのコンストラクタに0という引数渡すということ。

class a{
public:
a(int value);
};
みたいなクラスの場合、aのコンストラクタに数値渡さないと作成できないし

70 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 04:29:44 ]
変数とクラス名が同じだとエラー出るや

class A{
public:
A(int value);
};

class hoge
{
A a;
public:
hoge() : a(0)
{
...
}
};
ってこと
この場合
...の所に a = 0; って書けない

71 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 08:54:36 ]
>>67
前者は初期化で、後者は何らかの初期化、または未初期化で構築の後、代入だな。
どちらでも良い場合はあるけど、意味は明確に違う。

例えばconstが絡んだ場合とか、

class hoge{
const int a; //constなので代入できない。
};

>>69のようにメンバの構築に引数が必要な場合とか。

未初期化な変数を嫌ったり、デフォルトコンストラクタの後に代入するような
効率の悪さを嫌ったり、色々あるからできるだけ初期化を使う。


72 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 10:11:47 ]
CとC++の違いを徹底解説!みたいな本に
Class::Method():field(0),field1(0)
{
}
なんて書いてあってさ、
何だよコンパイラバグってんじゃねーか!とか思ったころがあった

73 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 10:39:23 ]
>>72 本の名前晒しといてくれ。



74 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 10:40:42 ]
ていうかさ、constメンバや参照メンバもそうだけど
基底クラスの初期化も、この形式じゃないと出来ないよ。

もちろん、引数なしのデフォルトコンストラクタでの初期化は可能だけど。

75 名前:72 mailto:sage [2008/03/17(月) 11:55:05 ]
「オブジェクト指向言語C++入門 Cとの違いを徹底追求」
これかな。
やっぱり古いのもあってか、<string.h>とか、
namespace、例外の話はまったくなかった。
それ意外と、多少の誤植を除けば、解り安くもなければ解りづらくもない中立的な本だった。

まぁ、今となっては読むべき本じゃないわな

76 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 13:02:50 ]
低レベルな質問は初心者スレでやれ

77 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 15:16:38 ]
>>76
おまえが、↓に行け

C++上級者が集まるスレ
pc11.2ch.net/test/read.cgi/tech/1095113801/


78 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 16:49:26 ]
関数の戻り先アドレスがバッファオーバーランで壊されているようなんですが、どこで壊されているのかが分かりません。

a(){

b();

}

b(){

// ログに戻り先アドレスを記録

/* 処理1 */

// ログに戻り先アドレスを記録

/* 処理2 */

// ログに戻り先アドレスを記録

return;
}

あたりをつけるために、上のように処理の区切りで関数の戻り先アドレスをログにはき出そうと思うんですが、
戻り先アドレスをどのように参照していいかが分かりません。

もし分かりましたら、参照方法を教えてください。
よろしくお願いします。

79 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 17:02:46 ]
環境に依存します

80 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 17:17:10 ]
>>78
そこまで推測できているならデバッガでスタックにトリガ張ればすぐだろうし、
そうでなくてもコンパイラにスタックのチェックをするオプションがあったりしないか?
そもそもバッファオーバフローだと判っているなら関数内のポインタを全部洗えばいいだけじゃん。
# 巨大関数だったらしらねw

81 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 17:27:32 ]
>>79
失礼しました。
Windows2000 VC++6です。

>>80
それが、1ヶ月に1度位しか発生しないエラーなのでトレースが困難なんです。
各所にログを埋め込み、関数から戻ってこないのは確認できたので、戻り先アドレスが壊されているらしいと推測したんです。
次はどこで壊されるかをログに記録し、また1ヶ月待ってみようと思いましてw

82 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 17:30:16 ]
espでも記録しておくとか

83 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 17:46:56 ]
>>81
>79の時点でスレ違いだと気付こう。
>そうでなくてもコンパイラにスタックのチェックをするオプションがあったりしないか?



84 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 18:21:17 ]
>>83
申し訳ありませんでした。
色々なアドバイスありがとうございました。

85 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 21:45:50 ]
const T &なメンバをもつクラスを作ったんだが、
ひょっとして、コピーする手段がない?

86 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 21:51:54 ]
クラス初期化にしかconst T &は初期化できないから
まぁなんというか頑張れ

87 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 22:03:17 ]
コピーコンストラクタならおkだが、operator=はダメだろうな

88 名前:デフォルトの名無しさん mailto:sage [2008/03/17(月) 22:47:28 ]
const_ca

89 名前:デフォルトの名無しさん mailto:sage [2008/03/18(火) 00:27:05 ]
なんで&があるん?
*だけじゃ駄目なん?

90 名前:デフォルトの名無しさん mailto:sage [2008/03/18(火) 01:01:24 ]
駄目です

91 名前:デフォルトの名無しさん mailto:sage [2008/03/18(火) 01:23:09 ]
なんで

92 名前:デフォルトの名無しさん mailto:sage [2008/03/18(火) 01:24:56 ]
インラインアセンブラ使えばコピーできないことはないだろうが
当然おすすめはしない。

93 名前:デフォルトの名無しさん [2008/03/18(火) 01:32:09 ]
関数gがコンパイルエラーになります。なぜですか?不可解です。

class X {
protected:
  int val;
};

class Y : public X {
public:
  void f(Y* p) { p->val = 0; } // OK
  void g(X* p) { p->val = 0; } // エラー
};



94 名前:デフォルトの名無しさん mailto:sage [2008/03/18(火) 01:53:29 ]
X::valはYから見ればprivate
Y::X::valはYから見ればpublic

95 名前:デフォルトの名無しさん mailto:sage [2008/03/18(火) 01:55:26 ]
あ、いや、privateというべきじゃなくprotectedでいいのかな。どっちだろ。
いずれにせよYからX::valは触れない。Y::X::valなら触れる。

96 名前:93 mailto:sage [2008/03/18(火) 02:05:40 ]
>>95
やっぱりそうですか。なんとなく奇妙な言語仕様に思えるのですが。。。

97 名前:デフォルトの名無しさん mailto:sage [2008/03/18(火) 02:21:17 ]
じゃなぜこういう風に難解なルールになっているか逆に考えてみればわかる。

class Y2 : public X {
 void f(Y* p) { p->val = 0; }
};

というXを継承した別のクラスを作ってみよう。YとY2は別のクラスなのでY2から
Yのprotected属性のメンバ変数が変更出来てはまずいのに、もしこのような
ルールがなかったら上の例で可能になってしまう。

モジュールの隠蔽が破られないように特別なルールが作られているわけだ。

98 名前:93 mailto:sage [2008/03/18(火) 02:33:25 ]
なるほど。なんとなくですが、分かりました。

99 名前:デフォルトの名無しさん mailto:sage [2008/03/18(火) 07:13:26 ]
fseekgでstr.length()分を戻したいのですけど、
単にマイナスをつけて、-str.length()とするとイミフな数値しか出ません。
何でうまくいかないんでしょうか?

100 名前:デフォルトの名無しさん mailto:sage [2008/03/18(火) 07:39:13 ]
事故解決しました。 length()が返すのはsize_typeで、
size_typeはsize_tのunsigned intみたいだからですね。

101 名前:デフォルトの名無しさん mailto:sage [2008/03/18(火) 20:26:40 ]
出しかたによる。

102 名前:デフォルトの名無しさん mailto:sage [2008/03/18(火) 20:37:42 ]
>>100
環境依存の話すんなくそったれ

103 名前:デフォルトの名無しさん mailto:sage [2008/03/18(火) 22:02:40 ]
この言語機能多すぎじゃね?



104 名前:デフォルトの名無しさん mailto:sage [2008/03/18(火) 22:14:29 ]
必要な部分だけ使え

105 名前:デフォルトの名無しさん mailto:sage [2008/03/18(火) 22:23:31 ]
>>102
少なくともsize_typeは符号無しということは標準で決まっている事柄だったと思う。

106 名前:デフォルトの名無しさん mailto:sage [2008/03/18(火) 23:49:31 ]
>>105
unsigned intとどこに書いてある?

107 名前:デフォルトの名無しさん mailto:sage [2008/03/19(水) 00:00:40 ]
お前は何を言ってるの?

108 名前:デフォルトの名無しさん mailto:sage [2008/03/19(水) 00:22:24 ]
>>106
それは規格のどこにも書いていないが、
例えばもし99=100が使っている実装のsize_typeが
仮にunsigned longやunsigned shortだったとしても、
99=100は同じように質問して同じように解決していたに違いない。

たまたま100の使っている実装でsize_typeがunsigned intだったこと以外は
標準C++で普遍的に成り立つ話じゃないか。

109 名前:デフォルトの名無しさん mailto:sage [2008/03/19(水) 00:24:39 ]
size_typeは符号なし整数。
ただしbit数は決まってない。

110 名前:デフォルトの名無しさん mailto:sage [2008/03/19(水) 06:33:43 ]
>>108
頭の悪い子って、「話の行きがかりで登場したディテール」と「そのディテールに依存した話」の違いが
わからないから困るよね。

少なくとも、「環境依存の話すんなくそったれ」と「unsigned intとどこに書いてある?」の2レスより、
「でも規格で決まってるのはunsignedってことだけだから注意」とか書くほうが簡潔で有用。
非・馬鹿は最初からこう書く。

111 名前:デフォルトの名無しさん mailto:sage [2008/03/19(水) 07:24:46 ]
size_t が unsigned long のこともよくあるしな。

112 名前:デフォルトの名無しさん mailto:sage [2008/03/19(水) 09:04:06 ]
unsigned short だったりすると -length() しても int 型で普通に負の数になったりして。

113 名前:デフォルトの名無しさん mailto:sage [2008/03/19(水) 12:28:38 ]
std::cinで文字や数値を入力するとバッファに改行文字が残るようで、
その後に std::getline(std::cin, buf, '\n'); とかやらせると残った改行文字だけ読み込んでしまいます。
バッファをクリアする方法がないかと調べてみたのですが、
環境に依存せず確実にクリアする方法はない、という記述がありました。

こういう場合はそもそもstd::cinを使わないようにするのがよいのでしょうか?
fgetsとかを代わりに使えば改行文字まで読み込んでくれるみたいなのですが、
std::cinの方がすっきりしたコードになるので、他に問題を回避する方法がないか探しています。



114 名前:デフォルトの名無しさん mailto:sage [2008/03/19(水) 12:45:02 ]
>>113
cin.ignoreを呼ぶとかcin.getを繰り返すとかで十分では?

115 名前:デフォルトの名無しさん mailto:sage [2008/03/19(水) 12:49:09 ]
ああ、なるほど。
この場合はバッファに残るのが改行文字一個だけと分かってるから、それで十分なんですね。
ありがとうございました。

116 名前:デフォルトの名無しさん mailto:sage [2008/03/19(水) 15:15:14 ]
cinから一行読み込み+istringstreamで良くね?
string line;
getline(cin,line);
stringstream linestream(line);

117 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 15:40:59 ]
#define Max 1000

みたいなのを、グローバル変数を使って

const int Max = 1000;

とした方が良い(型指定ができるから)、と読んでる本で出てきました。
色んな所で「グローバル変数はできるだけ使うな」と言われていたのでびっくりしてしまったのですが、
こうやってconstにして#defineの代わりにするのは例外的によく使われるものなのでしょうか?

118 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 15:46:50 ]
defineよりはマシってだけの話。

119 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 15:52:08 ]
グローバル変数の議論とはまた別の話しだろ

120 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 15:56:36 ]
>>117
グローバル変数がダメなだってだけ覚えてて、なぜダメなのか考えたこと無いみたいだね?
大雑把に言うとどこで変更してるか分からないから把握しづらいといったとこです

const つけた場合(やろうと思えばできるけれど)変更できないので、そういう害は無い

121 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 15:58:48 ]
あほすぎるw

122 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 16:53:57 ]
別の翻訳単位で参照する可能性のある“変数”ならグローバル変数を使う。
別の翻訳単位で参照する可能性のある“数値”なら#define定義のあるヘッダを各自インクルードすればいい。

123 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 17:11:37 ]
>>122
なに言ってんの?w



124 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 17:12:31 ]
const ついてるやつはグローバル定数と呼ぶべきもの。

125 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 17:17:00 ]
>>117
グローバル変数に限らず、「○○はよくない」などと言われる物は絶対にダメという意味ではない。
○○以外の有効な手段があればそれを選べという意味であって、○○が有効となる限られたケースでは使っていい。

126 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 17:18:31 ]
理由を理解せずに規約に従っても意味がない事の典型だな

127 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 18:31:27 ]
>117
基本的にマクロは(特定の使い方以外)使わない方がいい。
マクロはプリプロセスで処理されてしまうため、コンパイルエラー時に酷い目に会う。
グローバル変数も使い方が難しいけど、コンパイラが識別できるものなのでマクロより余っ程マシ。
エラーが発生してもあくまで“変数”なので、マクロと違って識別名が普通に表示されるので
トレースしやすい。

因みに言うと、グローバル変数にするかどうかは「その値がどの範囲まで影響するか/正しいか」というのを
考えて決めるべき。プログラム中で一意な定数は積極的にconstグローバル変数にすべきだわな。

……しかし、こういう「疑問点を自ら追求する力を付ける」のがゆとり教育だったはずなんだけどね。
やっぱり失敗だったのか……

128 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 18:37:15 ]
なんで勝手に117をゆとり教育を受けた人認定してるんだよ

129 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 18:41:28 ]
エスパーするとC++でなく、Cの人が居ます。
「const リンケージ」でググって下さい。

>>117
C++で、それはただの定数で
変数のように書き換えることは出来ません。

グローバル変数が嫌われる主な理由は、
どこで書き換えられるか、把握し辛いことにあるため、
定数には当てはまりません。

130 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 18:56:40 ]
どう見てもゆとりです、本当にありがとうございました。

131 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 20:02:06 ]
1. マクロ定数はアドレスを完全に持たない。
 (const 定数はアドレスを取得しようと思えばできるが、
  アドレスを取得しさえしなければデータがデータメモリ上に置かれるとは限らない)

2. const 定数は名前空間に所属できる。
 (マクロには名前空間がないため、名前被りが発生する可能性が大きい)

3. 値を求めるのに何らかの処理を伴う定数を使う場合、マクロだと毎回コードが埋め込まれてしまう。
 (最適化が効く範囲ならいいのだが)

4. const 定数の方がコンパイルエラーが読みやすい。
 (マクロの場合、置換後のテキストを元にしてエラーが出力されてしまう)

5. マクロの場合、型を明確に指定するには明示的なキャストが必要になる場合がある。
 (見た目の問題でしかないと言われればそれまでだが)

6. ローカルスコープ内であっても、マクロ定数と同名の識別子を作ることはできない。
 (作れない方がいいという意見もあるのかもしれないが)

7. const 定数を使うと副作用が一切無いことが明示される。
 (キャスト演算子をオーバーロードしているクラスのオブジェクトの場合は例外だが)

132 名前:デフォルトの名無しさん [2008/03/21(金) 11:21:21 ]
質問があります。

動的配列を解放するときは要素数とかバイト数を指定しなくても

delete [] p;

でokですが、これはポインタpが指している動的配列の先頭バイトの
前に4byteの領域が確保されていて、ここに動的配列のバイトサイズ
が格納されているから、delete時にサイズを指定する必要がないと
聞いたことがあります。

しかし、動的配列の総バイト数はわかるとしても、要素のバイト数
の情報はどこに格納されているのでしょうか?

int *p; なら1要素のバイト数は4、double *p; なら1要素のバイト数は
8ですが、実行時にこの情報はどこから取得するのでしょうか?

ポインタpそのものは先頭1バイトのアドレス情報しか保持して
ませんから、こういう疑問をもった次第です。

133 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 11:30:24 ]
ポインタそのものにそのアドレスに何が格納されてるかの情報は含まれてる。
そうでなければ cout << *p << endl; とかやったときに何が表示されるか未定義になってしまうじゃないか。



134 名前:デフォルトの名無しさん [2008/03/21(金) 12:15:53 ]
>ポインタそのものにそのアドレスに何が格納されてるかの情報は含まれてる。

ありがとうございます。

ポインタは、単に先頭バイトのアドレスを格納する4バイトの記憶
場所をもっているだけでなく、動的データ(または動的配列の要素)
のバイト数とか、データが文字なのか、整数なのか、実数なのか、
といった情報も裏側にもっている。これらの情報はポインタが指す
動的変数や動的配列側にではなく、ポインタ側にある。

という理解でよろしいでしょうか?

135 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 12:21:02 ]
>>134
違う。ポインタの型によって静的に決まる

136 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 12:21:50 ]
静的に型付けされてるからそんなものは要らない。

137 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 12:23:04 ]
まさかvoid*をdeleteしてないよな…
あとポインタが4バイトとは限らないぞ。

138 名前:デフォルトの名無しさん [2008/03/21(金) 12:30:09 ]
うーん、わからなくなってきました。

文字型変数、整数型変数、実数型変数がコンパイル時に静的に
型付けされているのと同じというのは概念的にわかります。

しかし、自分が質問しているのは、その静的な型付けをどのよう
なしくみで実装しているのか?ということだろうと思います。

この段階にくると、コンパイラやアセンブラが理解できないと
無理なんでしょうけど。

139 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 12:50:07 ]
実行時に要素のバイト数は、どこにも格納されてない。
と、考えて良い。

コンパイルする時点では、当然型が分かるので、それを使う。
この段階というか、かなり基礎。

※RTTIは上記が理解出来た上で。

140 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 12:59:28 ]
>>138
いっぺん、自作クラスにoperator newとoperator deleteを実装してみればいいんじゃないかな。

乱暴な説明だけど、C++には「確保/削除するバイト数を受け取る、new/delete一族の大ボス的存在」である
::operator new(size_t)と::operator delete(void*, size_t)があって(他にも多重定義があるけど、とりあえず今はこの2例)、
たとえば int* p = new int; なんてのは、int* p = ::operator new(sizeof(int)); みたいにコンパイル時に解釈される。
同じく、後にdelete p; が出てきたら、pがint型のポインタなのはコンパイラにはわかるから(てか俺等にだってわかる)、
こっちは ::operator delete(p, sizeof(int)); になる。

141 名前:デフォルトの名無しさん [2008/03/21(金) 13:24:09 ]
>>138

>int* p = new int; なんてのは、int* p = ::operator new(sizeof(int));

int *p= new int [100]; は int *p=::operator new(sizeof(int)*100);
みたいになるんでしょうけど、要素のサイズが2バイトなのか4バイト
なのかの情報をコンパイル時にポインタに付加しておかないと、p[i]の
アクセスがうまくいかないのではないかと思うのですが、どうでしょうか?



142 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 13:25:59 ]
>>141
p[i]のpの型はコンパイル時に分かってるんだから

143 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 13:44:43 ]
まあ、強いて言えば、生成されたコード内に埋め込まれているって感じなのかな。

delete[] p;するときに、各要素のデストラクタを起動しなければならないわけだけど、
要素数は p = new T[count]; のcountで、実行時に変わる可能性のあるものだから、
ポインタの前かなんかに隠しておかなければならないわけ。
ちなみに、メモリブロックを単純に解放するだけなら要素数を隠しておく必要はないよ。
free()にサイズを指定しないでしょ?
メモリマネージャはメモリブロックの総バイト数をどこかに隠しておくかもしれないけど、それは別の話。

あとは、
T *p;
for(size_t i = 0; i < count; i++){
p->destruct();
++p; //←これ
}

これの++pがどうコンパイルされるかという、>>139が言うようにC言語レベルの基本的な話。




144 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 13:56:21 ]
>>141
> p[i]のアクセス
たとえばintが4byteの環境だとすると、p[i] と書かれた箇所はネイティブコードにおいては
「pのアドレス+i*4byteのメモリアドレスへ行ってそこから先4byte分に書き込まれているビット配列を〜」
という風に、既にintが「4byte」というミもフタも無い表現に変わっているから、型情報も何も関係無いよ。

145 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 14:27:51 ]
>>141
p[i]というコードはコンパイルすると、アドレスはp+4*iといった意味の命令が生成される。
4が出てくる理由はpの宣言int* pによるもの(intが4byteの環境の場合)。

146 名前:145 mailto:sage [2008/03/21(金) 14:36:28 ]
すまん、144と同じ事書いてしまった。

147 名前:141 [2008/03/21(金) 17:03:54 ]
返事が遅くなってすみません。みなさん、ありがとうございます。

>>144 さんと >>145 さんの説明で

4byteという要素バイト数の情報をポインタp自体が保持して
いるのではなく、p[i]にアクセスする際にコンパイラがp+4*i
を計算する命令を生成しているだけ、ということがやっと理解
できました。

148 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 18:35:45 ]
配列 new の場合、アップキャストは行わないから
配列のサイズは型から静的に決まる、と。
というか、アップキャストはできない。
そこが鍵だな。

149 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 18:36:13 ]
×配列のサイズ
○要素のサイズ

150 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 18:44:36 ]
C++ 的にはフォーマットの決まった string の中から数字を
読み出したりするにはどうするのがお薦めなのでしょうか?
例えば

string s("# foo 30 bar 0.1 xlajkdfl;ajkds");

から 30, 0.1 を抜く場合。

int n;
double x;
sscanf(s.c_str(),"# foo %d bar %lf",&n,&x);

としたりするのですが、もっと「本来」の方法はあるのでしょうか?
どうも workaround 的な気がするので。



151 名前:デフォルトの名無しさん [2008/03/21(金) 18:48:30 ]
atofで一つずつ進めて数値になる所を取り出す

152 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 18:51:36 ]
それはないな

153 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 19:53:08 ]
自分で字句解析器を書く。



154 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 20:00:28 ]
各種正規表現ライブラリの後方参照を使う

155 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 20:29:16 ]
>>150
そういうのが必要になる状況ってあまり無くない?






[ 続きを読む ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧]( ´∀`)<200KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef