トップページ⇒tech
1001コメント278KB

C++相談室 part82

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん2010/06/02(水) 20:20:13
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレに
お願いします。

前スレ
C++相談室 part81
http://pc12.2ch.net/test/read.cgi/tech/1273407971/
0175デフォルトの名無しさん2010/06/12(土) 23:30:53
だから、「他のAにアクセスする」というのは角カッコ演算子の役割ではない、と言ってるの。
普通 b[2]って言ったら2に対応付けられた値だけ返ってくることを期待するでしょうが。
0176デフォルトの名無しさん2010/06/13(日) 06:27:24
B::operator[](int)とC::fullpath()の機能をまとめて、
string B::path(int n)みたいな関数にしたほうがいいと思う。
0177デフォルトの名無しさん2010/06/13(日) 11:39:03
そうすることにする
[]が先の方が良かったけど複雑だしな
0178デフォルトの名無しさん2010/06/13(日) 11:46:31
operator[]ってプログラマの自己満程度の意味しかないよね
こんなもの全くいらないし
fortran的に考えて
0179デフォルトの名無しさん2010/06/13(日) 12:19:12
>>174
その役目はイテレータだけどな。
0180デフォルトの名無しさん2010/06/13(日) 12:19:56
>>178
オペレーターオーバーロードは、それで記述が簡潔になる場合にしか使わないし。
0181デフォルトの名無しさん2010/06/13(日) 12:22:35
多次元[]実装するために必死になってtemplateいじってるやつ見ると笑いがこみ上げてくるoperator()とat()でいいのにね
0182デフォルトの名無しさん2010/06/13(日) 12:26:48
>>181
一次元のコンテナがあれば[]で何次元でも作れるのに?
0183デフォルトの名無しさん2010/06/13(日) 12:28:20
>>182
それじゃあ生成・破棄の効率がクソ悪いだろ
01841292010/06/14(月) 16:23:42
>>135 遅くなったけどありがとう。

いまいち伝わってないというか、上手く説明ができてなかったようなので言い方変えると、

class Test {
int value;
public:
void Set(int v) {
this->value = v;
}
};

void func(Test* t) {
t->Set(1); //これでfunc()の呼び出し元のtest.valueを変更したいけど、
//*t = Test(); //これができると呼び出し元のtest自体が書き変わってしまうので禁止できないか?
}

void main() {
Test test;
func(&test);
}

イベントでいうと以下のようなことをやりたいのですが、Senderの実体を書き換えられるのは困りますよね。
ttp://www.ne.jp/asahi/nagoya/ahomaro/builder/cpb-018.html
イベントなのでどんなクラスにも対応しなければならず、ラップして代入禁止というのは無理です。
ポインタで渡して実体を書き換えないように気を付けるのが普通なんでしょうか。
0185デフォルトの名無しさん2010/06/14(月) 16:45:05
Setでも書き変わってるようにしか見えんが・・・
01861292010/06/14(月) 17:01:59
>>185
Setでは書き換わってもいいんだけど、*t = Test()で全く別のオブジェクトにはなって欲しくないってことです。
0187デフォルトの名無しさん2010/06/14(月) 17:19:51
代入しただけでは全く別のオブジェクトにはなりません
01881292010/06/14(月) 18:11:57
ああ、全く別じゃなくてメンバ全部コピーしてるだけですね。
そう考えると、やらないように気を付けるでいいのかな。
言い間違いのつもりだったけど、いまいち理解できてなかったのかも。
ありがとうございました。
0189デフォルトの名無しさん2010/06/15(火) 01:18:55
だから>>135はコピーだけ禁止する方法を示してくれてるんだぜ
0190デフォルトの名無しさん2010/06/15(火) 09:50:05
高級言語から覚える弊害がこれだよ
0191デフォルトの名無しさん2010/06/15(火) 10:27:04
「const参照渡し」で終わりなんじゃないのか……?
0192デフォルトの名無しさん2010/06/15(火) 10:32:41
あー、setはしたいのか。
じゃあ代入禁止でおk。boost::noncopyableでもおk

