■過去ログ置き場に戻る■ 1- 前250 次250 最新50


[memo] "9999999999_00.html#R20" という感じで、URLの最後に "#RレスNo" を追加すると幸せになれます。

C++相談室 part10
501 名前:質問君 :02/09/03 00:39
いろいろ細かいことに答えてもらい
ありがとうございました。
日々精進します(^^;

502 名前:デフォルトの名無しさん :02/09/03 00:44
>>492
実行したのを終了しなきゃね。

503 名前:デフォルトの名無しさん :02/09/03 09:36
=演算子のconst性は(a=b)=cには関係するが、
a=b=cには無関係。


504 名前:デフォルトの名無しさん :02/09/03 09:39
>ことを保証するため。a=b=c で c と a の値が違ってたら困る。
auto_ptrわ?

505 名前:デフォルトの名無しさん :02/09/03 10:48
>自前でコピーコンストラクタを書いてやれば解決すます

それより
operator =() の戻りが、参照になってないから、一時オブジェクトがつくられちゃうってだけでしょ。

506 名前:デフォルトの名無しさん :02/09/03 14:54
void foo(A &x);
foo(a = b);
という場合、const A &operator=()ならエラーになるけど、
A &operator=()なら通る。あと、intの場合(i = 0) = 1
は正当だから、i = 0は左辺値になる。だから、constは
この場合付けない方がいい。

507 名前:デフォルトの名無しさん :02/09/03 15:04
constは付けない(前スレで既出だった気がする)
理由はEffectiveC++読むこと


508 名前:デフォルトの名無しさん :02/09/03 15:10
>(a=b)=c
>(i = 0) = 1
これは不定じゃないか?

509 名前:デフォルトの名無しさん :02/09/03 16:32
newをmallocみたいなものだとした場合、これに対するreallocみたいなものはないですよね?


510 名前:702 :02/09/03 17:30
>>509
STL使ってれば全然そんなこと考えない。

511 名前:デフォルトの名無しさん :02/09/03 17:50
>>510
702って何だろう?801みたいなもんか?072の間違い???

512 名前:デフォルトの名無しさん :02/09/03 18:18
STLコンテナのresize?

513 名前:デフォルトの名無しさん :02/09/03 18:32
ふつーにvectorでいいんでない?

514 名前:デフォルトの名無しさん :02/09/03 22:14
>>509
ありません

515 名前:デフォルトの名無しさん :02/09/03 22:16
vectorは重いからイヤです

516 名前:デフォルトの名無しさん :02/09/03 22:32
おまえらnewで何の領域を取りたいのか聞けよ

517 名前:デフォルトの名無しさん :02/09/03 22:45
効いてほしけりゃはじめからそう書け

518 名前:デフォルトの名無しさん :02/09/04 09:43
>515
貴様は本当に計ってみたのかと小一時間・・

519 名前:デフォルトの名無しさん :02/09/04 10:23
そりゃ関数の引数や戻り値にそのままvector使ったりしたら重いわな。
そういう用途ならauto_ptrでも使っとけ。
ローカル変数やメンバ変数にするなら、重いはずは無い。
処理系によっては、むしろ型の情報を使った最適化が行われていて、
速くなるかも知れない。
何か理由があって、vectorを使えないなら、生のメモリが欲しいのか、
コンストラクト済のメモリが欲しいのかによってやり方は変わる。
前者なら直接malloc/realloc呼ぶのが正解。後者なら、もう1つ配列を
new[]して地道にコピーするのが正解。
malloc->construct->reallocでも良さそうだけど、reallocは
コピーコンストラクタを呼ばないで、単にメモリコピーをしてしまうから、
正しい挙動にするには、malloc->construct->malloc->construct->free
という手順を踏まなければならない。つまり、reallocみたいにコピーを
省略するのは無理。それならnew[]の方がまし。

520 名前:デフォルトの名無しさん :02/09/04 11:50
あるプログラムのデバッグをしているのですが
必ずある時点でAborted(core dumped)
となって止まってしまいます。
通常のデバグの方法ではなかなか原因が検出できなくいきづまってしまいました

そこでcygnin上で動かしているgccが吐く
***.exe.stackdumpを調べれば原因がわかるかもと思っているのですが、
ちょっと読み方がわかりません。
これの便利な使い方ってどうやるのですか?
ちなみに簡単なアセンブラやレジスタの仕組みなどはわかります。

521 名前:デフォルトの名無しさん :02/09/04 11:56
>>520
どうせスレ違い厨には分からないだろ。

522 名前:デフォルトの名無しさん :02/09/04 18:53
>>520
gdbだ. ヒントだけあげるから自分で調べて.

523 名前:デフォルトの名無しさん :02/09/04 21:02
SDKのファイル・フォルダセキュリティ設定に関して質問があります。
AddAccessAllowedAceEx関数を使用し継承を設定したのですが、設定したフォルダの中に新しいフォルダを作成すると「継承元なし」のフォルダが出来てしまいます。
継承元を親フォルダに設定するにはどうしたらよいでしょうか?
OSはWindowsXPで、VC++のバージョンは6.0です。

524 名前:デフォルトの名無しさん :02/09/04 22:55
>>523
スレ違いだボケ
win32apiスレに行け

525 名前:デフォルトの名無しさん :02/09/04 23:11
class A {
int a;
int b;
void show() { printf("a:%d b:%d", a, b); }
};

上のようなクラスがあり、そのインスタンスを複数作った場合、
show()のためのメモリも複数確保されるのでしょうか?

厨な質問ですみません。

526 名前:デフォルトの名無しさん :02/09/04 23:12
二つの自然数a,bの最大公約数を求めるプログラム

527 名前:デフォルトの名無しさん :02/09/04 23:27
>>525
show()自身により消費されるメモリはそのコード本体のみ。
インスタンスを作ろうが作るまいが関係ない。

528 名前:デフォルトの名無しさん :02/09/05 00:41
>>527
クラス内に関数を定義するとinline宣言だから違うかもよ?
もっともクラス毎ではなくて、呼び出し毎になるが。

529 名前:デフォルトの名無しさん :02/09/05 00:42
>>526
ユークリッドの互除法か?それが何か?

530 名前:デフォルトの名無しさん :02/09/05 01:04
>>528
inlineされたとしても、コード本体のみ
という表現に間違いはないと思いますが...

531 名前:デフォルトの名無しさん :02/09/05 01:19
>>530
んだね。スマソ。

532 名前:デフォルトの名無しさん :02/09/05 01:53
#include <iostream>
class A{
public: A(){m_a=3;}
protected: int m_a;
};
class B{
public:int func(){
  class fl_A: public A{
  public:
    void operator=(const A &in_A){
      A *a_A = this;
      *a_A = in_A;//ダメポ… }
    int Get_m_a(){//B::m_A::aにアクセスしたいけど、friend関数は使いたくない。
      return m_a;
    }
  };
  fl_A a_flA = m_A;
  return a_flA.Get_m_a();
}
private: A m_A;
};
int main(){
  B a_B;
  std::cout<< a_B.func()<<std::endl;;
  return 0;
}
クラスBのメンバのインスタンスAのprotectedなメンバにアクセスしたいのですが、
friend関数を使わずに無理やり実装したのですが、
多分、処理系依存とかだと思うのですが、どういう風にコンパイラは解釈するのでしょうか…
おとなしくfriend使って実装するつもりですが、気になったので教えてください。

533 名前:532 :02/09/05 01:55
間違えました。
fl_A a_flA = m_A;

fl_A a_flA;
aflA = m_A;
初期化と代入を間違えました。

534 名前:デフォルトの名無しさん :02/09/05 02:04
>>532
int func()内の、fl_A a_flA = m_A; だけど、これはコピーコンストラクタがないと
コンパイルできないよ。

fl_A a_flA;
a_flA = m_A;

と二行に分けたら?

535 名前:デフォルトの名無しさん :02/09/05 02:04
あららら

536 名前:デフォルトの名無しさん :02/09/05 02:11
>>532
処理系依存と書きながら処理系を指定しないのはどうして?

537 名前:デフォルトの名無しさん :02/09/05 02:18
>>536
と言うか、文法上?の誤りを指定して欲しかったのかな…

この書き方だとコンパイラーがこういう風に解釈しても構わないから、
こう言う風になってバグが発生するみたいな…

一応コンパイラーはMS Visual C++ Professional 6.0 sp5を使っています。

538 名前:デフォルトの名無しさん :02/09/05 02:26
それだったら、コンパイラはデータメンバのうちpublicとprivateの順序を
自由に変えてよいから、fl_A a_flAとA m_Aの順序が入れ替わるかも
しれない、というのはダメ?

539 名前:デフォルトの名無しさん :02/09/05 02:41
>>538
良いです!
つうかそんな卑怯な仕様があったのですか(笑)
なるほど
それなら確かに駄目ですね。
しかし、c++って深いですね…

540 名前:デフォルトの名無しさん :02/09/05 02:44
>>539
今ソース探してるから、信じるのは後にしてね。

541 名前:デフォルトの名無しさん :02/09/05 02:55
どっかで見たんだよなあ・・・・コンパイラは、private、public、protectedの
各々のデータメンバをまとめることがあるから、データメンバの並び方に
依存したプログラムを書いてはいけない、という文を。

542 名前:デフォルトの名無しさん :02/09/05 03:19
>>541
でも本当っぽいですね…
自分も少し探してみましたが見つかりませんでした。

543 名前:デフォルトの名無しさん :02/09/05 04:27
>>509
placement new?


544 名前:520 :02/09/05 04:44
522
ありがとうございますgdbを使用して
だいたいの原因を切り分けられるようになりました。
しかし今度は実行時にsignal6エラーを吐いて失敗するようになりました。
このエラーはなんなのでしょうか?検索エンジンで調べても不思議なほど
情報が少ないですね。
別に珍しいエラーではないと思っているのですが・・

545 名前:デフォルトの名無しさん :02/09/05 08:19
>>532のソースと>>538のソースの関係が見えません。

> fl_A a_flAとA m_Aの順序が入れ替わる
って、 a_flA はローカル変数で m_A は B のメンバですよね?
ローカル変数に public も private も関係ないし、
入れ替わるってどういうこと?

546 名前:デフォルトの名無しさん :02/09/05 10:17
>>543
http://www.google.com/search?q=signal+6+gdb&ie=euc-jp&hl=ja&lr=lang_ja&btnG=Search
腐る程当たりますが何か?


547 名前:デフォルトの名無しさん :02/09/05 10:35
バイナリレベルでのメンバの配置が public や private の影響を
受けるというのと混同してるのでは。

548 名前:デフォルトの名無しさん :02/09/05 15:24
>>546
指してる先は>>544じゃないのか?

というわけで>>546はポインタのミスに気を付けよう:)

549 名前:デフォルトの名無しさん :02/09/06 11:04
vector vec;
して
myClass *myclass = new myClass("test");
vec.push_back(vec);

したばあい
vec.clear()で廃棄おっけーですか?
それともdelete vec[0]が必要なのでしょうか?
これだと結局vectorの要素一つ一つを回していかないといけませんよね?


550 名前:デフォルトの名無しさん :02/09/06 11:08
deleteが要ります。
いやならスマートポインタ使え。イジョ。

551 名前:デフォルトの名無しさん :02/09/06 12:01
スマートポインタつっても std::auto_ptr はだめだぞ。イジョ。

552 名前:デフォルトの名無しさん :02/09/06 17:49
なんか、ここで答える人達って
「タイシタコトナイヨネ」

553 名前:デフォルトの名無しさん :02/09/06 18:00
どういう答えが聞きたかったのですか。
たいしたことある答えが必要なら、たいしたことある質問してください。

554 名前:デフォルトの名無しさん :02/09/06 18:01
いま552はムキになって長文の質問を(しかもわざと難しく)書いている最中です。

555 名前:デフォルトの名無しさん :02/09/06 18:19
>>549
・・・・・

え?

556 名前:デフォルトの名無しさん :02/09/06 18:36
vector vec;

vec.push_back(vec);



557 名前:デフォルトの名無しさん :02/09/06 18:45
#include <iostream.h>#include <string.h>
struct charactor{
public:
float posX,posY;
};
class CLeft{
public:
charactor *C;
void SetP(charactor *Chara){C=Chara;}
float GetP(){return C->posX;}
};
class CRight{
public:
charactor Own;
CRight(CLeft cl,float px){Own.posX=px;cl.SetP(&Own);}
};
int main(){
CLeft cl;
CRight cr(cl,1.0f);
cout << cl.GetP() ;
return 0;
}
コンパイルは通るのですが、これを実行すると、エラーが出てしまいます。
構造体のポインタを宣言したところがまずいようなのですが、何が悪いのか
自分ではわかりません。アドバイスお願いします。

558 名前:デフォルトの名無しさん :02/09/06 19:15
値渡しになってるよ。

CRight(CLeft& cl,float px){Own.posX=px;cl.SetP(&Own);}
        ~~

559 名前:デフォルトの名無しさん :02/09/06 19:26
無事解決しました。ありがとうございます。
しかし、なぜこの状況でアドレスで引数を宣言しないといけない理由が
わかりません。もっと精進して参ります。

560 名前:デフォルトの名無しさん :02/09/06 19:47
>>557
プリプロセッサ命令は一行に複数書くなよ。変だよ。すごく変だよ。

561 名前:デフォルトの名無しさん :02/09/06 20:12
>>557
値渡しだとCRightのコンストラクタを呼び出す際に、CLeft型の一時変数が
作られ、それが渡される。

そしてSetPはこの一時変数のアドレスをcharacter *Cに代入するため、コン
ストラクタの実行が終わった時点で一時変数は消去され、*Cはダングリング
ポインタとなる。

このポインタに対しGetP()を起動すれば何が起きてもおかしくない。

562 名前:デフォルトの名無しさん :02/09/06 20:15
>>561
と思ったが、微妙に違ってた。

cl本体の*Cには何も代入されてない状態でGetPを呼び出しているのでした。
だから何が起きてもおかしくない、と言い換えます。

563 名前:デフォルトの名無しさん :02/09/06 22:20
>>557
関係ないですが、#include <iostream>は使えないのですか?

564 名前:デフォルトの名無しさん :02/09/06 22:53
>>557はJavaをやってたんじゃないかと推測。

565 名前:デフォルトの名無しさん :02/09/06 23:33
質問です。Visual C++6.0にて

void main()
{
ifstream ud;

ud.open("test.dat");
if(ud.bad()){
cerr<<"can't open file\n";
}
ud.close();
}

を作成・実行すると、"test.dat"なるファイルが存在しないにもかかわらず、なぜかサイズ0の
ファイル"test.dat"を勝手に作成して、 if(ud.bad()){} を素通りしてしまいます。
どうすればファイルを勝手に作らないように出来るでしょうか?

566 名前:デフォルトの名無しさん :02/09/06 23:39
ios::nocreate

567 名前:デフォルトの名無しさん :02/09/06 23:49
>566様〜、解決しました。多謝。

ud.open("test.dat",ios::nocreate);
if(ud.fail()){…}





568 名前:デフォルトの名無しさん :02/09/06 23:54
ライブラリ等を作りたいときに、
Cでいろいろ関数を書いて、DLLにしておけば
VBなどで呼べますよね

なら、C++でクラスを用いてライブラリを書いたとき
COMを使わずにVBから呼べるDLLって作れるんですか?

569 名前:デフォルトの名無しさん :02/09/06 23:55
■10.000円の高額収入
1件につき最大10.000円の高額収入。月収100万円以上も可能。
■画期的なビジネス!
インターネットを利用したこれまでにない斬新で画期的なビジネスです。
■誰でも出来ます!
インターネットができる環境の方なら誰でも参加可能です。
インターネットを利用したビジネスですので、自宅や会社で好きなときにで
きるビジネスです。
■専門的な知識は一切不要!
ビジネスに必要なツールは全て当社で用意いたします。
また、サポートも万全です。
■詳細は今すぐこちらから
http://www.bea.hi-ho.ne.jp/paisen/

570 名前:デフォルトの名無しさん :02/09/06 23:57
>>565
void main() 気持ち悪い

571 名前:デフォルトの名無しさん :02/09/07 01:48
っていうか、誰がvoid main()なんて広めたんだよ…。
int main(int argc, char **argv)だろうがと小一時間(略
// int main(int argc, char **argv, char **env) ってのもあるね。

572 名前:デフォルトの名無しさん :02/09/07 02:43
VC++的には合法だからだろ<void main()


573 名前:デフォルトの名無しさん :02/09/07 02:56
>>572 プ

574 名前:デフォルトの名無しさん :02/09/07 02:56
悪い習慣が何でもVCのせいだとは恐れ入った。

575 名前:デフォルトの名無しさん :02/09/07 03:15
>main 関数および wmain 関数が void 型 (戻り値なし) を返すように宣言することもできます。
VC++6.0のヘルプから抜粋。



576 名前:デフォルトの名無しさん :02/09/07 03:18
574 じゃないが、
>>575
それが本当に void main() と書くヤツがいる「原因」なのか?

577 名前:デフォルトの名無しさん :02/09/07 04:09
class AA : public A;
A *a;
があって
((AA)(a[i])).foo (); はダメで
((AA*)(a))[i].foo (); はOKなのは何故でしょうか?

578 名前:デフォルトの名無しさん :02/09/07 04:34
>((AA)(a[i])).foo ();
AからAAへの変換コンストラクタが必要

>((AA*)(a))[i].foo ();
A*からAA*にstatic_castされる。
コンパイルできるからといってOKとは限らない

579 名前:デフォルトの名無しさん :02/09/07 09:24
>571
だって、小規模なテストするには楽なんだもん…

580 名前:デフォルトの名無しさん :02/09/07 09:30
void main(void)で教わりました。
多分ああいう教師のせいだと思います。
もちろん私はdouble main()にしていますが。

581 名前:デフォルトの名無しさん :02/09/07 09:31
>>579
void main()よりもint main()の方が短くていいじゃん。
mainのreturnは省略してもいいんだし。

582 名前:デフォルトの名無しさん :02/09/07 09:57
void main() で書いてある本があるからだろ。
void main() でもエラーでないんだし

583 名前:デフォルトの名無しさん :02/09/07 10:09
double main()でもFILE *main()でもエラーは出ない。
VC6なら警告も出ないね(/W4)

584 名前:デフォルトの名無しさん :02/09/07 11:14
ここはまた main() を議論するスレになったんですか?

585 名前:デフォルトの名無しさん :02/09/07 11:17
int main()
int main(int, char **)
int main(int, char **, char **)

これら以外は main() と認められず。

586 名前:デフォルトの名無しさん :02/09/07 11:29
グローバルなクラスのインスタンスは
いつコンストラクタが呼ばれるか不定という話がありましたが

グローバルなクラスのポインタ(Class* ctest;)を用意して
mainでインスタンス生成(Class c;)→ポインタコピー(ctest = &c;)
extern Class* ctest;で別モジュールから弄ったりしたら
怒りますか?

587 名前:デフォルトの名無しさん :02/09/07 11:30
>>585
C++ではint main(int, char **, char **);も認められたのか?

588 名前:デフォルトの名無しさん :02/09/07 11:47
>>586
「main に入った時後、最初に使う瞬間」にならどのグローバルインスタンスも
初期化されていることは保証されてように読めるので、それは
あまり意味がないのではなかろうか。

> [3.6.2]
> It is implementation-defined whether the dynamic initialization
> ...(略)... is done before the first statement of main or deferred to
> any point in time after the first statement of main but before the
> first use of a function or object defined in the same translation unit.

589 名前:デフォルトの名無しさん :02/09/07 11:51
>>586
main以前にctestを使わなければ問題ないのでは?
でも、もしそうなら別に実体でも構わないと思うけど・・・

590 名前:デフォルトの名無しさん :02/09/07 12:21
>>585
Embedded C++/C99ではvoidも認められてはずですが何か?

591 名前:デフォルトの名無しさん :02/09/07 12:23
>>586
Cやその他のライブラリ関数を使わないなら問題ない

592 名前:586 :02/09/07 12:35
>591
実は、初期化とか面倒なウィンドウの生成と
DirectDrawをひとまとめにしちゃって
他のモジュールからはDirectDrawオブジェクトのインスタンスしか
見えないようにしたいナァという話なのです

593 名前:デフォルトの名無しさん :02/09/07 14:01
>>590
freestanding まで視野に入れて議論するのは無意味だろ。そもそも組み込み系
だと「終了してはいけない = main から return した瞬間にハングアップ」とか「エン
トリポイントが main じゃない」とかもアリアリだから。

hosted environment では C99 でも main は int のみ。以下、規格書から抜粋。

> 5.1.2.2.1 Program startup
> 1 The function called at program startup is named main. The implementation declares no
> prototype for this function. It shall be defined with a return type of int and with no
> parameters:
>
>  int main(void) { /* ... */ }
>
> or with two parameters (referred to here as argc and argv, though any names may be
> used, as they are local to the function in which they are declared):
>
>  int main(int argc, char *argv[]) { /* ... */ }
>
> or equivalent; or in some other implementation-defined manner.

594 名前:デフォルトの名無しさん :02/09/07 15:02
>>593
組み込み系まで視野に入れて議論するのは無意味だろ。

595 名前:593 :02/09/07 15:50
>>594
俺に言うなよ。void main() が OK っつーのは freestanding の話で、即ち
組み込みなんかも視野に入れての意見なんだから >>590 に言ってくれ。

596 名前:デフォルトの名無しさん :02/09/07 16:24
っていうか大人しくint main()にしろよ。voidからintに改めるのがそんなに面倒なコトか?
無難な方法を使うってことができないのか?

597 名前:デフォルトの名無しさん :02/09/07 16:48
俺は自分のスタイルを貫き通す。これがポリシー。
自分を捨てたプログラミングなんて、やってらんない。
だから俺はいつでも void main(void)。
没個性プログラマーは、社会の歯車になって埋もれてしまえばいいよ。

598 名前:デフォルトの名無しさん :02/09/07 16:53
なんでも個性と呼ぶのは問題だろ、現実を見ろ…とネタにレス。

599 名前:デフォルトの名無しさん :02/09/07 17:16
>>597
創造性がない奴に限って、どうでも良いところで差別化を図りたがる(w

600 名前:デフォルトの名無しさん :02/09/07 17:24
なるほど。だから>>597には仕事が来ないのですね。

601 名前:デフォルトの名無しさん :02/09/07 17:30
>>597
単なる独りよがり。別名ワガママ。

602 名前:デフォルトの名無しさん :02/09/07 17:31
来月のUNIX Magazineの特集は「個性派プログラミングで差をつけよう!」
らしいよ。注目だね。

603 名前:デフォルトの名無しさん :02/09/07 18:11
>>597
そろそろ「釣れた」と書いて逃げる頃合でしょうか?(^^)

604 名前:デフォルトの名無しさん :02/09/07 19:02
すみません。
マイクロソフトのC++でアプリの作製方法等を詳しく解説した
HPありませんか?
なかなか見つからないので、お願いいたします。

605 名前:デフォルトの名無しさん :02/09/07 19:13
猫でもわかる

606 名前:577 :02/09/07 19:42
>>578
勉強して出なおしてきますありがとう

607 名前:597 :02/09/07 21:30
釣れすぎワラワラ

608 名前:デフォルトの名無しさん :02/09/07 22:10
http://pc3.2ch.net/test/read.cgi/tech/1030606700/594
仕方なしにマルチしますすいません。
あっちでは間違っているといわれたけど、どのあたりがおかしいんでしょうか?

609 名前:デフォルトの名無しさん :02/09/07 22:20
間違っているとは思えないんだが、
オブジェクトの作成ではなくオブジェクト用のメモリ確保と初期化って事か?

610 名前:608 :02/09/07 22:30
ありがとうあなたは良い人です。(@@)うるうる(感動している)

611 名前:デフォルトの名無しさん :02/09/07 22:31
>>608
あってるから安心しろ。強いて言えば>>609だが。

612 名前:608 :02/09/07 22:33
安心しますた。

613 名前:デフォルトの名無しさん :02/09/07 22:33
new演算子を使うとメモリ領域確保と同時にコンストラクタ呼び出せる
から便利だね。mallocだと明示的にコンストラクタ呼び出さないといけ
ない。

614 名前:デフォルトの名無しさん :02/09/07 23:13
delete NULL;を必ず1ソースに1つは含める。
これが俺のPolicy!

615 名前:614 :02/09/07 23:15
(-_-)

616 名前:デフォルトの名無しさん :02/09/07 23:20
>>614
なんか意味あんの?

617 名前:デフォルトの名無しさん :02/09/07 23:31
delete ptr; としたあと ptr = 0; とするのなら二重deleteを防ぐ意味の上で
有効なテクだろうが、delete NULL; の必要性がわからない。

618 名前:デフォルトの名無しさん :02/09/07 23:43
>>614
::Sleep(0)(あるいは1)なら分かるけど


619 名前:デフォルトの名無しさん :02/09/07 23:58
delete NULL
は型がわからないからコンパイル通らないと思った

620 名前:デフォルトの名無しさん :02/09/08 00:04
昨日,すれ立てるまでもない…に投稿したけど,レスがつかなかった
のでこちらに投稿させていただきます.

C++で数値計算のプログラムを書いてます.ある変数(double型)を
volatileをつけて宣言した場合と,そうしなかった場合で,計算結
果が異なってしまいました.コンパイラによる最適化が問題かと思
い,最適化しないようにオプション(-O0)をつけてコンパイルしたの
ですが,結果は変わりません.これはコンパイラのバグでしょうか?
あるいは,C++の仕様の範囲内でしょうか?コンパイラはg++を使用し
ております.


621 名前:デフォルトの名無しさん :02/09/08 00:11
それ以前の問題でNULLは整数リテラルの0だからdeleteできないのが普通だろ。

622 名前:デフォルトの名無しさん :02/09/08 00:12
>>620
なぜvolatileをつける必要がある?

623 名前:デフォルトの名無しさん :02/09/08 00:16
>>620
volatile をつけた時と、つけない時でどっちの結果が正しいの ?
また、マルチスレッドは使ってるの ?

624 名前:デフォルトの名無しさん :02/09/08 00:17
NULLマクロを使うには cstddef をインクルードする必要がある。

>>620
volatileは本来の変数の値には影響しない。g++のバージョンとCPUの組
み合わせによるバグかもしれない。

625 名前:620 :02/09/08 00:26
お返事ありがとうございます.

>>622

元々,同じ計算を実行する(と私が思っている)ソースが2つあるのですが
2つの計算結果が違ってしまったんですよ.いろいろ検証してみた結果,
問題の変数が,一方ではグローバル変数,もう一方ではメンバ変数になっ
ているのが原因らしいということがわかりました.で,メンバ変数の方を
volatileつけて宣言するか,定数に置きかえれば,2つの計算結果が完全
に一致したわけです.私としては,最適化の副作用かなと思って,-O0と
してみたわけですが,これは効果なしでした.

>>623

どちらが,正しい結果かはわかりません.また,マルチスレッドでは
ありません.コンパイルして,ターミナル上から 普通に(?)実行して
います.解いているのは微分方程式です.非線形項が入っているとは
いえ,同じ計算機で,みため同じソースなので,同じ計算結果が出ない
とおかしいと思うのですが.レジスタに割り当てられる際に値が変更
されることも考えにくいし,丸め方か何かが影響しているのでしょうか.

626 名前:620 :02/09/08 00:32
>>624

gccの2.96とPentium3で主に実行していました.CPUのバグも
疑って,Pentium2,Pentium4で実行してみましたが,改善され
ませんでした.gccをバージョンアップした方が良いのでしょうか.

627 名前:デフォルトの名無しさん :02/09/08 00:35
風俗サイト広告逝ってよしっ!第3回戦
ただいま戦闘中!!!
嫌いな人はこちらへ漏れなく串つき

http://live.2ch.net/test/read.cgi/festival/1029826982/l30




628 名前:デフォルトの名無しさん :02/09/08 00:41
>>626
2.96でそんなバグは聞いたことがないけどなあ。Pentium3ならなおさら
バグはないでしょう。

3.2が出ているからバージョンアップしてみるのも手です。

629 名前:デフォルトの名無しさん :02/09/08 00:43
>>625
その違いって、誤差レベルなの ? だったら、計算順序による丸め誤差の
影響はありえる。(丸め誤差については、C++ の仕様の範囲外。)

630 名前:デフォルトの名無しさん :02/09/08 00:43
テンプレートの一部だけ特殊化って出来ないですか?
template<class A, class B>
class C
{
 ...;
};
template<class T>
class C<int, T>
{
 ...;
};
と言う感じで

631 名前:622 :02/09/08 00:44
>>620
文面から見る限りではvolatileで何かが変わるとは思えないし、コンパイラのバグもそうそうあるものじゃない。
ソースを見ないとなんともいえないけど、ステップ数はどのくらい?
どっかに上げれば暇だからみてもいいよ。

632 名前:デフォルトの名無しさん :02/09/08 00:52
とりあえず前後のポインタ操作にバグがあったりはしないか?

633 名前:デフォルトの名無しさん :02/09/08 00:56
質問です。
VC++6.0にて配列を作るのに、一次元ならば

double *test;
test = new double[2];

delete[] test;
test=NULL;

で実現できるのですが、二次元以上になるとエラーが出てきて実現できません。
一体どのように解決すれば宜しいのでしょうか?よろしくお願いします。

634 名前:デフォルトの名無しさん :02/09/08 00:57
>>617
ちょっと勉強になった.

635 名前:デフォルトの名無しさん :02/09/08 01:00
>>633
二次元以上は自分で確保する


char **pStr = new char[5];
pStr[0] = new char[100];
.
.
.


636 名前:620 :02/09/08 01:01
>>628

ありがとうございます.試してみます.

>>629

差は時刻とともに爆発的に増大します.系の性質から,微小誤差が指数
関数的に拡大することは承知しています.ですが,表面上同じコードが
volatileをつけるかつけないかで,違う結果を出すといったことがある
と,コンパイラのちょっとしたさじ加減で,異なる計算結果が得られて
しまうかも〜と不安になりまして.

計算順序はソースレベルでは同一です.丸め誤差がC++の仕様の範囲外
ということは,丸めに関しては,コンパイラあるいはCPUに依存すると
いうことでしょうか.


637 名前:デフォルトの名無しさん :02/09/08 01:09
俺にはC++という素晴らしい彼女がいるのに・・・
体が満たされないってこういうことを言うのね(涙

638 名前:デフォルトの名無しさん :02/09/08 01:11
>>636
> 計算順序はソースレベルでは同一です.

かなり注意深く書いてないと、ソースレベルで計算順序なんてわからない
ぞ。

> 丸めに関しては,コンパイラあるいはCPUに依存するということでしょ
> うか.

あたり。

とりあえず、gcc なら long double とかが使えるらしいので、試してみ
たら ?

639 名前:デフォルトの名無しさん :02/09/08 01:13
>>635
レス有難う御座います。が、やはりできません。

double **test = new double[i];
はもちろんのこと
double **test = new *double[i];

もエラーで弾かれてしまいます…

640 名前:デフォルトの名無しさん :02/09/08 01:14
double** p = new double*[i];

641 名前:デフォルトの名無しさん :02/09/08 01:15
これだと少なくとも誤差は出ないね。g++2.96 + Pen3

#include <fstream>

int main()
{
double d = 1.000001, dd = d;
volatile double e = 1.000001, ee = e;

std::ofstream of("test.txt");

for (int i = 0; i < 1000000; i++) {
of << d << ' ' << e << ' ' << d - e << std::endl;
d *= dd;
e *= ee;
}
}

642 名前:デフォルトの名無しさん :02/09/08 01:23
>640
おおおぉ〜!いけました。哀れな初心者に親切なご指導を有難う御座いました!

643 名前:620 :02/09/08 01:33
>>622

ありがとうございます.ですが,ソースは,見せると素性がばれ
ますのでお見せできませんm(__)m.ステップ数というのは「ステ
ップ」の意味を存知ませんので,いくつかわかりませんが,ソース
の中では,微分方程式を解く際の刻み幅500個分の計算を行っています.
250個めまでは,ほぼ一致しますが,以後は全く解の軌跡が異なります.

お返事頂いた皆様に感謝します(わざわざプログラムまで書いて頂きまして).

皆様のお返事を見ていると,問題は,丸め誤差であって,volatileをつ
けて計算結果が一致したのは,副次的な作用に過ぎないようですね.
そもそも,このような計算が,私の目的に沿って必要なことかどうかと
いうこと自体を,改めて考えなおす必要もありそうです.

というわけで,今日は(勝手ながら)ここらで収束させて頂きます.
また,何かありましたら,お願いいたします.


644 名前:デフォルトの名無しさん :02/09/08 01:38
>>643
ステップ数はおおざっぱに言えば、ソースプログラムの行数のこと

645 名前:デフォルトの名無しさん :02/09/08 01:41
微分方程式を解くというと、パッと思いつくのはオイラー法かルンゲ・クッタ法
だなあ。特に難しい事はしてなかったように思うんだけど。

646 名前:デフォルトの名無しさん :02/09/08 01:46
>>636
俺ならアセンブラコードを出力させて、差を追ってみるけどな。

647 名前:デフォルトの名無しさん :02/09/08 02:01
-Sオプションを付けてコンパイルしみたけど、何やら面妖なソースを
吐き出しました。

movl%ebx, -320(%ebp)
movl%esi, -316(%ebp)
fldl-320(%ebp)
movl-300(%ebp), %eax
addl$16, %esp
fmullLC0
incl%eax
movl%eax, -300(%ebp)
fstpl-320(%ebp)
fldl-32(%ebp)
fldl-40(%ebp)
movl-320(%ebp), %ebx
movl-316(%ebp), %esi
fmulp%st, %st(1)
fstpl-32(%ebp)
jmpL42

648 名前:デフォルトの名無しさん :02/09/08 02:06
>>613
C++には、デストラクタの呼び出し方法は存在するけど、コンストラクタのそれは存在しないだろ

649 名前:デフォルトの名無しさん :02/09/08 02:15
これがnon-volatileの計算部分

movl%ebx, -304(%ebp)
movl%esi, -300(%ebp)
fldl-304(%ebp)
movl-284(%ebp), %eax
addl$16, %esp
fmullLC0
incl%eax
movl%eax, -284(%ebp)
fstpl-304(%ebp)
movl-304(%ebp), %ebx
movl-300(%ebp), %esi

そしてこちらがvolatileの計算部分です

fldl-32(%ebp)
fldl-40(%ebp)
addl$16, %esp
incl%ebx
fmulp%st, %st(1)
fstpl-32(%ebp)
jmpL42

volatileと指定すると一度FPUにデータを読みとった後mulを実行している
ように見えます。

650 名前:デフォルトの名無しさん :02/09/08 02:18
ちなみにLC0というのは定数データとしてコンパイルされています。

LC0:
.long208632331
.long1072693249

volatileではこのような不変の値をも変数として扱うようにするようです。

651 名前:デフォルトの名無しさん :02/09/08 02:49
>>648
確かにそうですね。やるとすればコンストラクタと同じ中身を持つ関数を
定義しておいて、それを後から呼び出すしかないですね。

652 名前:デフォルトの名無しさん :02/09/08 02:52
mallocのポインタnewにわたせば?

653 名前:デフォルトの名無しさん :02/09/08 02:55
>>648
new( p ) T( ... );

654 名前:デフォルトの名無しさん :02/09/08 03:34
placepent newを使うのか・・・・トリッキーだ・・・

655 名前:デフォルトの名無しさん :02/09/08 04:23
>618
naru

656 名前:デフォルトの名無しさん :02/09/08 05:36
>>648 コンストラクタの明示的な呼び出し方はあるだろ。
A* a;
a->A::A();


657 名前:デフォルトの名無しさん :02/09/08 06:20
>>630
C++標準ならできるが、Visual C++ならできない。
この場合はインナークラスで代用することはできる。はず(笑)
template<class A, class B>
class C
{
 template <typename T> class sub {
 public:
  B func(T a) { ... }
  ...;
 };
 template<> class sub<int> {
 public:
  B func(int a) { ... }
  ...;
 };
 sub<A> impl;
public:
 B func(A a) { return impl.func(a); }
};


658 名前:630 :02/09/08 10:04
>>657
そうですか…
無名の共用体とか引数の違うコンストラクタがあるんで
インナークラスでは回避できなさそうです。
どうもありがとうございました。

659 名前:630 :02/09/08 10:41
すいません。その方法で回避できそうです。
感謝感激です。

660 名前:デフォルトの名無しさん :02/09/08 11:02
>656
何これ。

661 名前:デフォルトの名無しさん :02/09/08 11:42
動かんぞ。

#include <iostream>
#include <cstdlib>
#include <cstring>

class A {
char* ptr;
public:
explicit A(char* str) { ptr = static_cast<char *>(std::malloc(strlen(str) + 1)); }
operator char*() const { return ptr; }
~A() { std::free(ptr); }
};

int main()
{
A* ap = static_cast<A*>(std::malloc(sizeof(A)));
ap->A("string");
std::cout << *ap << std::endl;
ap->~A();
free(ap);
}

662 名前:デフォルトの名無しさん :02/09/08 11:51
ap->A("string")って何?
new(ap)("string")だろ。

663 名前:デフォルトの名無しさん :02/09/08 11:51
VC6で動いたよ
#include <iostream>
#include <cstdlib>
#include <cstring>

class A {
char* ptr;
public:
explicit A(char* str)
{
ptr = static_cast<char *>(malloc(strlen(str) + 1));
strcpy( ptr, str );
}
const char* c_str() const { return ptr; }
~A() { free(ptr); }
};

int main()
{
A* ap = static_cast<A*>(malloc(sizeof(A)));
ap->A::A("string");
std::cout << ap->c_str() << std::endl;
ap->A::~A();
free(ap);

return 0;
}

つーか、素直にoperator new オーバーロードしようぜ

664 名前:デフォルトの名無しさん :02/09/08 11:52
おっと、new(ap)A("string")ね。

665 名前:デフォルトの名無しさん :02/09/08 14:22
>>649-650

コンパイラが volatile を正しく処理しているようにしか見えないが

666 名前:デフォルトの名無しさん :02/09/08 14:28
>>636
殆どの CPU では、処理のわずかな違いで計算結果が変わってしまう。
なお、大抵のコンパイラでは、計算精度を一定に保つオプションがある。

667 名前:デフォルトの名無しさん :02/09/08 15:43
内部表現のbit数とメモリにストアしたときのbit数の違いかもしれないと
疑ったけど、-O0すると必ずメモリにストアするから違うねえ・・・

668 名前:デフォルトの名無しさん :02/09/08 16:52
>>667
x87 って、確か浮動小数点レジスタの精度は 80bit (double の 64bit より長い)
あったよね。

64bit の即値とかけ算する fmull と、80bit レジスタ動詞でかけざんする fmulp
で精度に狂いが出てるんじゃないの?

669 名前:デフォルトの名無しさん :02/09/08 17:58
ロードするときは64bitだからそれはないと思う
それから-O0やvolatileだったら、計算するたびにメモリにストアするから
その都度64bitになってる筈

670 名前:デフォルトの名無しさん :02/09/08 18:32
>>656
ダウト

ANSI C++ の規格書から抜粋。
> 12.1 Constructors
> 1 Constructors do not have names. ...
> 2 ... Because constructors do not have names, they are never found during name lookup; ...

クラス A のコンストラクタは A() という名前では呼べません。

671 名前:デフォルトの名無しさん :02/09/08 19:51
素直にnewインクルードしてplacement new使えよ…

嫌ならこういう関数でも書くか?
template< typenameT >
inline T* CallConstructor(T& instance)
{ return new( &instance ) T; }

672 名前:デフォルトの名無しさん :02/09/08 20:29
>>671
Factory だな、そりゃ。

673 名前:デフォルトの名無しさん :02/09/08 21:58
>>671
instance を最初期化であぼーんだな、そりゃ。

674 名前:デフォルトの名無しさん :02/09/08 22:35
テンプレートの引数に型ではなく値を指定する事ってできないのでしょうか?
下記のような事がしたいです。(擬似コード)

template<class T, const_value V>
class hoge
{
public:
static T s = V;
static T getClassValue()
{
return s;
}
};

よろしくお願いします。

675 名前:デフォルトの名無しさん :02/09/08 22:40
>>674
テンプレにしなくても、コンストラクタにでも渡すようにしたら?

676 名前:デフォルトの名無しさん :02/09/08 22:43
>>674
intなら渡せるはず。


677 名前:デフォルトの名無しさん :02/09/08 22:46
>>674
template<class T, T V> でどう?
T にclass型は渡せないけど。
渡せるのは、組み込み型ならいけるんだったかのぅ。
ポインタ型のときはその値は外部リンケージが要る。

678 名前:デフォルトの名無しさん :02/09/08 22:55
あるクラス A について、

A a = 初期値;



A a(初期値);

って同じ物だと思っていましたが、もしかして動作がちがうのですか?

679 名前:674 :02/09/08 23:09
>>675-677
みなさんレスありがとうございます。
実は渡したいのは関数ポインタ、それもメンバ関数ポインタなのです。
「プロパティ」みたいなテンプレートクラスを作りたいのですが…。

680 名前:デフォルトの名無しさん :02/09/08 23:20
>>678
explicitを付けてコンストラクタを定義すると、前者の形は使えなくなる。

681 名前:674 :02/09/08 23:21
さらに追加で質問です。
現在は >>675 さんの案のようにコンストラクタで渡す方式(動的バインド)で
試しているのですがこれも現状うまくいっていません。

クラスの宣言の中では、そのクラス名ってテンプレート引数に渡せないのでしょうか?
VC6 だと
  error C2027: 認識できない型 'ClassName' が使われています。
のようなエラーが出てしまいます。
下記は試している途中のコードです。
template <class Subject, class MemberFunc> class MemberFuncCaller
{
private: Subject& subject_;
private: MemberFunc operation_;

public: MemberFuncCaller(Subject& subject, MemberFunc operation)
: subject_(subject), operation_(operation){}

public: void Do(){ (subject_.*operation_)(); }
};

class User
{
typedef void (User:: *UserFunc)();

public: inline void MemFunc(){ printf("Do it, ok!\n"); }
// ここでコンパイルエラー
MemberFuncCaller<User, User::UserFunc> DoObject(user, &User::MemFunc);
};
解決策をご存知の方よろしくおねがいします。

682 名前:678 :02/09/08 23:23
>>680
なるほど。ということは、前者は

A a(なにか);
a = 初期値;

と同じになるわけですか?

683 名前:デフォルトの名無しさん :02/09/08 23:25
>>679
こんな感じか?bcc5なら通った。
あと、VC6でtemplateを使いまくるのはかなりキッツイので覚悟した方がいいぞ。

template
<
  typename Value,
  typename Class,
  Value (Class::*Getter)(),
  void (Class::*Setter)(Value)
>
class property { ... };

//property<std::string, SomeClass, &getName, &setName> name;

684 名前:デフォルトの名無しさん :02/09/08 23:26
>>682
その通り。

>A a = 初期値;
コピーコンストタクタが呼ばれる

>A a(初期値);
直接初期化 A::A(初期値)が呼ばれる

ただし、RVOによりコピーコンストラクタは省略されることもある。
explicitは初期値がA型なら問題ない筈

685 名前:デフォルトの名無しさん :02/09/08 23:30
こういうことかな。

#include <iostream>

class A {
int x;
public:
explicit A(int i) { x = i; }
void print() const { std::cout << x << std::endl; }
};

int main()
{
A a(1);
//A b = 2; //エラー
A b = A(2);

a.print();
b.print();
}

686 名前:678 :02/09/08 23:31
>>684
なるほど。ありがとうございます。
要するに、両者は違うものだが、最適化で同じになりうる、という認識で。

>>674
なんか割り込んでたみたいですみませんでした


687 名前:デフォルトの名無しさん :02/09/08 23:32
>>679,>>683
プロパティということは、メンバ関数をオーバーロード
している?
たしか、多重定義されているメンバ関数のポインタは、
テンプレートの引数として使えないはず。

688 名前:674 :02/09/08 23:57
>>683
VC6 だと property のインスタンスの宣言時に「特殊化」のエラーが出ます。
メンバ関数へのポインタから通常の関数へのポインタへの変換ができない
という内容みたいです。
特殊化も、メンバ関数ポインタから通常の関数ポインタへの変換もしてないのですが…。

>>687
いえ、メンバ関数は一個です。


現状の悩みは >>681 でも書きましたが、
このクラスを利用したいはずの、利用側クラスの内部に宣言が書けない事です。
相変わらず 認識できない型 'ClassName' が使われています が出てしまいます。

689 名前:674 :02/09/09 00:06
ひとつ勘違いしてました。
メンバ関数ポインタから関数ポインタへの変換ができないというエラーは出ません。
でるのは
error C2973: 'property' : テンプレートの仮引数 'Getter' が無効です。
でした。

さっきのエラーは Value (Class::*Getter)() を書き間違えて
Value (*Getter)()
とした為にでていました。


690 名前:bloom :02/09/09 00:14

http://www.leverage.jp/bloom/start/

691 名前:デフォルトの名無しさん :02/09/09 00:20
>>681
> // ここでコンパイルエラー
> MemberFuncCaller<User, User::UserFunc> DoObject(user, &User::MemFunc);
これって typo?
MemberFuncCaller<User, User::UserFunc> DoObject(User, User::UserFunc);
ではなくて?

692 名前:683 :02/09/09 00:26
>>681
ちゅーかよく見たらあーた、クラス定義の中で
コンストラクタは呼び出せないよ、そりゃ。

× MemberFuncCaller<User, User::UserFunc> DoObject(user, &User::MemFunc);

○ MemberFuncCaller<User, UserFunc> DoObject;
○ User() : DoObject(*this, &User::MemFunc) {}

693 名前:620 :02/09/09 00:40
昨夜はどうもありがとうございました.解決策が2つみつかりました.

>>668 などで指摘されている通り,double型(64ビット)の変数がレジスタ
(80ビット)に割り当てられた際に,余分な桁がまぎれこみ,計算結果に
違いが出たようです.

私が思いついたのは次の2つで,結局,2を選択しました.

1. g++のコンパイルの際に-ffloat-storeオプションをつける.
これにより,double型(64ビット)変数のレジスタ(80ビット)への割り
当てを抑制できました.

2. double型の変数をlong double型で宣言しなおす.
もともとlong double型は80ビットですので,レジスタに割り当てても
  不要な桁が入りこまないようになります.

ちなみに,計算速度は,1,2で,大きな差はありませんでした.

694 名前:674 :02/09/09 00:45
>>691
???? テンプレートじゃない普通の引数に型名ですか?よくわかりません。
>>692
しまった。この間仕事で Java とか使ってたので宣言時に初期化できるような気になってました。
これを適切に直しても VC6 だと利用側のクラス名を判別できないエラーが出ます。

bcc ならできるとの事なので、いまインストールしてみたのですが、たしかにコンパイルできますね。

ところで、この場合、Getter と Setter はどうやって使えばいいのでしょうか?
template <typename Type, class ClassName, Type (ClassName::*Getter)(), Type (ClassName::*Setter)(Type)>
class property
{
private: Type m_Value;
public: ClassName x;
public: Type& operator= (const Type& rhs){ return (x.*Setter)(rhs); }
public: operator Type() { return (x.*Getter)(); }
};
class User
{
private: int v_;
public: int Get(){ return v_; }
public: int Set(int v){ v_ = v; }
property<int, User, &User::Get, &User::Set> ValueProperty;
public: User() : ValueProperty(){}

};
としてmainとかで
User user;
user.ValueProperty = 50;
printf("%d", user.ValueProperty);
こうすると、未定義の構造体 'User' というエラーが出てしまいます。
なぜでしょうか?

695 名前:デフォルトの名無しさん :02/09/09 00:49
>>693
うーん、そうだとしても、-O0で、volatileとそうでないものに違いがでる
というのは納得行かんなあ・・・

まあ解決して何よりなんだけど・・・

696 名前:デフォルトの名無しさん :02/09/09 01:05
>>692,>>694
DoObject(…) ってのはメンバ変数定義(のつもり)かよ…。関数宣言かと思った。

697 名前:674 :02/09/09 01:09
>>696
よく Java や C# とごっちゃになるんです。
まんま Java/C# 式のまちがいをした時は
「へんてこな純粋仮想関数の宣言です!」とか怒られるんですよ。

今日はもう寝ます。みなさんありがとうございました。
質問者が寝てしまっても、次にきた時の参考になるように
アドバイスを残してくださる優しい方がいた時のためにあらかじめ
書いておきます。

ありがとうございます!

698 名前:デフォルトの名無しさん :02/09/09 01:24
どうでもよさげな話で恐縮だが、クラスの中身ってpublicから書く?
それともprivateから書く?

699 名前:デフォルトの名無しさん :02/09/09 01:25
どうでもよすぎ。
見た目効率〜とかいうスレがあったと思うからそっち逝け。

700 名前:デフォルトの名無しさん :02/09/09 01:25
>>698
public -> protected -> private

全部pからはじまるのがむかつく。・・・・なんとなく。

701 名前:デフォルトの名無しさん :02/09/09 01:28
>>698
public フィールド
protected フィールド
private フィールド
public メソッド
protected メソッド
private メソッド


702 名前:デフォルトの名無しさん :02/09/09 01:37
>>699
すまぬ。

>>700
今、僕もそうしています

>>701
フィールドとメソッドで分けるの?


結構、private (先頭無指定)から 書いてあるソースを見かけることが多いので、
ほかの人はどうしているのかと思い、質問してしまいました。おじゃましました。


703 名前:620 :02/09/09 03:05
>>695

確かに,-O0で最適化を抑制しているのにvolatileの有無で結果が違
うのは,変数がレジスタに割りつけられている可能性が出てきておか
しいと思います.もう少し検証して何か出たら,また報告します.


704 名前:デフォルトの名無しさん :02/09/09 04:10
>702
そりゃスコープ省略すると勝手にprivateになるからだろw

705 名前:701 ◆k/Ubp.Kg :02/09/09 06:27
>>702
分ける。理由は特にない(藁。つか、フィールドとメソッドが一緒だと読みにくいのよね、俺的に。
まぁ趣味だから、どう書くかよりも統一されてるコトの方が重要だと思ってる。

>>704
そうだね。俺、あれが好きじゃないからpublicを頭に回してprivateを明示的に書くようにしてまふ。
これもやっぱし趣味だな。

706 名前:704 :02/09/09 06:31
ちなみに漏れはオブジェクト指向(データ指向)マンセーなので
利用者がスグに知りたいパブリックメンバを前に、
プライベートなメンバは後ろ〜の方に書いてます

そもそも外から見られたく(いじられたく)なくてプライベートにしてるのに
真っ先に書いてあるのは不自然じゃないか、と

707 名前:683 :02/09/09 08:14
>>694
> public: ClassName x;
これだとUserの中にproperty<..User..>の中にUserの中にproperty<..User..の中に…
の無限入れ子になってしまう。C++はJavaじゃないので参照なりポインタなりは
そのむねちゃんと書かんといかんよ。

template <typename Type, class ClassName, Type (ClassName::*Getter)(), void (ClassName::*Setter)(Type)>
class property
{
private: Type m_Value;
public: ClassName& x;
public: property& operator= (Type rhs){ (x.*Setter)(rhs); return *this; }
public: operator Type() { return (x.*Getter)(); }
public: property(ClassName& owner) :x(owner){}
};

class User
{
private: int v_;
public: int Get(){ return v_; }
public: void Set(int v){ v_ = v; }
property<int, User, &User::Get, &User::Set> ValueProperty;
public: User() : ValueProperty(*this){}
};

708 名前:683 :02/09/09 08:16
> private: Type m_Value;
あとこれは要らんな。

709 名前:デフォルトの名無しさん :02/09/09 18:15
個人的に値とpropertyを分けるのは好きじゃないな

property < int, ...> Value;

Constructor() : Value(this, 初期値) {}

Get(int& value);
Set(int& value, int& new_value);

710 名前:デフォルトの名無しさん :02/09/09 21:45
ファイルを操作するクラス CFileがあります。
ファイルのパスを格納しているクラス CFilePathがあります。
パスにならってファイルを開く関数 CFilepath::open() を定義して、
CFileをなんらかの形で返したいのですが、どのように返したらいいのでしょうか?

最近CからC++に移ってきたんですが、Cみたいにポインタで返さなくても
メモリの大量コピーとかはおこらないんでしょうか?

711 名前:デフォルトの名無しさん :02/09/09 22:07
CFilePathって一般的にはやや無理筋そうなクラスに見えるけど、
なんのためにあるの?
むしろ、CFile に getpath() みたいなメンバの方が自然な気が。

712 名前:デフォルトの名無しさん :02/09/09 22:12
あと、

>最近CからC++に移ってきたんですが、Cみたいにポインタで返さなくても
>メモリの大量コピーとかはおこらないんでしょうか?

戻り値の話なら、値で戻せばコピーが起きるのは CもC++も同じ。

てーか、そもそも、Cで何らかのオーバヘッドが発生する局面で、
C++だとそれが起きないなんて状況は、まずないね、逆はよくあるけど。

713 名前:710 :02/09/09 22:45
どうも書き方が悪かったようです。ここのパスってのは検索パスです。
CFilePathのコンストラクタで
{"/usr/share/hoge","/usr/local/share/hoge"}みたいなのが読み込まれて、
CFilePath.open("fuga.dat")
で/usr/share/hoge/fuga.dat,/usr/local/share/hoge/fuga.datの順に存在した物を開くと
いうものを作成したいのです。

714 名前:デフォルトの名無しさん :02/09/09 23:04
>>713
CFile を継承して、コンストラクタと open() を定義すれば良いと思うが...。

715 名前:710 :02/09/09 23:23
>>714
そうすると、ファイルを開くたびに検索パスを読み込む方法しか思い浮かばないのです。
C++まだよくわかってないんですが、、

716 名前:デフォルトの名無しさん :02/09/10 00:03
>>715
毎回読む、グローバルに保存しておく、staticメンバに保存しておく、お好きなように。

717 名前:710 :02/09/10 00:52
毎回読む、グローバルに保存は避けたいですね。
staticメンバってのはわからないので、調べてみます。

あと、一応、クラスを返すときはどういうように返すのが一般的かを
教えてください。

718 名前:674 :02/09/10 01:23
やっぱり先にお礼を書いておいて良かった!

>>707
そういえばそうでした、ありがとうございます。
ところで、このプロパティの中身をオブジェクトにして

int val = someObject.Property.memberVariable;

のように書いたときに、 someObject が int に変換できないという趣旨の
エラーが起こるのですが、この時は何が起こっているのでしょうか?
冷静に考えると、プロパティの実体のメンバにアクセスするための
ドット演算子が未定義である為に起こる症状な気がするのですが、
operator. ってオーバーロード出来ないんでしたでしょうか?

こういう場合に自然な振る舞い(C#などのプロパティのような振る舞い)に
する方法は何かありますか?
どなたかよろしくお願いします。

>>709
分けないと、アクセス制限の線引きが曖昧になりませんか?
インスタンスのプロパティなのに、そのインスタンスが受けるアクセス制限が
外と同じというのはちょっと…と思うのですが。


719 名前:デフォルトの名無しさん :02/09/10 01:33
>>718
. :: .* ?はオーバーロードできん。

720 名前:デフォルトの名無しさん :02/09/10 02:51
>>717
CFileに参照回数計測を実装すれば、ポインタ1つのコピー+αくらいで逝けるヨン。
他の場面で多少のオーバーヘッドは出るけど、
CFileみたいなクラスはそんなに速度は要求されないだろうしネ。

721 名前:720 :02/09/10 02:54
って、よくみたら、staticメンバわからんとか逝ってるし。
staticメンバわからんやつに参照回数計測はまだ無理かな。

722 名前:デフォルトの名無しさん :02/09/10 03:13
>>711
もしくは CFile::open(const CFilePath&) を作るか。

723 名前:デフォルトの名無しさん :02/09/10 03:21
>>721

staticメンバだと、pathリストパターンjが複数存在する場合に困るような...
今回の場合、複数ないかも知れんけどね。

724 名前:683 :02/09/10 07:57
プロパティって、対応する実体が無くてもあたかも存在するかのように見せられる
property<int, OwnerClass, &OwnerClass::GetLength, _> length;
int OwnerClass::GetLength() const {
 return strlen( m_string_data );
}
のが便利なとこだと思ってるので、常にメンバ変数とペアになってる
ことを仮定したpropertyテンプレートって好かんのだが…。

>>718
class property [with T=SomeValue&] {
 T operator()() const { return (x.*Get)(); }
};
と謎の()を定義して、その時だけプロパティらしからぬ
int val = someObject.Property().memberVariable;
で使うか、operator. の代わりに operator-> のオーバーロードで
我慢するしかないような気がする。

725 名前:デフォルトの名無しさん :02/09/10 09:23
オペレーターを定義するときには、
メンバー関数にするのとフレンド関数にするのとどちらが良いのでしょうか?

それぞれのメリット・デメリットにはどんなことがあるのでしょうか?

いろんな立場からのご意見をお聞かせ下さい。

726 名前:デフォルトの名無しさん :02/09/10 10:06
スレ違いかもしれませんが、統一スレのようなので、質問させてください。

みなさんはC++を使う場合のGUIまわりはどうしてます?
Winだと、BCBかMFCというところでしょうか?
.NETの方がきれいなGUIになっていったらどうします?

727 名前:デフォルトの名無しさん :02/09/10 10:56
凄い初歩的な質問で申し訳ないんですが、よろしくお願いします。

Win32コンソール用アプリケーションで、ユーザに1ラインに複数の言葉を入れてもらい、
それを個々のstringとして認識するにはどうしたらいいのでしょうか?
例としては、ユーザがcinに
"apple banana orange grape"
と入力した場合に、スペースを認識して"apple"というstring、"banana"というstring、
という具合に個別のstringに分けたいのです。

cin >> a >> b >> c; という様な手を使おうと思ったのですが、ユーザが入力する言葉の数は一定してないので、
言葉が3つ以下の時にキチンと作動しません。

お願いします。

728 名前:727 :02/09/10 10:57
すみません、上げてしまいました。;

729 名前:デフォルトの名無しさん :02/09/10 11:07
一度に1lineまるまる拾ってきた後、それを解析
strtok()などのループ

730 名前:デフォルトの名無しさん :02/09/10 11:10
>>727
配列も使えよ。

731 名前:727 :02/09/10 11:19
googleでstrtok検索したらなんとなくわかりました。
ありがとうございます。m(_ _)m

732 名前:デフォルトの名無しさん :02/09/10 11:26
ただし、strtok は少し癖があるから、気をつけて。
場合によっては、strtok_r を使うこと。

733 名前:デフォルトの名無しさん :02/09/10 11:49
>>725
それは、すでに語られ尽くしてる気がするな…。

734 名前:734 :02/09/10 12:40
STLの初心者ですが、教えていただきたいのですが、
過去ログの
(http://pc.2ch.net/tech/kako/1009/10090/1009071535.html)
265番目あたりの対処方法は、皆さんなら、どのように
しますか?
VC++,BulderC++で作成したsetをGNU g++でも動作させようと
しているのですが、iteratorがconstなので、エラーになります。
やはり、erase,insertをするしかないのでしょうか?


735 名前: ◆k/Ubp.Kg :02/09/10 12:47
>>734
gcc-3.2を使わない。2.95.x使うの止めた方がイイよ。

736 名前:デフォルトの名無しさん :02/09/10 12:57
>>725
立場がどうの、っつーほどのもんではない。
2項オペレータの左項に当該クラス以外のオブジェクトが来る場合を
許容しようとしたら、必然的に非メンバ関数として定義してやる
しかない、というだけの話。

737 名前:デフォルトの名無しさん :02/09/10 13:29
>>727
せっかく std::string をつかってるなら、文字列を char配列にコピー
してからでないと使えない strtok よりも、string のメソッドになってる
find、find_first_not_of、substr あたりを組み合わせて使ったほうが
よいんでは。

738 名前: ◆k/Ubp.Kg :02/09/10 13:32
boost::tokenizerは?

739 名前:デフォルトの名無しさん :02/09/10 16:18
VC++6っす。
プログラムに埋め込んで使えるようなデータベースライブラリーって
ないですか?Oracleとかだと、別途インストールしたりサーバの設定とか
面倒なので。

今まではSTLのmapとvector使ってやってたんだけど、そろそろ面倒で限界。鬱になる。



740 名前:デフォルトの名無しさん :02/09/10 16:21
>>739
探す暇があったら自分でつくれよ低能。

741 名前:デフォルトの名無しさん :02/09/10 16:37
>>740
煽る暇があったら働けよ低能。

742 名前:デフォルトの名無しさん :02/09/10 16:43
>>739=>>741

743 名前:デフォルトの名無しさん :02/09/10 16:45
そして
>>740=>>742という罠

744 名前:デフォルトの名無しさん :02/09/10 16:46
しかも
>>741=>>743という罠

745 名前:デフォルトの名無しさん :02/09/10 16:47
>>739
VC++スレできけばぁ?

746 名前: ◆JAPH9PWA :02/09/10 16:48
>>739
SQLiteはどうよ
Perlからしか使ったこと無いけど
http://www.hwaci.com/sw/sqlite/

747 名前:デフォルトの名無しさん :02/09/10 17:01
>>739
ちょいと弄れば使えると思う(BCC5.5用だが)
http://www.fuel.co.jp/~bull/odbc/



748 名前:デフォルトの名無しさん :02/09/10 17:02
>>745
べつにいんじゃない?

749 名前:デフォルトの名無しさん :02/09/10 17:03
>>739
DAOとかのMFCにあるやつ

750 名前:電子メール アドレス : :02/09/10 17:09
電子メール アドレス :
miyazakisyuji@docomo.ne.jp
ジャンジャンメールクレーーーーなんでもOK!!






■過去ログ置き場に戻る■ 1- 前250 次250 最新50
DAT2HTML 0.33f Converted.