しかし>>190が意味不明だ
0193デフォルトの名無しさん2010/06/15(火) 10:37:44
>>184
void __fastcall TForm::ButtonClick(TObject * const Sender)
01941902010/06/15(火) 12:08:46
流れから想像するに代入で参照が切り替わると勘違いしてんじゃねーかなって思ったわけです
ちょっときびしいか?
0195デフォルトの名無しさん2010/06/15(火) 13:07:28
>>190はキチガイだと思う
0196デフォルトの名無しさん2010/06/15(火) 13:10:09
アセンブラ、C or Lisp、C++ とかがよいと思うな。

x86アセンブラのほうが覚えること少なくてらくでしょ。
基本はmovとcmpとjmpだけでよいし。
0197デフォルトの名無しさん2010/06/15(火) 13:37:45
どこの誤爆?
0198デフォルトの名無しさん2010/06/15(火) 17:24:46
マって人生誤爆してるよね
0199デフォルトの名無しさん2010/06/15(火) 17:38:27
最近再びwindowsプログラムやりはじめたんだけどMFCってクソですね
0200デフォルトの名無しさん2010/06/15(火) 17:57:39
スレチとか脳障害なの?
0201デフォルトの名無しさん2010/06/15(火) 18:04:52
いやC++にちょっと慣れてきたら改めて思ったっていう独り言です。スレチですねごめんね。。。
0202デフォルトの名無しさん2010/06/15(火) 18:37:00
逆に何がお気に入りなんだろ。
0203デフォルトの名無しさん2010/06/16(水) 00:02:08
mfcは設計自体は糞だけど、C++で高速なWindowsプログラムを作成する場合
もっとも、いい選択肢だよ
0204デフォルトの名無しさん2010/06/16(水) 00:15:53
MFCと速度は関係なくない?
0205デフォルトの名無しさん2010/06/16(水) 00:25:28
そんなことはない、BCBやQtなんて使ってみなよ
吐き気がする位遅い
0206デフォルトの名無しさん2010/06/16(水) 00:35:24
MFCでウィンドウズプログラム恐怖症になったがC#で救われた
0207デフォルトの名無しさん2010/06/16(水) 00:47:38
Qtが遅いのはXwindowだっけ?あれが遅いんじゃないの?
0208デフォルトの名無しさん2010/06/16(水) 01:36:11
MFCがここ10年くらいの後発の言語や
フレームワークより使いにくいのは仕方ないだろ
それ以前の負の遺産を引きずってるんだから
0209デフォルトの名無しさん2010/06/16(水) 11:33:01
>>206その気持ちよくわかる。
0210デフォルトの名無しさん2010/06/16(水) 12:21:55
質問しようとして検証コード書いたり状況説明を考えてる内に下らないチョンボに気が付いたw
元質問は自己解決したんですが、良く分からなかった事があるので教えてください。

多重継承しているクラスがあります。
class Derive : public Base, public Listener{

で、他の関数にthisポインタを渡そうとしてます。
Derive::func(void){
  thread->SendRequest(this, data);
}

SendRequestはこんな感じです。
void SendRequest(Listener *listener, int data);

SendRequestを呼び出す前のthisのアドレスが、
呼ばれたSendRequest内の引数listenerでは+4されていたのは何故でしょうか。
VC++2008です。

すみませんがよろしくお願いいたします。
0211デフォルトの名無しさん2010/06/16(水) 12:30:33
>>210 多重継承とはそういうもの。
Derive の中には Base部分と Listener部分が含まれている。
おそらく、先頭4バイトがBase部分で、その後にListener部分が続いていたんだろう。
0212デフォルトの名無しさん2010/06/16(水) 12:37:32
なるほど、ありがとうございます。
確かに
class Derive : public Listener, public Base

としたら+4されなくなりました。
0213デフォルトの名無しさん2010/06/16(水) 16:24:54
static_castさんは親切だからね
0214デフォルトの名無しさん2010/06/16(水) 19:24:22
だが皆から蔑まれてる c style cast さんも親切なのです
0215デフォルトの名無しさんNGNG?2BP(0)
ありがた迷惑
0216デフォルトの名無しさんNGNG?2BP(0)
struct A { };
void foo(const A* const a) { }
void bar() { foo(&A()); }

これはまずい?
const参照使えば大丈夫なのは知ってるんだが
ポインタだとダメ?
0217デフォルトの名無しさん2010/06/16(水) 21:10:09
何を以てまずいとか大丈夫とかダメとか言っているのかわかりません。
0218デフォルトの名無しさん2010/06/16(水) 21:19:22
>>216
こんぱいるできたか?
0219デフォルトの名無しさん2010/06/16(水) 22:23:40
まずい以前にテンポラリオブジェクトのアドレスなど取れないわ
02202102010/06/16(水) 23:48:01
ついでなので>216もコンパイルしてみました。
一応コンパイルは通るし、fooの引数aもスタック上のオブジェクトを指してるっぽい。

…でも出来る出来ない以前にちとダサいと思うw
0221デフォルトの名無しさん2010/06/16(水) 23:51:10
VCは独自拡張でアドレスとれた気がする
02222102010/06/16(水) 23:52:29
あ、VC++だったからですか…。
0223デフォルトの名無しさん2010/06/17(木) 07:39:57
最近、C++の存在意義に悩んでいます・・・。
PC性能が上がってきて、速度とかあんまり気にする必要がなくなってきてる気がして・・・。

あ、趣味グラマです。
0224デフォルトの名無しさん2010/06/17(木) 07:51:35
ま、趣味ですからね
0225デフォルトの名無しさん2010/06/17(木) 17:30:41
んなこたーない。速度超重要。
0226デフォルトの名無しさん2010/06/17(木) 17:49:34
低レベルの方が自分がなにやってるのかしっかり分かって安心できるしバグも見つけやすいと思う
0227デフォルトの名無しさん2010/06/17(木) 17:58:14
MFCが大きくて遅くて不安定だったのはWin16,Win32s,Win32初期あたりの話だな
当時より大きく遅くなっているが今のハードだと問題にならない
0228デフォルトの名無しさん2010/06/17(木) 22:58:50
最初に指定要素分配列を確保したら以降は削除するまで要素数が変化しない配列を動的配列といいますか?
0229デフォルトの名無しさん2010/06/17(木) 23:00:03
秘密です
0230デフォルトの名無しさん2010/06/17(木) 23:02:53
>>228
いいえペンです
0231デフォルトの名無しさん2010/06/17(木) 23:06:04
>>228
reallocしないならば静的確保だというのですか?
0232デフォルトの名無しさん2010/06/17(木) 23:06:22
ケフィアです。
0233デフォルトの名無しさん2010/06/18(金) 11:07:40
>>228
             /)
           ///)
          /,.=゙ ''"/   
   /     i f ,.r='"-‐' つ____   こまけぇこたぁいいんだよ!!
  /      /   _,.-‐'~/⌒  ⌒\
    /   ,i   ,二ニ⊃( ●). (●)\
   /    ノ    il゙フ::::::⌒(__人__)⌒::::: \
      ,イ「ト、  ,!,!|     |r┬-|     |
     / iトヾヽ_/ィ"\      `ー'´     /
0234デフォルトの名無しさん2010/06/18(金) 16:50:25
行列の固有値を計算するプログラムをVC++2005とgcc4.4.1でコンパイル実行
すると、全く同じプログラムなのに結果が違う。ちなみにMATLABの結果は
VC++の結果と一致している。

2日ほど悩んでいたが...

原因は、何と自作のライブラリファイルで使っていたabs関数に「std::」をつけて
いないことだったorz。

xをdouble型の変数としてabs(x)を呼べば関数のオーバーロードによって
double abs(double x) が呼び出されると思っていたのにgccではint abs(int i)
が呼び出されていて結果が違っていた。xがdoubleであってもintに型キャスト
されるため整数部(の絶対値)のみが返ってきていた。

これはC++の数学関数が標準名前空間std内にあることによるのだろうが
(ちなみに #include <cmath>としている)、VC++では「std::」をつけなく
ても問題なく、double abs(double x) が呼ばれている。

C++の仕様としては、gccとVC++どちらが正しいでしょうか?

「std::」をつけなくてもコンパイルエラーや警告がでず、意図しない
別のabsが呼ばれるgccの方が怖いですけど。
0235デフォルトの名無しさん2010/06/18(金) 17:05:49
template<uint8_t N> class Hoge : public BasicHoge;

BasicHoge * CreateHoge(uint8_t n)
{
    switch(n)
    {
    case 0: return new Hoge<0>;
    case 1: return new Hoge<1>;
    ・・・
    }
}

int main() { BasicHoge *p = CreateHoge(Rand8()); ・・・; }

上のようなことをしたいんだけど
1〜uint8_tの最大まで書くのがめんどいんだけど
うまいこと実行時の整数をコンパイル時の整数にマッピングする方法ってない?
0236デフォルトの名無しさんNGNG?2BP(0)
Boost.Preprocessor
02372352010/06/18(金) 17:37:20
すいません自己解決しました

>>236
マクロ無しでも余裕でした
0238デフォルトの名無しさん2010/06/18(金) 19:51:40
>>234
gcc 4.3以降なら-Wconversionで警告出せるよ。
警告出ないと確かに怖いね。
0239デフォルトの名無しさん2010/06/19(土) 01:43:51
Windows上のアプリケーションから、直接システムコールを呼び出して、ヘッダーファイルを
インクルードせずにプログラムを作るには、一体どうしたらいいんでしょう?

色々と調べ回ったのですが、大体がLinuxでのことしか書いてないし、Windowsでのもの
も、実際にコードにしたら、Windowsから不正だのなんだのと言われて、プログラムが止まってしま
うんですが…

例えば、int 21hとか
0240デフォルトの名無しさん2010/06/19(土) 01:45:35
マシンコードとかアセンブラだろ
常識
0241デフォルトの名無しさん2010/06/19(土) 03:28:08
>>239
ヘッダーインクルードを忌避する理由は何?

Windows API (Linux のシステムコールに相当) を呼び出すには call 命令を使うが、その
飛び先 (API を提供している DLL のエントリポイント) をリンクするのはアセンブラでは
煩雑と言うか面倒と言うか忘れたと言うか、使用するアセンブラによる。
API を呼び出すのにかかるコストは、C/C++ の関数形式でもアセンブラの call 命令でも
全く変わらない。
せっかく C++ なのだから、素直に windows.h をインクルードするのが吉。

int 21h で有名なのは MS-DOS ファンクションコールだが、Windows アプリでは (デバイス
ドライバを書いて特権を取得しない限り) そもそも int 命令が禁止されていて、MS-DOS
ファンクションコールは一切使えない (プログラムが不正終了するのはおそらくそのせい)。
MS-DOS アプリが動作するのは、MS-DOS ファンクションコールがエミュレートされている
から (64bit OS では 16bit アプリをサポートしないため MS-DOS アプリは動作しない)。
0242デフォルトの名無しさん2010/06/19(土) 04:55:33
windowsAPIも最終的にはCPUやGPU命令呼び出すから
それを直にやりたいんだろ。
アセンブラ。
0243デフォルトの名無しさん2010/06/19(土) 05:41:16
APIでできる事を自分でやるって、車輪の再開発をしたいって事?
0244デフォルトの名無しさん2010/06/19(土) 07:05:44
>>242
その方法を自分で調べられん奴が一体何をするつもりなんだろうね
0245デフォルトの名無しさん2010/06/19(土) 08:44:24
ヘッダをインクルードしたくないだけなら、必要な宣言をコピーすればいいじゃない
0246デフォルトの名無しさん2010/06/19(土) 08:50:18
疑問に思ったんですが、関数オブジェクトってどういう使いどころがあるんでしょうか。
STL以外での使い道に心当たりがある方お願いします。
0247デフォルトの名無しさん2010/06/19(土) 08:55:18
DOS時代なら特権レベルとかなかったから好き放題だったんだけどねえ
今はintとかin/outとかhaltとか好きに呼べない
ま、安全のためだから仕方がないが
0248デフォルトの名無しさん2010/06/19(土) 15:59:10
自作のコンテナのイテレーター作るときに気を付けること(iterator_tagの設定など)をまとめたサイトってありますかね?
0249デフォルトの名無しさん2010/06/19(土) 20:30:21
>>248
STLで足りない理由を明確にすることかな
0250デフォルトの名無しさん2010/06/20(日) 02:09:03
>>248
作り方: http://msdn.microsoft.com/en-us/magazine/cc301955.aspx
規格(の草案): http://www.kuzbass.ru/docs/isocpp/lib-iterators.html#lib.iterator.requirements
0251デフォルトの名無しさん2010/06/20(日) 06:28:27
C++で
#define YAMA 0
#define KAWA 1
#define HAIRETUNOKAZU 20

とかを使いまくってるのですが、これは話にならないくらいの糞コードなんでしょうか?

static const HAIRETUNOKAZU = 20
みたいにするのが業界標準なんでしょうか?
0252デフォルトの名無しさん2010/06/20(日) 06:35:44
他にも関数作成時は
void kansuu(int number);
みたいに書きまくってるけど
void kansuu(const int number);

for文も
for( a=0 ; a<10 ; a++ )
みたいに書きまくってるけど
for( a=0 ; a<10 ; ++a )

if文も
if( n=10 )
と書きまくってるけど
if( 10=n )

と書かないと業界では鼻で笑い飛ばされて帰っていいよと言われる糞コードなんでしょうか?
0253デフォルトの名無しさん2010/06/20(日) 06:38:42
for文に限ってはほんのほんのほんお少しだけ当てはまる
他については決してそんなことはないというか、
void kansuu(const int number) ってのは void kansuu(int number) と同じシグネチャだから
逆に混乱を招きかねないって意見も多くあるし、
if ( 10 == n ) についても同じ
0254デフォルトの名無しさん2010/06/20(日) 06:49:13
なるほど、ありがとうございました。
for文は++aのがデータのメモリ間のコピーだかなんだかの処理がa++より一回少なくて高速だと聞いたのですが、
それほどその程度の速度を意識したことなかったし、大抵の初心者サイトで最初に教えられるのはa++だから惰性で続けてました。

ほかにも構造体を関数へ渡すときは

kansu(KOUZOUTAI)
void kansu(KOUZOUTAI)

kansu(&KOUZOUTAI)
void kansu(*KOUZOUTAI)

kansu(KOUZOUTAI)
void kansu(&KOUZOUTAI)

みたいないろんなやり方があって自分は2番目を常用してますが、これは好みでしょうか?
DirectxのSDKなどでは2番目で使用する前提の関数が多く用意されてるのでこれがプログラマ達の標準だと思ってました。
他の方でも知っておられたら教えてください。
0255デフォルトの名無しさん2010/06/20(日) 07:29:42
++aがいい。組み込み型なら別に気にしなくてもいいけど、用がなければ前置でいい。
10=nというその例のようなミスを防ぐためにはいいのかもしれないけど、それは強制しないし
n=10と書いても警告が出るからn=10を推奨。10=nは逆に禁止したいぐらい。
値を変更するなら3番目、kansu(*KOUZOUTAI)のtypoだよね?
変更しないならconst参照で受けるのがいい。
鼻で笑い飛ばして帰っていいよとは言わないけど、上記のようなことを説明をしつつ伝える。
0256デフォルトの名無しさん2010/06/20(日) 07:38:26
OpenCVのC++インターフェースとかは入力パラメータがconst参照渡し、出力パラメータが非const参照渡し
Googleのコーディング規約では入力パラメータがconst参照渡し、出力パラメータがポインタ渡しになってるな。
どっちにしろ値を渡す目的ではconst参照渡しを使うのがいいと思う。
0257デフォルトの名無しさん2010/06/20(日) 08:00:54
なるほどありがとうございました。
自分で組んでる分にはわざわざconstなんて付けないし、
人との共同でも値変更があるかはプログラム設計書に明記してりゃいいやと思ってたけど、
安全で安心ではありますね。
0258デフォルトの名無しさん2010/06/20(日) 08:05:26
コンパイラが勝手にconstチェックしてくれるなんて使わなきゃ損だね
0259デフォルトの名無しさん2010/06/20(日) 08:26:34
>>255
1番目は値渡し(コピー)。
2番目はポインタ渡し。
3番目は参照渡し。

のつもりじゃないだろうか。
0260デフォルトの名無しさん2010/06/20(日) 08:34:40
ttp://codepad.org/pnRhDYaP

ポインタ派参照派どちらの派閥をとわずご満足いただけます
0261デフォルトの名無しさん2010/06/20(日) 08:36:16
たまに他言語使ってconst参照相当の物が無いと不安になって心が押しつぶされそうになる
0262デフォルトの名無しさん2010/06/20(日) 09:00:11
C#使っていると、constのような最小限のチェック機構が無いのは何でだろうと悩んでしまう。
0263デフォルトの名無しさん2010/06/20(日) 11:58:09
勉強しろw
0264デフォルトの名無しさん2010/06/20(日) 12:15:56
Immutable保証するやつはないだろ
そもそもメソッドのパラメータとして記述できるのはparamsとrefとoutだけじゃね
0265デフォルトの名無しさん2010/06/20(日) 12:25:40
c#の参照渡しで書込み保護できないとか危険卓
0266デフォルトの名無しさん2010/06/20(日) 12:31:13
まぁC#はC++と違って何もつけなくても間接参照できるし
ref使うのは特殊なケースだろう

間接参照でImmutable保証出来ないのはJavaにしろPythonにしろ同じだし
0267デフォルトの名無しさん2010/06/20(日) 13:48:19
ポインタが無効かどうか知るには管理者からboost::weak_ptrを渡してもらえばいいですか?
0268デフォルトの名無しさん2010/06/20(日) 14:33:30
すまん、const参照渡しって概念は何となく分かるんだが、
const参照渡しが推奨される理由が分からないorz

constポインタ(?)とかじゃダメなの?
0269デフォルトの名無しさん2010/06/20(日) 14:38:25
参照ならNULLが無い
const参照ならテンポラリオブジェクトも取れる
そしてクライアントの手間が省ける
0270デフォルトの名無しさん2010/06/20(日) 16:44:04
>>259
あわわ。寝ぼけてたみたいでorz
指摘ありがとうです。

>>257でちゃんと伝わってたようで安心した。
0271デフォルトの名無しさん2010/06/20(日) 18:36:12
リソースが限られてる組み込みとかって、
templateよりdefine関数の方が一般的?
0272デフォルトの名無しさん2010/06/20(日) 18:50:47
と公言していた某プロジェクトが今どうなったか知らぬのか
# defineは関数ではない
0273デフォルトの名無しさん2010/06/20(日) 18:54:58
確かにdefine関数っていうのはおかしいか
マクロ展開
0274デフォルトの名無しさん2010/06/20(日) 19:49:27
>>270
うむ。orz
■ このスレッドは過去ログ倉庫に格納されています