490 :
営利利用に関するLR審議中@詳細は自治スレへ :
2012/04/07(土) 18:29:03.06 簡単な数式を引数でとって結果を返す関数をテンプレートで書こうとしてます。 template<class II, class PD, class CT> int sansuu(II pos, PD n, CT tr) { for (; 0 < n ; --n, ++pos) { ---> ここの書き方 if( tr.eq(*pos, '0') ) { } } return 0; } int main(int argc, char* argv[]) { const char* p = "1+1"; ここの書き方 sansuu(p, strlen(p), char_traits<char>); const wchar* wp = L"1+1"; sansuu(wp, strlen(wp), char_traits<wchar>); インプットイテレータとサイズを引数にして、あとcharとwcharでも 使えるようにしたいんですがどうしたらいいのでしょうか stringを見たらchar_traitsとかあったんですがよくわかりませんでした。 お願いします。
>>490 いいたいことはわかるんだけどまずcharだけでいいから動くもの書ける?
forの中身を全部教えろはうんざりだな
492 :
営利利用に関するLR審議中@詳細は自治スレへ :2012/04/07(土) 19:12:10.50
>>491 中身のアルゴリズムの質問ではないんです。書き方が悪くてすいません。
テンプレートの使い方がよくわからないので、そこのところをお願いします。
>>490 どうでもいいが、IIとかPDとか大文字だけの名前使うと
プリプロセッサと衝突するぞ
じゃあとりあえず非テンプレートでちゃんと動くwchar_t版書いてみるところからはじめようか
>>492 困ってるポイントがわからんから、まずテンプレートを使わず
char固定でコード書いてみてくれないか
496 :
営利利用に関するLR審議中@詳細は自治スレへ :2012/04/07(土) 19:34:06.85
char_traits 使ってるのに strlen というあたり違和感ありあり
>>497 ありがとうございます。
でもこれだと
if(*it=='+')
のところでwchar_tとcharを比較してしまうとおもってどうにかしたほうが
いいと思ったんです。
>>498 char*はascii互換文字コード(ASCII,SJIS(MS932),EUC-JP)で入ってる文字はASCIIコード内だけ
wchar_t*はUTF-16 or UTF-32で入ってる文字はASCIIコード内だけ
という前提なら一応大丈夫・・・のはず
ASCII範囲外の文字も使うならwchar_t*だけで実装して
使う側が文字コード変換する方が良いんじゃね?多分
追記、ascii互換文字コード(〜, UTF-8)
>>501 ありがとうございます。
まだ読みきれてないですが勉強します
503 :
営利利用に関するLR審議中@詳細は自治スレへ :2012/04/07(土) 20:46:08.50
widen
なんで書き込みないんここ
お前が書き込まないからだよ
C++のことが好きになってしまいました
time.h以外に興味ありません
int* p = new(0) int; pが0になる保証ってありますか?
ヌルポに書き込んでる時点で鼻から悪魔 組み込み系とかで0番地にどうしても書き込みたい場合ならpはヌルポになるだろうけど、 普通はその前にアクセス違反で死ぬ
と思ったけど g++ だと死なないな int() じゃないからかと思ったけど、 int() でも死なないし、あまつさえ int(1) でも死なない 一体どう言う事だ
あ・・・ヌルポだからメモリ確保に失敗したと思って初期化しやがらないのか なら、0 になる事は保証されてるっぽいな
>>510 void* をひとつ取る配置用の operator new は引数をそのまま返す。 (18.6.1.3 p2)
そして noexcept で宣言されているので、ヌルを返すことはメモリ確保失敗の意味になる。
その場合、初期化は行われず new 式の結果がヌルになるとされている。 (5.3.4 p13)
というわけで、その p は必ず 0 と等しくなる。
・・・ void* より優先される operator new のオーバーロードが宣言されてなければね。
>>514 うぉぉ、わかりやすい説明だぜぇぇぇぇぇ。
プレースメントnewは殆ど使わないから
すぐ挙動を忘れちゃう(´・ω・`)
ヌルヌルポか
ifstreamとgetlineで外部のファイルを1行ずつ読み込む処理を作りました。 しかしリリースモードで実行すると1行ずつ読み込めません。デバッグモードでは問題なく読み込めました。 原因が分かる人がいたら教えてください。 ちなみにvs2008を使っています。
読み込むテキストファイルは同じやつか?
どうせ未初期化の変数の値を使ってるとかの類
さもなきゃカレントディレクトリのファイルを読もうとしていて、 DebugとReleaseでカレントが違うことを失念しているとか。
523 :
519 :2012/04/13(金) 17:27:10.86
getlineは通常に動いてました。すみません。
>>521 さんの想像通り未初期化の変数が誤動作の原因でした。
>>520-522 アドバイスありがとうございました。
524 :
デフォルトの名無しさん :2012/04/14(土) 01:20:20.19
1 0.1 2 0.2 3 0.3 ... みたいにintとdoubleが交互にならんだ入力を、 istream_iterator<int> a(cin); istream_iterator<double> b(cin); で交互に読み取りたいのだが、(テーブルの列読み込み) while (a!=istream_iterator<int>()) { int x = *a++; double y = *b++; } てやっても評価順が制御できなくて困っています。 どうすればいいんでしょうか?
525 :
524 :2012/04/14(土) 02:00:41.50
なんか、上のサンプルを作ろうとしたけどうまくいってしまう。 問題が別のところにある可能性もあるから、ちょっと待ってくれ。
うまくいってるならそれでいいんじゃねーの?w
527 :
524 :2012/04/14(土) 02:32:52.43
どうもfor_eachとのからみでおかしい。 C++0xがはいっちゃうけど、流れでここに出させてもらいます。 入力は -1 0.3 -1 0.8 ... みたいな、doubleは適当な乱数。 1/1000くらいの割合で評価順が逆になる。 #include <iostream> #include <algorithm> #include <iterator> using namespace std; int main() { auto b = istream_iterator<double>(cin); for_each(istream_iterator<int>(cin),istream_iterator<int>(),[&b](int n){ if (*b++<0) cout << "fail" << endl; }); } }
乱数で0とか浮動少数じゃない数値になってんじゃないの 乱数やめて固定値でやtってみたら
529 :
524 :2012/04/14(土) 03:44:48.16
そうね。ちょっと適当にやりすぎたわ。 istream_iteratorがバッファリングでもしてるのかと思ってしまった。
>>527 それじゃだめだろ。istream_iteratorの実装によってはインスタンス生成時に値を一回読む。
531 :
524 :2012/04/14(土) 10:01:34.51
>>530 まじかw
1/1000って書いたけど1/10000でもあったから、
調べてみたらたしかに1行目でドジってるw
この目的を達成するために仕様に沿った形で書けますか?
ちなみに使うときは527みたく
for_each(istream_iteratorA,...,istream_iteratorBを使った関数)
の格好(入力イテレータで読む)で。
532 :
524 :2012/04/14(土) 10:09:20.74
>>532 つ
a=...
b=...
for_each(...)
別の発想で交互に読み込むことを保証するイテレータの組をつくることはできないか?
>531 読み込みが決まり切ってるなら型を起こせばいいんでは? #include <iostream> #include <algorithm> #include <iterator> using namespace std; struct i_and_d { int i; double d; }; istream& operator>>( istream &is, i_and_d &id ) { return is >> id.i >> id.d; } ostream& operator<<( ostream &os, i_and_d &id ) { return os << id.i << "," << id.d << endl; } void testprint( i_and_d x ) { cout << x; } int main() { for_each( istream_iterator<i_and_d>(cin), istream_iterator<i_and_d>(), testprint ); }
534 :
524 :2012/04/14(土) 10:56:59.48
ありがとう。return os << endl;ってできるの知らんかった。 ですが、API上、iとdは別のイテレータにしておかないといけないんです・・・
535 :
524 :2012/04/14(土) 11:15:24.98
いま自分で実装しようとして引っかかったんだけど、 bool operator==(const istream_iterator&, const istream_iterator&) ってどう定義すればいいんだろ・・・
API上別にしないといけないってどういう事? あるタイミングで i を使って、別のタイミングで d を使うって事? 使ったかどうか覚えておけばいいだけのような
>>534 APIって何?WinAPI? 自作エンジン操作するAPIとか?
とりあえず、実際に使う部分を見せて欲しいな 関数名が秘密ならそのあたりは変えていいから
>>535 イテレータ内部でストリームを basic_istream<charT,traits>* in_stream; で保持しておいて
return lhs.in_stream == rhs.in_stream; するのがstdでのやりかた
541 :
524 :2012/04/14(土) 14:43:12.69
寝てたんで見るのがおそくなった。すまん。
>>540 が綺麗なんで、APIを変えることにしました。
単体の列をストリームで扱えるようにしたかったんだけど、
行ごとに読み込むストリームのほうがたしかに自然だな。
可変テンプレート引数をとるようにして(my_iter<int,double,double>)
tuple<int,double,double>が値になるようにすればテーブル読み込みできるね。
read()を書くのがちと面倒くさそうだが。
542 :
デフォルトの名無しさん :2012/04/14(土) 18:04:19.59
template <typename T, typename U> void f(tuple<T,U>& t) {...} template <typename T, typename U> void f(pair<T,U>& t) { f(tuple<T,U>(t)); } みたいな多重定義を避けられる方法ってないですか? ただし、なんでも受け付けちゃう template <class PairType> void f(PairType& t) {...} ってのは無しで。 (コンパイルでtuple<int,int,int>をつっこんでたらエラーが出るように)
543 :
541 :2012/04/14(土) 18:15:50.84
>>542 template <typename T, typename U, template <typename...> pair_type>
void f(pair_type<T,U>& t) {...}
かなぁ・・・他にいい案があったら教えて下さい。
template<typename T,typename U>struct pair{〜;operator tuple<T,U>&(){return tuple<T,U>(*this);}};
545 :
541 :2012/04/14(土) 18:42:36.84
std::pairの仕様みてもそんなの無いんですが、暗黙の変換をどっかで定義しろってことですか?
>>542 template<class T, class U> class tuple
{
・・省略・・
tuple( const std::pair< T, U > value ){省略}
・・省略・・
};
もしくは、
template<class T, class U> tuple<T, U> to_tuple( const std::pair &value )
{
return tuple< T, U >( value );
}
c++0xにstd::tupleというのがあってだな・・・ スレ違いの話題で混乱させてしまってすみませんでした。
脳内でネームスペースを勝手に補完したらダメだよね。
m(__)m
c++0x ってどんな風に入力したらこうなるんだ?
俺はSTLマスターだが質問あるか?
ないわー
ないない
>>551 std::messagesってどうやってつかうの?
std::set<T>のインスタンス同士の一致比較(つまり、同一の集合であることの確認)ってどうやるの? T型の要素はソートされて格納されるそうだから インスタンスをa, bとして、a.begin()〜a.end()までとb.begin()〜b.end()をそれぞれ比較して 全部一致することと同値なのだろうか それとも、STLの仕様的にはそこまでは保証されておらず、上の方法はたまたまうまくいっているか、処理系依存で、 やはり比較前に自前でaやbに格納されている要素をソート等せねばならないのだろうか
結論だけいうと==でやれ
> インスタンスをa, bとして、a.begin()〜a.end()までとb.begin()〜b.end()をそれぞれ比較して > 全部一致することと同値なのだろうか 同値でしょ。 要素値を比較する前に双方の要素数を比較した方が良さそうな気がする。 // 要素数チェック if(a.size()!=b.size()) return(1);
mismatchでやれ
比較オブジェクトが同一かも検査したほうがいいんじゃないか?
560 :
555 :2012/04/15(日) 15:52:01.26
レスdクス
とりあえず要素となる型に<演算子が定義されていれば
(ていうかstd::set<T>のTの用件なのでそもそも定義されている前提)
少なくともVS2010では>556の方法で逝けるみたいです!
STLのマニュアルとして↓ここ見ながらやってたんですが、
http://www.cplusplus.com/reference/stl/ グローバル関数でset<T>& operator==(set<T>&, set<T>&)が定義されるとか
どこにも書いてなかったから気づかなかったorz
561 :
555 :2012/04/15(日) 15:54:45.55
訂正 誤: set<T>& operator==(set<T>&, set<T>&) 正: bool operator==(const set<T>&, const set<T>&)
std::setは赤黒木。 赤黒木は同一要素からなる集合に対してはbegin() 〜 end()までの順序構造も同じ。 だから単にsizeを見た後iteratorを回してoperator ==での直接比較か operator <(or operator >)x2で同値比較すればよい。
563 :
555 :2012/04/15(日) 16:22:00.26
スマン>560でボケたことを書いたorz 要素型Tのless than演算子(operator<())だけでは 一致比較できるわけないじゃんorz(多分bool operator==(const T& a, const T& b)が必要) set<int> a, b;についてはa==bで一致判定できましたが Tが自作クラスの場合は要検証です検証中なう
大抵赤黒木で実装されるけど 赤黒木でなければならないと規格で決められているわけでもない
>563 !(a<b) && !(b<a) だな。562も書いてるけど。
>>565 a,bの間に全順序の存在しか仮定しないときに、
果たしてそのコードでa==bと同値になるのか
冷静に考え直したほうがいいんジャマイカ、
いやすまん>565でいいのかorz (!(x<y) && !(x>y)) ⇔ (x≧y && x≦y)⇔ (x == y) 結局、Tについてoperator<()が定義されていれば、 set<T> a, b; についてa==bできるっぽい (実際Tを自作クラスとしても、Tのoperator<()を定義したらVS2010で動いた)
>std::setのoperator==ではstd::equalが使われstd::equalでは
>>555 のように比較される
なるほど、、いつどのアルゴリズムを使うのかきちんと決まってるのか
std::equalの定義(というか規格上の等価テンプレート)みたら、
Tについてstd::equalが使われる場合、Tについてoperator==()は必須みたいですね
>567の最後の行は撤回(実はoperator==()が定義されてた)
>>570 ・グローバル変数の使用は避ける。
・calculatorの中で初期化とされてるのは初期化でなく代入。初期化と代入は別物。
・なぜcalcuratorの中でanswerに代入(初期化)?
・// a:Aの値。
ソースを先頭から読んだ場合この時点ではAの値といわれてもなんなのか不明。
・// Yと回答されたらループ、それ以外は終了。
実際の処理との不一致。
このコードに限らずだが広域でのusing namespaceが個人的にヤダな せめて関数の中でusing namespaceするか、using std::cout;の様に 取り込んどいて欲しい。std系統じゃぶつかりづらいがVectorとか Listとかありふれた名前は簡単にぶつかる。
573 :
570 :2012/04/16(月) 16:33:06.78
男ならヘッダファイルでusing namespace std;
>574は漏れもやったが30分で悔い改めた それはそうと、デカいオブジェクトの実体をSTLのコンテナに格納して 複数個所から参照しつつ必要に応じて追加するということをしたいんだけど コンテナにinsert()する前後で参照が有効であり続けるようなうまいやり方ってないですかね… コンテナの要素型を自作クラスでうまく作ればできなくは無いけど標準的なやり方は?
std::listを使う
using namespace std; がヘッダに書いてあるライブラリを使うことを強制されているんだ!
windows.h が自動的にインクルードされていたり、まさに地獄だぜ。
>>577 listを使うか、間接参照するか
マクロ展開出力みたいに ADL展開出力オプション欲しいよな
>>577 なんでもかんでもshared_ptrでくるんじまいなよ! コンテナ用件は自動的に満たされるぜ!
using namespace std; をわざわざincludeするようのヘッダー作ってincludeしまくってるわ とりあえずusing std::stringとかにかえてみた
お前の using namespace std; のせいで ライブラリのヘッダでコンパイルエラーが出たわ
using namespaceはよほどのことがない限り使わないな。 namespace fs = boost::filesystem; とかはよくやるが。
そんなこともできるんだったな すっかり忘れてた
using namespaceを使っといて、完成版では置換すればよい。 手間の問題。
using namespace したものを置換するのは困難だぞ
590 :
デフォルトの名無しさん :2012/04/17(火) 22:09:49.45
テストコードをそのまま本番に持って行ってるわけね
class Sample { const bool aaa(const a, const b) const const int bbb(const c) const const Sample(const d) const } 最近constに触れる機会があったのですが TYPEはintとかfloatとか 【const TYPE】 aaa(const x) const 質問なのですが、【const TYPE】の部分がconstだと 実際にはどういう利点があるのでしょうか 他の部分がconstになっていると 色々とパフォーマンスに影響がありそうだと直感的に理解できるのですが (変数には値とかコピーが入るわけですよね?) 戻り値の型にconstがあったからといって特に意味無いような気がしてしまいまして じゃあ、頭のconstにはどんな意味があるんじゃ!? ということで疑問が湧いてしまったのですが どなたか意味というか意義というか、教えてくださいまし
const TYPE&じゃなくてconst TYPEなの?
>>581 >なんでもかんでもshared_ptrでくるんじまいなよ!
何を言いたいのかわからんが、
確かに「型Tのset」のかわりに「型Tのshared_ptrのset」にでもして
shared_ptr<T>のoperator<()とoperator==()を(適当なスコープで)定義するとしたら逝けそうですな
※ とにかくデカいオブジェクトなので同じものを複数持ちたくない。
当然insert時は重複チェックをやる。これをも極力高速、極力コンテナに任せにしたいからlistというのもちょっと、、、
>577における「コンテナの要素型を自作クラスでうまく作」るのより良さげな回答だけど
しかしshared_ptrはSTL標準ではないのではないか
>>591 const病の伝染をやり過ごせる利点がある
class Sample {
int* p;
// (適当な構築子)
const int* GetPtrA() { return p; }
const int* GetPtrB() const { return p; }
};
であるとして、
const Sample foo(...); // constオブジェクトとして構成
int* p1 = foo.GetPtrA(); // コンパイル時エラー
int* p2 = foo.GetPtrB(); // おk
595 :
594 :2012/04/17(火) 22:41:43.73
ああスマン頭のconstか わからんメリットなど無いのではないか (でもテンプレート絡みでちょっとあるのかも?テンプレートについて人類は何一つ断言できない)
戻り値はconstにする派ってのもいたと思う Effective C++に書いてあるけど、正直やりすぎだと思う
レスありがとう …やっぱり、頭が const TYPE の場合はあまり意味なさそうな感じですか? 恐らくコスト面でも無視できるような違いしかないってことですよね。 実際にもあまり使わないという認識でいいのかな そういえば、 const TYPE&の存在がありましたね…。 const TYPE& はパラメーター(参照)のstd::vectorのアイテム参照とかグローバル変数の配列の参照を返す時とかに有効な気がしますが intとかfloatみたいな値を返す時とかに積極的に使う理由ってありますか?
戻り値 const Effective C++ でググれ >・ 戻り値にconstを使うと、問題のある関数の安全性や効率を改善できる > >例2) >const Rational operator* (const Ratioanl& lhs, const Rationa& rhs); > >(a * b) = c のようなコードは不正だが、const 指定すればコンパイル時エラーとなる。 >(a * b) = c; これを展開すると、const Rational (a * b) = Rational c となりエラー。 正直こんなのどうでもいいと思うが
戻り値const派は右辺値参照の登場で窮地に立たされたな
右辺値参照で何か不都合とかあったっけ?
右辺値参照とconst絡みで問題なんてないと思うが 教義を貫けない的な話?
折角右辺値参照を使ってるのに 無駄に複製が発生するようになるからじゃない
603 :
デフォルトの名無しさん :2012/04/18(水) 00:40:30.17
禿の自刃に殉じた使徒の数知れず (;ω;)
>>598 >・ 戻り値にconstを使うと、問題のある関数の安全性や効率を改善できる
>・ 戻り値にconstを使うと、問題のある関数
>問題のある関数
メイヤーズ氏もついに演算子の多重定義をdisる境地に達したのか
「定数式が必要です」と言われてしまいました……教えてください。 「sound_effect.h」に次のように書きました。簡略化しています。 #ifndef SOUND_EFFECT_H #define SOUND_EFFECT_H extern const int SOUND_EFFECT_MAX; class CSoundEffect{ public: CSoundEffect(); ~CSoundEffect(); void RaiseFlag(int Num); void LoadSet(int SoundSet_Num); void Play(); private: int File[SOUND_EFFECT_MAX]; int Flag[SOUND_EFFECT_MAX]; }; そして、「sound_effect.cpp」には次のように書きました。各関数の定義ははぶきます。 #include "sound_effect.h" const int SOUND_EFFECT_MAX = 45; CSoundEffect SE_Object; すると、SOUND_EFFECT_MAXが代入済みの整数定数とみなされていないのか、 「構造体または共用体中にサイズが 0 の配列があります」ということになってしまいます。 なお、extern const intではなく#defineを用いるようにすれば、エラーは出なくなります。 ですが、整数定数の定義には#defineではなくconstを使うようにしろと言われてきたので……
すみません、簡略化時に#endifを削ってしまいました。 「sound_effect.h」の末尾に#endifがあるものとしてお答えください。
enum { SOUND_EFFECT_MAX = 45 };でいいだろ
俺ならメンバ変数にstatic const int SOUND_EFFECT_MAX = 45; ってやっちゃうな externだとリンクの時に初めて値が入るとかでコンパイル時にそういう風に使っちゃいけないんだろう
どうしてもexternでやりたいなら sound_effect.h extern const int SOUND_EFFECT_MAX= 45; sound_effect.cpp const int SOUND_EFFECT_MAX; だな
クラス定義はマクロじゃないからな。
const定数のリンケージがC++だと、Cと違ってそのモジュール内だけになるからだったか? そのルールって、C++は定数式で配列が初期化できるからあるってことかな?
黙して共用ヘッダの無名空間に収めとけよ
外部リンケージの const 定数は配列の要素数などには使えない仕様 内部リンケージ(const が付く場合はデフォルト)であっても、 実体定義より前には配列の要素数などには使えない 宣言だけでは無理で、コンパイラは 0 であると仮定してエラー復帰してコンパイルを続けるので 連鎖的に配列が 0 要素だとか変なエラーが出る class CSoundEffect{ public: static const int Max = 45; private: int File[Max]; int Flag[Max]; }; これでFA VC6のような化石コンパイラを使わない限りは大丈夫 VC6使うなら enum { MAX = 45 }; で
皆さんありがとうございます。 おかげさまで解決いたしました。
こっちにしようかC++11スレにしようか迷ったけどこっちで。 template aliasで下のコードがエラーになる(clangで)のは何故ですか? barはfooの別名だと思うのですが。 -- template<typename T> struct foo{ /*empty */ }; template<typename T> using bar = foo<T>; template<template<typename> class T> struct zot { /* empty */ }; void qux( zot<foo> ){ /*empty */ } void quux( ){ qux( zot<bar>( )); // ココ }
>>586 俺も好き。Java使わさせられるとき
同等の機能が無いから不便で仕方ない。
618 :
デフォルトの名無しさん :2012/04/18(水) 20:32:59.12
zot に bar を渡すときに foo のインスタンス化を要求するからだろ
fooのインスタンス化は出来るんじゃね? alias使わずqux(zot<foo>());だけならideoneでも通るし
C++規格素人だが>615はコンパイラの常識的挙動に照らしておかしくねえ? template<typename T> using bar = foo<T>; でbarを本当にfoo<T>の別名として使ってインスタンス化の片棒を担がせるには Tの型を明示的に与えるか、型推論できるような書き方であらねばコンパイラ困っちゃう 、希ガス
すわなち、(省略されている型パラメータUを補完したとして) template<typename T> struct foo{ /*empty */ }; のTはfooの自由変数だが、 template<template<typename U> class T> struct zot { /* empty */ }; において、 U,Tは束縛変数の1, 2であって、テンプレートzotの自由変数は 実は( template<typename U> class T )という全体である で、void qux( zot<foo> ){ /*empty */ } と書いたなら、この実体化では zotの自由変数( typename<typename U> class T)のTがfooでUがfooの自由変数T、と解釈できる (で、Uはzotの定義で使われないからUの定義が無くとも実体化できる。) 一方、qux( zot<bar>() )と書いたなら、barをfoo<T>の別名と解釈するときにTの定義が要るから、 上の話で言うUの定義が必要、という違いがある 、、多分、、
いま思いついたが>621説を検証するには、>615のコードの3行目を template<template<typename U> class T> struct zot { U x; }; に変更したときに4行目の void qux( zot<foo> ) { /*empty*/ } がエラーになるか確かめればある意味一応検証になる エラーにならなければ>621説は反証される
struct void std::wstring any(); return 3;
エイリアステンプレートはテンプレートとしては元のテンプレートと別物扱いってことなんだろ template<class X, class Y> class hoge {}; template<class X> using fuga = hoge<X, X>; みたいなときはhogeは引数2つのテンプレートでfugaは引数1つのテンプレートとしてふるまうから別物扱いするのが自然だし
WindowsXP以上,VC2003の環境です。 ある特定のウインドウの位置の変更や、サイズの変更があった場合に 通知を受け取るにはどうすればよいでしょうか? いまは、ループでずっとGetWindowRect()を呼んでいます。
イベントにWM_SIZEってなかったっけ?
627 :
625 :2012/04/19(木) 18:51:46.80
>>626 監視対象が、自分の作ったウインドウ(アプリ)じゃないんですよね。
DLL作ってフックしないといけないんでしょうかね・・・。
ループ使わないなら基本的にはフックじゃね vista以降は上位権限のプロセスのメッセージは取れないらしいけど あと使ったことないけどCreateRemoteThreadっていうので何か出来るかもしれない
629 :
625 :2012/04/19(木) 22:53:19.86
とりあえず、新しいプロジェクトでDLLを作って WM_SIZE,WM_MOVE,WM_MOVINGをフックできるようになりました。 それで、更新された新しいRECTをEXE側に渡したいのですが、 DLLからEXE側の関数を呼ぶにはどのようにすればよいでしょうか?
.exeの方にdllexportの関数って用意できないっけ? exeの方のウィンドウハンドルとってきてメッセージでもいいけど
セキュリティで弾かれるのはハンドルを取得する時だけで合ってた? 違うプロセスのウィンドウハンドルを指定してゴニョゴニョは問題ないっけ?
ヘンタイ仕様のAPIの話って、ここでして良いの?
Mayaのプラグイン作ってそんなかでFindWindowしてSendMessageしたりしてるけど特にはじかれはしてないなぁ、Windows7ね。 exeが多重起動してたらどれからとってくるかは知らね、目的は果たせたからあんま調べてない。
634 :
631 :2012/04/20(金) 01:25:31.84
あ、ごめん ここC++スレだった。 でもWin32スレに書いてもまともな返答返ってこなさそうだし困ったもんだね。
たびたびごめんなさい。
Windowsは一度公開API群を再設計したほうがいい 仮想化でやってるのは内部的な整合性を保つ為だろうけど どうせなら今までの粗雑なAPIはレガシー化させて 整合性のあるAPIとして生まれ変わったほうがいい 現状の#defineだらけのヘッダーやら互換性の為に残されたAPIやらは 一度分離してくれたほうがみんな幸せになれる
>>636 Win64は随分まともになってるじゃないか
Win64? DWORD→DWORD_PTRのことかね
.netのクラスライブラリ群がネイティブになって winapiは、なくなるのじゃないの?
現状では.NetのGUIはwinapiをラップしたものでしかないぞ…
メッセージとか継ぎはぎ感が否めないよな
C99対応を前提にして BOOLもbool型にしとくべきだろうね
>>636 WinAPI使わなきゃいいじゃん
使わない自由はある
MSだって昔は.Net Frameworkで切り捨てるつもりだったんだし
だから WinRT を設計したじゃないか
WPFでGUI APIを一新したかったんだろうけど、普及しなかったな。
粗雑で素朴なCのAPIでもABI的な意味で需要はあるし手間の点はQtとかのラッパで十分とも言えるし
Windows8でAPIが近代っぽいのに変わるんじゃなかった? Win32APIとかのレガシーなのをやっととっかえる気になったと聞いたが
.netとかwinrtなんてvmじゃ、いつまでたってもwinapiは撲滅させられない
俺もWinRTには期待してた ふたを開ければ機能限定版のWin32APIラッパだった Windowsにフタをしてやりたくなった
クラスについて質問です クラス内にメンバ変数しかなかったら newする度に変数の分だけメモリを消費するだろうと推測できるのですが 例えば、メンバ変数は2〜3個でも、メンバ関数が100個くらいある場合には newする度にメモリの消費量が半端ない感じになってしまったりしますか? クラスのメモリを確保した時の挙動がちょっと気になってしまいまして 詳しい方いらっしゃったら教えてくださいまし
>>650 こうかな??
ttp://ideone.com/8d2zK クラスのメンバ関数は普通の関数にthisを食わせる暗黙のパラメータがあるもんだと思ってもらえればイイと思うお。
だから、関数のインスタンスは、一個でいいし、最適化すればクラスに内包してる必要はないと思う。
ちなみに、テンプレート関数にするとちょっと事情が変わってくる。
template<typename T> class boo { friend class T; }; こんな具合にテンプレート引数をフレンドクラスにしたいのですが方法教えて下さい。
クラスのメンバでistream&をもってるんだけど、デフォルトは何で初期化すればいいの? class A { istream& is; A(): is(???) {} A(istream& is): is(is) {} };
悪い事は言わないから参照ではなくてポインタを使いなさい。
初期化できないのでA()は定義しちゃダメ
>>653 参照だと色々不便な気がするけど大丈夫なの?
んで、デフォルトコンストラクタをProtectedにするとか・・・。
すまん、もちろんpublic:を忘れている。 ストリームの終端をA()で表現して、 iter!=A() 的な判定をするんだが、654の根拠は何? iostreamってあぶなっかしい?
>>657 いや、参照は初期化時以外に実態を束縛できないのでNULL参照になりやすいからアブネーという話だと思うよ。
istream&じゃなくてistream_iteratorとか持ったら?
コンストラクタを別の場所から呼び出すのにthisを使う、次のようなコード(拾ってきたもの) って規格的にはアリでしょうか? struct sample_class { int value; sample_class(int i): value(i) {} sample_class() { *this = sample_class(10); } };
ありだけどそれぐらいならsample_class() : value(10) { }ってしたほうがいいだろ
>>658 ふむふむ、あんまそういうのに遭遇したことがないからよくわからんが、
シングルスレッドでワンショットで終わっちゃう(走り続けない)ようなソフトでもヤバイのかね?
>>659 そういう人もったことないけど、やってみるわ。アイディアありがとう。
>>662 実態が生きてるうちは大丈夫かな。デストラクタ走ったら死亡コース。
>>663 なるほど。自分が書くような小さいプログラムだと、
mainの最後だけでデストラクタ呼ばれるパターンが多いから、
いつも気にしてないんだよね。
でもこれからは気をつけてみるわ。ありがとう。
さっきのistream_iteratorを使えばいいという話ですが、これが通らない・・・ メッセージが邪悪すぎるから、誰か助けてくれ〜 #include <iostream> #include <utility> #include <iterator> using namespace std; istream& operator>>(istream& is, pair<int,int>& p) { is >> p.first >> p.second; return is; } int main() { istream_iterator<pair<int,int> > is(cin); }
グローバルフックするDLLからEXEに通知を受け取るために、 boost::functionをDLL側に渡して、DLLから呼び出したんですが デスクトップ、スタートボタン、タスクバーが消えましたww どうしたらよいでしょうか? (コンソールアプリや他ライブラリでDLLを使いまわしたいので、 ウインドウメッセージでは受け取りたくないんです) いまこんな感じです↓ >// EXE側 >boost::function<bool(STRUCT&)> func = &CallbackFunction; >StartHook(func); >//DLL側 >boost::function<bool(STRUCT&)> callbackFunc; >EXPORT BOOL StartHook(boost::function<bool(STRUCT&)> &func) >{ > callbackFunc=func; > : > callbackFunc(struct); >}
>>669 う〜ん、求めているものではないなぁ。
とりあえず、コンパイルエラーの意味がわからんかったんだが、
それに関して何かコメントない?
>>670 テンプレートを使った実装を使うときにエラー起こすと意味不明な文字の羅列が出て上級者でもイラッと来るらしい。
で、コンセプトっていう機能が入る予定だったけど、ウヤムヤになって空中分解した。
コンセプトがあればエラーメッセージはもっとシンプルになる予定だったそうな。
別に空中分解したわけじゃないよ コンセプトマップをユーザーが定義すべきか自動で定義されるべきかが決まらなかったのでC++11に入らなかっただけ
673 :
650 :2012/04/20(金) 23:59:43.85
>>651 さん
virtutal属性とかテンプレート関数の有無が鍵になる感じなのですね!
便利なクラスにする為に大量にメンバ関数を作る分には問題ない事が分かったので
安心してクラスを作り込みたいと思います。
ちょっと返信遅れちゃいましてごめんなさい。
どうもありがとうございました!
すまん。ちょっと誇張した。
676 :
デフォルトの名無しさん :2012/04/21(土) 00:03:44.63
>>671 メタプログラミングとかでエラー出ても、メッセージの雰囲気でけっこうわかるんだが、
stringとiostream関連はいまだに読めないw
678 :
デフォルトの名無しさん :2012/04/21(土) 00:09:21.77
パンピーで悪かったわね。
680 :
677 :2012/04/21(土) 01:11:26.04
すいません、色々調べましたがギブアップです。 EXEからDLLにコールバック関数を登録して、DLL側から構造体を受け取るにはどうすればよいでしょうか? EXE(またはコンパイラ)が変わってもDLLを修正せずにできる方法でお願いします。
shared_ptr使えばいけるじゃないの?
exeが適当なウィンドウを作って dllがFindWindowでexeが作ったウィンドウを見つけて そのウィンドウハンドルにWM_COPYDATAで構造体を送り付けたらいい
683 :
677 :2012/04/21(土) 01:54:10.77
コンソールアプリや関数だけのライブラリからも呼びたいので、 メッセージは使いたくないんです>< 関数ポインタはDLLとEXEでアドレス空間が違うんですかね>< >// EXE側 > >bool CALLBACK func(STRUCT struct){ > return true; >} > >int main(){ > StartHook((LPVOID)&func); > : >// DLL側 >EXPORT BOOL StartHook(LPVOID func) { > STRUCT data; > data.dat = 0; > > bool (*callback)(STRUCT); > callback = (bool (*) (STRUCT))func; > callback(data); // ←この次の行の関数呼び出しでランタイムエラー >
共有メモリとか名前付きパイプとか
685 :
677 :2012/04/21(土) 03:43:58.56
共有メモリだと、フラグとか値が変わるのを無限ループで監視しないといけないですよね? それは無駄に重くなるのでやりたくないんですよね。。。 名前付きパイプ調べてみましたが、イベントってのが使えそうな気も・・・。 それと、DLLからEXEの関数呼び出しはなんとなくできました。 EXE側の関数をdllexportして、DLL側からEXE側にGetProcAddress()して関数アドレスを取得して 呼び出せました。これなら新しいEXEを作るときもDLLを変えずに済むかなと思ったのですが、 フックプロシージャからEXE側の関数を呼び出すと、なんかダイアログ出てきてシステムに無理やりDLLをとめられました・・・。 自分のミスなのか、フックプロシージャ内はなにか特別なのか??
当たり前だろ フックされたプロセスとフックを仕掛けたプロセスは違うんだから 呼び出せるわけがない
どうでもいいけどC++関係ねぇ
689 :
677 :2012/04/21(土) 04:04:56.72
>>686 そうなんですか・・・。
EXEと静的リンクしたDLLは同じプロセス空間、
DLLのフックプロシージャの中は別のプロセス空間ということでしょうか?
>>662 コンストラクターの引数は参照で、
内部ではポインターで保持したら?
c++ではmallocとfree関数はつかわないんでしょうか? newとdelete演算子ですか?
deleteも使わない
えっそうなのw 横から便乗で質問だけど、コンストラクタ・デストラクタ呼び出したい時はnew deleteなのはわかったけど その必要がない場合でもnew deleteすべき?
そんな質問する様なら、1つ良い事を教えてあげる。 混ぜるな危険!
newは遅いという説が・・・・
newの中身は普通はただのmallocだよ 他にはコンストラクタも動かすけど、それはplacement newでも同じ
>>697 placement newを教えるからにはstd::aligned_storageもだな…。
そしてoperator new の闇に嵌まって逝く訳ですね
>>666 istream_iteratorの中からは自分でグローバルに定義したoperator >>が見えない(stdのoperator >>に隠蔽される)からエラーになる。
・解決法の一つ。stdじゃない場所に自分で定義したクラスを介する。
class mypair
{
pair<int, int> p;
public:
mypair() : p() {}
mypair(pair<int, int> const & p1) : p(p1) {}
operator pair<int, int>() const { return p; }
istream & readvalue(istream & is) { return is >> p.first >> p.second; }
};
istream & operator >>(istream & is, mypair & pr)
{
return pr.readvalue(is);
}
int main()
{
istream_iterator< mypair > is(cin);
pair<int, int> p = *is;
}
>>691 malloc()は使用する必要性がほぼ0になるが
個人的にはrealloc()はしばしばまれに使うべ
std::vector()が使えるならそれに越したことは無いが
reallocはPOD型(C++11では概念変わったけど)にしか使えないのがねえ まあ、環境依存でいいなら多少危険でも使えるケースはもうちょい多いと思うが
デフォルトのnewだとサイズsで取った領域をサイズs+1にしたいとき無条件にnewし直ししかないじゃん? realloc()はヒープ管理のリンクリストに直に触るから、サイズsの既存分を動かさずに済むことがある std::vector<T>が中で何やってるかは知らんが、案外realloc()を呼んでいるのではないか
707 :
デフォルトの名無しさん :2012/04/21(土) 23:55:39.79
708 :
デフォルトの名無しさん :2012/04/22(日) 00:01:56.82
newのデフォルトの実装は、環境やコンパイラに依存だろ。 reallocとかと混ぜる根性がよくあるな、おまえら。
>>706 実装によるけど一般的には、vector<T>は要求よりも多めに確保して現在の利用状況をリポートする。
領域確保時は、何だったかな、現在の1.5倍だったかの領域をnewしてコピーするんだったかな。
まー、実装依存だわね。
>>706 reallocなんで呼ぶわけないだろw
事前確保の容量超えたら新しくnewしてコピー/ムーブだよ
>>709 GCCとMSVCがそれぞれ1.5倍と2倍(どっちがどっちか忘れた)だったはず
勝手にコピーや元の領域の開放を行わないreallocがあれば vectorもどきを作るのに使えるのにね・・・ 伸ばせるなら伸ばす、伸ばせなければ失敗、 あるいは、新たな領域を確保して、それを返すだけ、という
>>711 誰がコンストラクタ走らせるの?
そういう用途はプレイスメントnewという機構があるよ。
>>712 vectorがどういう風に実装されてるか知ってる?
714 :
デフォルトの名無しさん :2012/04/22(日) 01:19:53.01
実装を知らないと使えない、とか、 オブジェクト指向と言うかC++の思想に反するよな。
>>713 詳しくは知らない。
でも、アロケータにメモリ確保を任せて帰ってきたメモリをプレイスメントnewしてるのかねぇ。
オブジェクトをプッシュバックしたら、コピコンかムーブで移譲だよね。
その段階で破棄されるオブジェクトのデストラクタ走るし。
俺はユーザープログラマだからそんな詳しく知らなくても使える。と、言い訳。
717 :
716 :2012/04/22(日) 01:25:35.85
アロケータの実装がreallocであることもある可能性は捨て切れない。
reallocは絶対に使えないのよね 領域が移動する場合に、reallocが勝手に内容をmemcpyするから ちゃんとしたコピーなりムーブなりが行われない 逆に言えば、この領域移動さえなければ使えると言う事
719 :
716 :2012/04/22(日) 01:32:35.49
ほぇ〜。そうなんだ。 アロケータのことはよく知らんのよ。実装する機会もないし。
newした内容をmemcpyでコピーできないのと同じ事さ アロケータの知識は正直あまり関係ない
※ただしPOD型は除く
722 :
716 :2012/04/22(日) 01:47:33.69
>>722 PODだろうとmalloc、realloc、freeは使うなよ
おいおいnewで確保したか、mallocで確保したか
管理しきれなくなってバグの原因になりかねんから
PODとCの関数で思い出したが、POD型にmemsetでゼロ
初期化するヤツなんなんだろうな。
Type value = {0}; こういう形で十分だろうに。
Type value = {}; こうだろ
>>718 >>720 それって、要素型Tにコピーコンストラクタが定義されていれば
どうとでもなるんじゃねwwwwwwwwwww
代入と異なりコンストラクタは構築先が何であるかを問わないから
(そうでない作りにすると普通の構築時に必ずバグって発覚する、)
生のメモリ領域を与えてから構築することができる
、、ハス
>>723 それ警告出すコンパイラあるから俺は使わない
>>725 reallocが内部でmemcpyするって言ってんじゃん
コピーコンストラクタもoperator==もガン無視でbitwiseコピーされる
>>726 Cの仕様で定義されてるんじゃなかったっけ?
俺はそういうふうに習ったけど。
某らんどとかは、変数の初期化処理に警告だしたりするからな。あれは不味いだろうと思う。
定義はされてるよ でも、初期化忘れか、意図的な0クリアかを コンパイラが機械的に判断するのは難しかろう
それともいっこ、単純にあらかじめ大きめの容量を確保しておくという戦略は 使わないかもしれないオブジェクトについてデフォルトコンストラクタを呼んでしまう欠陥がある コンストラクタというのは初期化しか仕事しないから高速を要する処理中に極力呼びたくないわけよ この意味でも常にぎりぎりの領域サイズでrealloc()しつつプレースメントnewというのは 高速処理中にちまちまstd::vec<T>のインスタンスを生成するのに比べたらかなり手堅い (本当に手堅いのは高速を要する処理開始前に必要なサイズを全部確保しておくことだが)
命令型言語のPGで新規の領域を不定値のままにして気持ち悪くない奴はカス なぜなら、命令型言語を選択したPGはその時点でチューリングマシン教の教徒であり、 チューリングマシンは状態の書き換えによって計算を進めるモデルだからだ そのためのType a = { }だったり(new Typeではく) new Type() 構文だろうノシ
>プレースメントnewでrealloc()した後にコピーコンストラクタで構築 とか意味が分からないけどとりあえず >使わないかもしれないオブジェクトについてデフォルトコンストラクタを呼んでしまう std::vectorもそんな挙動はしないよ?
>>734 >std::vectorもそんな挙動はしないよ?
ちょっwwwwごめwwwwwwwwっうぇwwwwVS2010のstd::vector<T>で今調べたらそうだったわwwwwwww
(確保した要素数しかデフォルトコンストラクタが呼ばれた)
>意味が分からない
サソプル イズ ベスト:
struct TypeB {
int x;
TypeB() : x(-1) { }
TypeB(const TypeB& other) { x = other.x + 100; } }; // コピーされたら100足される
void test2() { const int n = 100;
TypeB* sizableArray = (TypeB*)realloc(0, sizeof(TypeB) * n);
for (int i = 0; i < n; ++i) {
TypeB a;
a.x = i;
new(sizableArray + i) TypeB(a); // It's new!
}
for (int i = 0; i < n; ++i) cout << "sizableArray[" << i << "]=" << sizableArray[i].x << endl;
}
実行結果は、sizeableArray[0] = 100\c\rsizableArray[1]= 101\c\r...
語るね〜 終わったら呼んで。
>>731 bitwiseコピーした後にどうコピコンすんだよ
既にアドレス変わってる上に、初期化元は自分自身だろ
>>737 >new(sizableArray + i) TypeB(a); // It's new!
>>739 アドレスsizableArray + i以外の場所にあるTypeB型のオブジェクト
元データを論理的に保存しないといけないのに なんで別のものでコピコンすんの?
>>741 コピコンで元データが論理的に保存されないとする根拠は?
>735のサンプルにおけるTypeBのコピコンにおいて、仮に100を足すのをやめたら
>738で(スタック上の)aと論理的に同じオブジェクトがアドレスsizableArray + iにできるわけだけど?
>>742 そもそも、realloc したら元データが元の場所から無くなるんだよ
というか、
>>735 読んでなかったが、今話してる事じゃねえよこれ
vectorの伸張の話してんだぞ?
>>743 ああスマン、それはそうね
p1がTypeBのコピー元配列srcArrayを指しているとして、
TypeB* p2 = realloc(p1, sizeof(TypeB) * n)
の実行後、p2 != p1でありなおかつsrcArrayの要素がsrcArray内の他要素のアドレスに依存するならそうね
しかし>702以降の流れはstd::vector<T>との比較という文脈なのを思い出してホスイ、
Tにそのような型が許されるだろうか?
>>731 意味が解らん。reallocで1度コピーreplacement newでもう一度初期化。
処理が遅くなるだけだろ何のメリットが有るんだ?
>>733 命令型ってbashとかzshだろ
メモリ確保は自動で行われるから
確保も開放も意識する必要は無い
あれだけruby厨だったuy(
>>735 )がC++に手を出すようになったか
>>730 memset か std::fill に決まってるジャン(std::fill_n は警告出る事あるのでやはり使わない)
= { 0 } は可読性に劣るとも思うしね
初期化忘れか意図的な 0 クリアかが
コメント残さないと確実に伝えられないから
最初の 0 がある意味マジックナンバーじみているのも気持ち悪い
普通構造体に = { 0 }してたら初期化だと思うがな。 あと組み込み向けのしょぼいコンパイラーだとこっちの方が早いことがある 逆にmemsetの方が早いってのは聞いたことないけどね
>>751 それ初期化じゃないじゃん。
それに
={};
で初期化し忘れと読み取るアホはおらんよ。
= { }; は C で使えないよね
使えないけど、それがどうかしたの?
知らない人が結構いそうだから使いたくないわ
>>747 >reallocで1度コピー
領域拡大時であってもrealloc()だとコピーが起きないことがある
縮小時はもちろんほぼ常に起きないことが期待できる
>replacement newでもう一度初期化。
誰も2回も初期化しないわけだが
つかデフォルトのnewは使えば必ずメモリ確保してから初期化するのに対し、
プレースメントnewはそれ自体はメモリ確保しないから、
メモリがすでに確保されている場合はより早いの
ワカル?
>>748 ソウジャナイ
破壊的代入が本質的(それ無しには何事も進まない)のが命令型言語、
非破壊的代入で全て済ますのが関数型言語
前者はチューリングマシン、後者はλ式をそれぞれ数学的基礎とする
一方で書けるアルゴリズムは他方でも書けるという意味で両者の計算能力は等価
ただし得手不得手はもちろん違う
>>758 どこらへんがおかしいのかkwsk
つかrealloc()が勝手にコピーするとオブジェクト必ず壊れるとか思ってる?
std::vector<T>の要素型として使える型Tについてはそれは心配せんでええ
>領域拡大時であってもrealloc()だとコピーが起きないことがある >縮小時はもちろんほぼ常に起きないことが期待できる どういう理屈なんだ?
>>759 関数型は、演算式と制御文を全て関数で記述する事を目的とした言語
破壊的代入が無いというだけだと宣言型とダブるので、
破壊的代入が無い = 関数型というのはおかしい
>>761 K&Rの終わりぐらいに書いてあるmalloc()の実装例でも読めばおk
サイズs1、s2の領域がこの順で隣接しており、s2が開放されたなら
サイズs1をサイズs1+s2までコピー無しで拡大することができる
(※簡単のため管理用のヘッダサイズは無視)
>>762 関数型言語であってもリストで手続き(順序的な処理)を表わせるから
手続き型/非手続き型の区分は命令型/関数型の切り口とは異なる別概念
Prologみたいに処理の順序が平に書かれない言語を非手続き型といい、
手続き型というのはそれの対義語
>>763 宣言型というのは、ようわからんが非手続き型っていうのとほぼ同義ジャネ?
破壊的代入無しでチューリングマシンの計算能力と等価な言語、
といえば多分λ式ベースの言語(つまり関数型言語)しかないんじゃないかなあ、、
なお、関数型は、(関数で)新しい関数を作り出すことしかしない故に関数型
>>764 mallocじゃなくreallocの内部の話なんだけど
実際コピーしない処理系が存在するのか?
gccのreallocはソース公開されてるがコピーしてる
実際どの処理系がしてるんだ?
普通に考えてもmalloc内部の実装に依存するreallocなんてクソだろ
>>764 >関数型言語であってもリストで手続き(順序的な処理)を表わせるから
>手続き型/非手続き型の区分は命令型/関数型の切り口とは異なる別概念
>Prologみたいに処理の順序が平に書かれない言語を非手続き型といい、
>手続き型というのはそれの対義語
お前だけの常識で語られてもなぁ
>>766 realloc()をmalloc()と別階層とすべきですかそうですか、、
コピーを生じない処理系の具体例については、
少なくとも下記コードをVS2010で走らせるとp1 == p2なんだけど?
void* p1 = malloc(1000);
void* p3 = malloc(1000);
free(p3);
void* p2 = realloc(p1, 2000);
cout << "p1=" << p1 << ", p2=" << p2 << endl;
glibcのソースをよく読みなおすことをお勧めする
>>767 漏れだけの常識がどうかはようわからんが、そうなの?
>764で妥当だと思うがなあ〜
で、いつまでちんたらちんたら続くんだ?
>>760 おいおい、オブジェクト領域でreallocなんか使ったら壊れるだろうがw
ポインタ関係が全部おかしくなるわ。
>>768 サイズ変更が「可能な場合」はコピーされない。不可能な場合はコピーされる。
コピーされる場合はありえるんだが、たまたま特定環境化で動作するから使っていいとかアホの極み。ドシロウト。
仕事でそれ使ってたらリアルで背任でクビになるようにもっていく。
>>768 そのコードじゃそりゃそうだろ。
つかそのコードはreallocの問題じゃねぇ。言い方悪かも試練が偶然だ。
解放された領域をもう一度使用してるのは意図して書けばできる事だが、
reallocが同じ領域であることを知っててコピー処理を省略してるかどうかは別問題。
>>770 >ポインタ関係が全部おかしくなるわ。
ポインタを含まないか、ポインタを含んでも指す先が移動対象でないなら
そういうオブジェクトは勝手にコピーされても無問題でしょ?
で、std::vector<T>の要素型として使えるような型Tのオブジェクトなら、それは成立している、というしくみ
>>771 >>772 まあ冷静に
コピーされる場合がありえるし、コピーされる/されないを
realloc()の呼び出し側で制御できないのは承知していますから
ただ、std::vector<T>の要素型として使えるような型Tのオブジェクトなら、
プレースメントnewをうまく使って安全にrealloc()で領域管理できるという話
775 :
デフォルトの名無しさん :2012/04/22(日) 21:54:51.43
マジレスしないでニヨニヨ笑ってる人が絶対いる悪寒 あまりにも不自然すぎる
>>774 二重コピーされる分realloc使うのが無駄なのは事実だろ
まだmalloc, free, mallocしてreplacemente new呼んだ方がマシだ
>>776 ちょっと前のレスから気になってたが、replacement newってなんぞね?
また、realloc()の呼び出し1回で同一オブジェクトのコピーが2回起きるみたいな書き方も気になるが、
それっていつどういうシチュで??
もし>738のようなコピーコンストラクタ呼び出しの回数のことを言ってるのなら、
それはrealloc()一回につき同一オブジェクト当たり1回以下にできる
(realloc()がコピーするかしないかや呼び出し下で制御できないが、
領域の移動があったかどうかは呼び出し元で判定でき、移動しなかったオブジェクトについて呼ぶ必要はないため。)
その程度の処理が問題になるなら動的確保自体使わなきゃいいだろ。 まずはEffectiveC++でも嫁やザコ
779 :
777 :2012/04/22(日) 22:10:35.64
スマン訂正 std::vector<T>の要素型として使えるような型Tのオブジェクトなら、 勝手にコピーされても何もする必要がないから、領域の移動は関係なかったな、、
>>777 reallocで1回、new( buffer ) Type();で1回、合わせて2回だろ。
>>773 自分自身をさすポインタをもつ場合、コピーコンストラクタ/operator=を正しく書けばvectorに入れられるが、メモリコピーでは正しく処理できない。
>>780 普通そうはならないべ
サイズs1の領域が確保済みで、realloc()でそのサイズをs1+s2に拡大する場合、効率的な実装なら、まず>764(の前半)のようなケースでは実質コピー0回。(空き領域リンクリストの繋ぎ替えが起きるだけ。)
運が悪ければ、領域の移動を要し、サイズs1の部分のみコピーされる(コピー1回)。
ここには今の想定だと構築済みオブジェクトが入っているが、コピー安全なオブジェクトなのでそれ以外なにもしなくていい。つまり、コピーはオブジェクト毎に高々1回。
で、new(p) Type(); が必要なのは、新規に確保されたサイズs2の領域だけ。よって、2回コピーされるオブジェクトは生じない。
なお、細かいことを言えば、new(p) Type()はアドレスpについてType型のデフォルトコンストラクタを呼び出すだけなのでコピーではない。
また、Typeのデフォルトコンストラクタが全フィールドを確実に初期化する保証があるなら
new(p) Type(); と書くより new(p) Type; の方がよろしい。(0 fillが省略されるから早くなる。いつの規格からかは知らん。)
>>781 ああすまん、それはそうね。
>>782 >サイズs1の領域が確保済みで、realloc()でそのサイズをs1+s2に拡大する場合、効率的な実装なら、まず>764(の前半)のようなケースでは実質コピー0回。(空き領域リンクリストの繋ぎ替えが起きるだけ。)
この前提が間違ってるって何度も指摘されてるだろ
>>782 手間が増えるだけでreallocするメリットねぇじゃねぇか
>>783 >何度も指摘
kwsk
すくなくとも、(たまたまかどうかはともかくとして)realloc()前後で領域が移動しなかった実例が>768にあるわけだが
これって呼び出し前後でアドレスが変わらない部分についてもrealloc()は律儀にコピーしてるってことなの??
>738おすすめのヒープメモリ管理方式を聞いてみたい気がするカモメ、
>>785 ことなの?じゃなくコールスタック追いかけるか
逆アセしてみろよ。memcpy呼ばれてるだろ
>>786 VS2010のデバッグモードでmemcpy()にブレークポイントしかけて見て見たが、
>768のコードにおける4行目
void* p2 = realloc(p1, 2000);
の呼び出し中のmemcpy(src, dst, count)の呼び出し回数は3回、ただしcountはどれも2だったべ
これはリンクリストか何かのコピーじゃねーの?
(>783の指摘どおりだとしたら1000バイト級のmemcpy()が起きないとおかしいが)
で、仮に万が一>783の指摘が正しかったとして、2回コピーされる件はどうなったのよさ?
主張を取り下げて>782で納得?
不毛だ
>>787 2回コピーは俺だが。新しい領域のみコンストラクターの結果を
コピーするんならたしかにコピーは1回だな。そこは納得するよ。
>>790 ちょっwwwwwwおまwwwwwwwwww
例示のコードはrealloc()とは話が違うわけだが
そりゃーfree()で本当に解放してしまった領域には誰に何書かれるかわからんでしょうよ
(別スレッドあり、デバッグビルドのfree()だと丁重に0xccccccccで埋めてくれたりすることあり。
セキュリティー目的で埋めるライブラリもあるかも試練、)
なんつーか>768のコードの意図が伝わってないようだけど、
K&R式なmalloc()およびrealloc()な実装の下で>768をシングルスレッド状況で走らせると
>782で言うコピー0回な挙動になるんすよ
>768は、その挙動を演出するために、使用中の領域(p1)とは関係ない領域(p3)を一旦malloc()後にfree()してるだけ
p1が指す領域は一貫してfree()されない。
>>779 vector の要素型に realloc() で発生しうる memcpy() への耐性なんて要求されてないんだが
>>791 realloc内部でfreeされるがな
だから、C++ならnewだけを使えよ。 わざわざ危険を犯そうとする冒険者になることは、ない。
newの使い方よりも newそのものの速度が問題になる状況って どんな状況だ?
もうほっとけよ
class MyClass{ public: bool hoge(); } MyClass instance; があるとして、 「instance.hoge()」 が与えられたときに、 「MyClass::hoge(),&instance」 を返すようなマクロは作れませんでしょうか?
メンバ関数ポインタ
799 :
797 :2012/04/23(月) 04:25:55.73
なんとか、 「instance.hoge()」 という記述から、メンバ関数ポインタとthisポインタを取得したいんですよね。。。
「&MyClass::hoge,&instance」が欲しい理由じゃないのか?
801 :
797 :2012/04/23(月) 12:43:53.90
これが欲しい理由は、一度&MyClass::hogeと&instanceを保存しておいて、 あとでそのメンバ関数を呼び出したいんです。 使う箇所が多いので、テンプレートとかでなんとかできないかと思いました。
std::bindとstd::functionでおk
803 :
797 :2012/04/23(月) 14:26:18.17
いやそれだと、 bind(&MyClass::hoge,&instance)って呼び出さないといけないじゃないですか。 これをbind(SUPER_MACRO(instance.hoge()))で記述できるようにしたいんです。
#define SUPER_MACRO(expr) ([] () { expr; })
805 :
デフォルトの名無しさん :2012/04/23(月) 14:49:33.81
メンバポインタの書式が限定的なのが気に入らないわけね &MyClass::hoge //現状 ~~~~~~~~~~~ &instance.hoge //こう言いたいだけ
>>803 std::function<T ()> hoge = std::bind(&MyClass::hoge,&instance);
hoge();
hoge();
で我慢しなさい
実行時型情報を使う場合は、 型情報の取得や比較などするクラスについてのみ型情報がバイナリに埋め込まれるのでしょうか? それとも全てのクラスの型情報が埋め込まれるのでしょうか?
全て
じゃあ自前でやりますかな。
>>774 自身内部へのポインタを持ってても
std::vector<T>のTとして使えるだろ常考
>811 >781
vectorって vector<char [1000]> みたいに配列を型として作ることできないんでしょうか?
<固定長の配列>の配列ならboost::arrayをvectorに突っ込む。 <可変長の配列>の配列ならvectorをvectorに突っ込む
配列型は定数なので無理です・3・
ちっ 無理か char *にして毎回メモリ確保してぶっこむわ サンキュー アディオス!
>>816 なんで既に vector を使ってる文脈で自分でメモリ確保・解放しようだなんて考えるの?
>>816 アラインメントの問題もあるし、自分でnew/delete管理するのは不可能ではないながらも非常に苦労する部分であるし
毎回メモリ確保するならstd::vector<std::vector<element_type>>ってした方が良いと思う。
boost::array という解答が出てるのに・・・ boost 使うの嫌なら、構造体に配列だけぶっ込んだ奴を使え
テストしてみたけど、typedefすらできんのだな。ふむ〜。 Tのサイズ示してナンセンスさを醸し出そうとしたけど大失敗! あれ上手く行ってもポインタ投げてるだけだよな。
C++でおk
823 :
816 :2012/04/24(火) 00:25:57.46
正直アラインメントがよくわかってないっす boostは使ったことないっす vector<element_type>ってのもよく知らないっす 自分でnew,deleteすんのもforループでぶん回して開放するだけなんで苦にならないっす
vector<vector<T>>だと君がnewとdeleteを管理しなくてよくなるよ。 Tはintとかcharとかの汎用表記だと思ってくれ。
>>823 それで苦にならんということは、おおかたエラー処理まで考慮すると間違ったコードができあがってる。
マジすか
じゃあ
>>824 さんがおっしゃった方法ちょっとやってみます
ありがとうございました
boost使った事がなくてboost::arrayを敬遠しているなら template<class Type, std::size_t N> struct wrapped_array{ typedef Type type; static const std::size_t size = N; type elements[size]; }; ってして std::vector<wrapped_array<char, 1000>> とすればいいよ。 アラインメントは、単にこちらが「汎用ヒープ領域をchar単位で管理する」と思い違いしただけだから ここではあまり関係ない。 new,deleteをforで回すのは行儀が良くない、というわけではないけど デストラクタ以外でnew,deleteを回すという行為自体が、その前のプロセスで例外などが起こった場合の リーク原因になるからスコープ防壁やshared_ptr等を実装する時以外は直接使わない方がいい。
>>823 まぁとりあえず使ってみなよ
馴染みの方法を取るのはその後でも遅くは無いさ
>>768 このコードの前に
void* px = malloc(1000);
void* py = malloc(1000);
free(px);
これをやるだけでデバッグビルドじゃとおってもリリースじゃとおらねぇダロアホ。しね。
>>827 難しそうですね
まあなんとかやってみます。
>>828 気になってはいたんで一度挑戦してみましょうか
ありがとうございました!
>>827 俺へタレでさっぱりなんだが
static const std::size_t size = N;
でstaticつけるのは何で? 付けないと何か問題生じる?
コンパイル時定数にならないし 直接初期化もできない というか、実際にstatic消してコンパイルしてみろ
iteratorを仮想化してくれるWrapper Libraryってないですかね? const InputIterator &begin = InputIteratorImplement< std::vector<int>::iterator >( vector.begin() ); こんな感じで。 なにがしたいかというと、仮想関数の引数にiteratorを使いたいのです。
ないだろうねぇ
>>832-833 ありがと。でも何でstatic無だとコンパイルできないのか分らん,orz
wrapped_arrayに要素をどうやって入れるのか、どう要素を参照するのかも分らん
>>836 static無だとタダの書き換えし辛い変数として扱われ
やろうと思えば実行時に書き換えられるから
実行時に書き換えられる値は定数として使えない
>>837 ありがと。ある程度知識ある奴ならその説明で分るんだろうが
俺、C++がほとんど分ってないからな
要素へのアクセスってCのstructと同じように出来るんだな
>>838 親父な俺が中級レベルになるのに役立った本を教えるよ。
エキスパートCプログラミング(訳:梅原系)
EffectiveC++(訳:吉川邦夫)
この2冊かな。More EffectiveC++もまぁよかったよ。
>>835 仮想関数に不特定のiterator渡したいときどうしてます?
なにいってんだよ、今時そんなんじゃ中級にもなれないよ。 テンプレート完全ガイドが「せいぜい中級」と言われる世界(すでに初級扱い)で いまさらその2冊は厳しいっすよ。
仮想関数にしなけりゃいいだけ。
仮想関数にしないと実行時に実装きりかえられないんですが
>834 ないね。仮にあったとして(名前Itとして)、 typename std::iterator_traits<It>::difference_typeは何になるというんだい?
静的にしか出来ないことを除いたサブセットにすれば問題ないんじゃないですか? 値を書き込むだけでしたら、その手の定義は不要でしょうから。
>>840 入門書読んでEffectiveC++読んでやっと初心者卒業くらいだろ…?
中級っていうと例外安全なテンプレートを自然に書けたり、
ちょっとしたメタプログラミング的な処理を書けたりするレベルじゃないの
>>846 仮にあったとして、どう扱いたいの?
InputIteratorで何でも受け付けるなら*itはvoid*でも返すの?
自分で必要とするinterface決めて、使う型に応じてアダプタ書いた方がいいんじゃね?
おまえらは自分はC++何級って思ってるんだ? 初級、中級、上級、神仙人級....
>>848 やっぱ自作ですよね。
コンテナは未定ですが、入出力する型(wchar_t)は決まってます。
できれば、書き出しだけじゃなく読み込みもしたいんですけどね。
やっぱ禿が最高ランクの称号だよな
>850 class base { virtual void process_one( wchar_t c, context &ctx ) = 0; public: template<typename Iter> /* non-virtual */ void process_iter( Iter from, Iter to ) { context ctx; for( ; from != to; ++from ) process_one( *from, ctx ); } }; あたりでいいだろ。
854 :
840 :2012/04/26(木) 00:16:49.07
御幣があったか。「中級になるのに役立った」ってのを正確に言うと、 「初心者ゾーンを抜け出すきっかけになった2冊」であり、その後の別の経験やきっかけで 「中級になった」ということです。
スキャンラインアルゴリズムの回答すら1月まともな答えを出せない板の住人が神級とな
こないだ他の場所でスキャンラインのアルゴリズムを即興で考えて講釈たれたんだけど俺の何級?
そんなこと言われたら ショッキュウやわ。
>>858 初級じゃね?ラジオシティぐらいいかないとな。
>>860 ラジオシティなんてリアルタイムで光源もりもり動かしたいとかでない限り楽勝じゃね?
数レスで人にやり方伝えるとこまでだったらちょっと難易度高いけど。
>>862 スキャンラインにしても、ラジオシティにしても実装するだけなら
まともに学校行ってる人間ならできるじゃん
C++使ってんだからいかに実用的な速度と再利用性を維持できるかに
答えられなきゃおはなしにならなくね
スーパーハカーがそろっているようですねwww 次は年収自慢でも始める?
年収なんざどうでもいい結果で示せ
うわっ…私の年収(ry
無職ですが何か? 面接受けただけで働く気がなくなるような企業ばかりだ
>>865 一度はドロップアウトした清人だからこそおっさんの面白さを見落とさず拾い上げる事ができたし、それを伝える事もできた。
同じ伝えるプロでも、金持ちに生まれてリア充一直線を突っ走ってきたアナウンサーにこの面白さは伝えられないし、
受け手が勉強ばっかりやって来たオタクではやはり理解する事ができない。
必要なのは人生経験という共通の背景。
人生経験でも挫折の連続じゃいくら経験しても意味がないんじゃね
871 :
デフォルトの名無しさん :2012/04/29(日) 14:11:15.57
struct X { int& a; double b,c; }; みたいなクラスあるいは構造体があったとき、 ・メモリの連続性は保証されていますか? ・オフセットを指定する文法はありますか? Cなら unsigned offset: 16; みたいなのがあった気がするんですが。
>>871 a,b,cの順番で並んでる事は保証されるが、
a,b,cが隙間無く並んでることは保証されない。
オフセットは標準ではなかったんじゃ無かったっけ?
大体の処理系でoffsetofが使えただろうけど。
別の方法としてメンバー変数のポインタを使う方法もある。
int (X::*n); //こんなの
ビットフィールドのことかね
>>872 バイナリ出力するときに、そのままの順序で吐き出せるかと思ってましたが、そうなんですか。ならメンバーで
double bc[2];
とかを持っておいて、個別にアクセスしたほうがいいですね。
ありがとうございます。
>>871 a, b, c の順番は保証されてるけど、間は詰まっているとは限らない
各メンバのオフセットを直接指定する事はできないが、
間の詰まり方を調整する事はコンパイラによっては可能な場合もある(環境依存)
VC++ と g++ では #pragma pack で調整できるのでググれ
ここまでは、C でも同じ
最新規格の C++11 だと alignas を使って
C++11 対応コンパイラ間であれば環境非依存で調整可能
ただし、もちろん C++11 に対応していないコンパイラでは使えない
>>873 本当は、aを飛ばしてbcだけをバイナリ出力したかったのです。
ビットフィールドが欲しいわけじゃないので、勘違いでした。
>>874 アライメントというのがあって、それ意識してメンバーを並べてりゃ隙間は開かないよ。
>>875 おぉ、有益な情報ありがとうございます。
じぶんでググってみますが、特に有用なページとかあれば教えてください。
>>879 横からだけど、template引数に型を突っ込んでアラインメントを得る事自体が
アラインメント適用した後のストレージの後ろに隙間が開く可能性を孕んでいる。
>>879 #pragma packと似たような環境依存だよ。
基本的同じOSで動くコンパイラーが生成したコードだと
アライメント規則が同じになる。
こっちは、OSに依存するけどコンパイラーに依存しない。
>>876 bとcだけなら型が同じなので
連続して記述してあれば配列と同じメモリ配置になるよ
offsetof で先頭からのオフセットが取得可能なので
そこから sizeof(double)*2 だけ出力すればいい
まああんまお勧めしないが
b, c を別構造体にして、それを出力した方が素直だと思う
32bitなら、4の倍数で塊になるようにメンバーを並べればいい。 例えばshort a; int b; short c;だと、aが4の倍の倍数にならないので2バイト穴が開く。 int b; short a; short c; と並べてやれば穴は開かない。
>>875 pragma pack なんかは char アラインしかされない int とか作れるけど、
alignas じゃそういうのはできないよ。 (7.6.2 p5)
#include <iostream> using namespace std; struct X { short x; int y; short z; }; struct Y { short x,y; int z; }; int main() { cout << sizeof(X) << endl; cout << sizeof(Y) << endl; } こわ〜い(笑
>>882 > bとcだけなら型が同じなので
> 連続して記述してあれば配列と同じメモリ配置になるよ
そうなるコンパイラが多いのは事実だろうが、何の保証も無い。
OSもコンパイラーもどっちの依存も完全になくすには、1メンバーずつ書き込むしかないわな
エンディアンとか考えはじめるとガクブル・・・ C++11でその辺も何とかなったりしないのだろうか。
移植性を考えるなら、テキストでやるか1バイトずつやるか、昔からこの2択でFAだろ。
ローカルで定義された構造体ってstaticメンバ関数はもてるのにstaticメンバ変数はもてないんですかね?
と、そのまえに関数G内で関数Fを定義って不可能ですか? 一応方法としてG内で構造体Sを作りその中でstaticメンバ関数Fを定義すれば良いみたいですが このFからGの変数にアクセスする方法はありますか?
>>891 関数のローカルstatic変数にアクセスできるから。
staticメンバー関数は、static変数を操作するための関数というより
どちらかというと、static関数が属してるクラスのオブジェクトを操作するための関数。
ホントですね じゃあと思ってstatic関数を関数内定義しようとしましたがこれは出来ませんね うーん
関数内関数はラムダをキャプチャすればできるかも。
仕事でC++11って使ってる?
898 :
896 :2012/04/29(日) 22:32:53.75
趣味グラマですの。
ラムダ式は関数オブジェクト作るだけだからそれでいいなら03でもローカルな関数オブジェクト作ればいんじゃないか
900 :
896 :2012/04/29(日) 23:45:52.61
自分は892とは別人ですの。
>>897 C+11をサポしているコンパイラーってあんまりないんじゃない
VC2010サポートしているのか
>>901 VC2010だって一部しかサポートしてない
ラムダ式は大丈夫だったけど
アレでサポートしてるというのか?
VC11でも限定的サポートだし、この先どうなるんだか。
98(03)からVC2005まで何年掛かったかを考えれば解るだろ
今はC++の規格ってどういう動機で決まってるの? C++の始まりはストラウストラップ先生の「高速で動くシミュレーション用言語が欲しい」という 個人的動機だったと理解しているが
>>906 使って出てきた問題が修正されたり、あったらいいよねって機能が追加されたり、
多くの環境で必要とされる独自拡張が標準化されたり、広く使われるライブラリが標準化されたり。
>>906 Boostはレビューしてもらって多数決で採用が決まる。
レビューで、色々文句も出るので改善しないと採用してくれない。
>>896 ラムダは関数の引数に渡すとき以外は
普通はautoで受けるぜ
初心者なんだが、 結局C++で具体的に何が出来るのか教えてくれ。 他のところだと「何でも」しか来なくて具体的な例が知りたい。
>>910 動作させる環境においてプログラムに許されていることなら何でも出来るよ
参照渡し
C++から色んなライブラリを扱うことによって何でもできる C++だけではGUIアプリは作れん CUIだけ
914 :
デフォルトの名無しさん :2012/04/30(月) 15:13:39.74
>>910 お前Javaスレにも殆ど同じレスしてたろ
916 :
デフォルトの名無しさん :2012/04/30(月) 15:15:37.39
>>915 よくわかったなw
今プログラミングの勉強してていろんなところで聞いてるw
ジェネリックプログラミング、 まあ比較的簡単な奴ならJavaやC#でもできるが C++ほど融通が利かない上に実行速度が1/3ぐらいに低くなる
>>910 PS3とかの3Dを駆使したゲームも作れるし、
OSも作れるし、
組み込み機器のソフトも作れるし、
ネットワーク関連のソフトも作れるし、
スマートフォンのアプリも作れる。
だから誰に聞いても何でも出来るとしか答えがこない。
当然他の言語の方が楽に作れる分野は一杯あるけどな。
C++で出来ないわけじゃない。
919 :
デフォルトの名無しさん :2012/04/30(月) 16:19:56.28
>>918 おぉ!
ありがたい!
だから皆そう言うのかぁ〜
d(゚Д゚ )☆スペシャルサンクス☆( ゚Д゚)b
俺は趣味グラマーだけど おまえらは仕事でC++(Cじゃなく)をメインに使っているのか?
C++メインだよ でも同僚はみんなろくにC++を知らない
C++メインの部署で禄にC++知らないのがほとんどって><
基本Cでちょっと便利そうな昨日をつまんで使うタイプ
そんなつもりで使っててもmangling やstatic やadl が避けようも無く暴れ始めるのがC++の凄いところ。
確かにKoenig lookupは気色悪い でもあれがなければ<<とか>>のオーバーロードが自然に記述出来なかったわけだ
>>925 演算子なんか全部グローバル名前空間に宣言することにすればよかったんじゃ?
えっstdを使わないの?ぶつかって仕方ないんじゃね
同じ引数型で同じ演算子なら意味付けはひとつにして欲しい。
何を言ってるの?
ADLで何で困るのか解らん。 using namespace使いまくるとかバカな事してんのか? using宣言かnamespaceの別名使うくせをつけろよ
using namespaceは使わないな std:: とか boost:: と打つのが快感
namespace hf = hoge::fuga; とかはよくやる
自分のクラスを、継承した別のものにキャストすることは出来ますか?
出直して来い
>>934 出直してきました
thisに新しいのを代入してしまえばいいですかね?
親クラスのthisを、派生クラスのthisにキャストできるかと聞きたかったのか?
>>936 違います。
親クラスの中で、自分自身を派生クラスに置き換えたいんです。
>>933 できるっていやーできるが、茨の道だしEffective C++にもいろいろ書いてあった気がするが良い?
a. クラスbaseからその派生クラスderivedへのキャスト
それを行うコピーコンストラクタをderivedに定義すればできる
ただし、explicitを忘れると、暗黙の型変換でbase→derivedが行われて死ぬ
b. クラスbaseのポインタ(or 参照)からその派生クラスderivedへのポインタ(or 参照)へのキャスト
キャストで一応はできる
(1) 速いが自己責任なやり方
base* p = new derived;
derived* q = reinterpret_cast<derived*>(&p);
これは、qを使ってbaseにないフィールドに「ついうっかり」アクセスすると死ぬ
(2) 遅いが多少安全なやり方 -- dynamic_castを使う。
baseに仮想関数が1つ以上無いとコンパイルエラー。
また、正確にderived*かderived&へのキャストでないと例外が発生する
void Base::Function() { dynamic_cast<Delived>(this)->DelivedFunction(); // 派生class上の関数呼び出し } これがしたかった訳じゃないのか
>>935 コンストラクタ以外ではthisへの代入はできない(コンパイルエラー)
コンストラクタでのthisへの代入は、昔の規格だとコンストラクタがメモリ確保する、の意味に取られるんだったと思う
(今の規格でどうなってるかは知らん)
>938のb.あたりでどう?
>>938 (1) 速いが自己責任なやり方
多重継承してても死ぬぞ
(2) 遅いが多少安全なやり方 -- dynamic_castを使う。 コンパイラーによっちゃインライン展開によって動的処理が消える reinterpret_cast使っても多重継承でアウトになるし、こっちだけにしとけ
ダイナミックキャストをしても安全なのはそのオブジェクトが真に派生クラスであった場合だけじゃなかったっけ?・3・; ダイナミックジャスコしたところでそれは変換前と変換後のクラスが派生関係にあるかどうかを調べるだけで(なければヌル)。
何を危惧しとんのかしらんが、そらそうよ
自己言及にすれば?
>>938 > base* p = new derived;
> derived* q = reinterpret_cast<derived*>(&p);
> これは、qを使ってbaseにないフィールドに「ついうっかり」アクセスすると死ぬ
static_cast にしとけば多重継承してても大丈夫だし生成してるのが
derived なら q を derived として扱って何の問題も無い。
>>946 static_castの存在を忘れてたスマンス;
あと「qを使ってbaseにないフィールドに「ついうっかり」アクセスすると死ぬ」は確かに間違いで、
「pが指す先が本当はderivedでなかったら死ぬ」に訂正
&p もダメだな。だから static_cast にしとけと。
モノステートクラスとシングルトンクラスの使い分けってどうしたらいいんだ? いまいち相違点というかメリット/デメリットが見えてこない。 互いに、アプリレベルでひとつしか実体を持たないし、 初期化するタイミングをユーザーが選択できる。 ポリモーフィズムできるか出来ないかぐらいか?
モノステートはインスタンスは幾つでも作れるが、状態が一個しか無い シングルトンはインスタンスが1つだけ作れる モノステートは1つしか実態を持たないわけじゃなくて、状態が1つしかないだけ Construct(メモリ確保と初期化)、Destruct(後処理とメモリ開放)を考えるなら staticなクラスフィールドに実体が存在し続けるモノステートよりシングルトンの方が優秀 だと個人的に思ってる
モノステートは、C++独自のメリットとして、 デストラクターとテンプレートの親和性が有る。 まず、デストラクターだが、モノステートが抱きかかえてる オブジェクトが死ぬタイミングではなく、モノステートのオブジェクトが 死んだ時点で呼ばせる事が出来る。例えば、関数の呼び出しと 脱出のログをとる場合、関数に1個モノステートのオブジェクトを置いて おけばいい。他にもデストラクターを使った排他制御にも使える。 次にテンプレートだが、もともとシングルトンを想定してないテンプレートで コンストラクターを呼び出す仕様になってる場合、シングルトンは使えない。 見た目が他のクラスと変わらないモノステートであれば、問題なく使用できる。 基本的に、アドレスが同一である事を求める場合ぐらいしかシングルトンのメリットはない。 FlyWeightでもモノステートで実装できるし、static変数の初期化を利用した 根底クラスの拡張もモノステートでできる。 よほどの事情がなけりゃモノステートにしとけばいいだろ。
>>951 >モノステートのオブジェクトが
>死んだ時点
モノステートなクラスって、
・それ自体のオブジェクト(インスタンス)は生成されない(コンストラクタ系が全部privateなのでできない)
・抱えてるオブジェクトは(あるとしても)全部static
だから、
死んだ時点=抱えてるオブジェクトのデストラクタが呼ばれた時点=プログラム終了後の後処理タイミング、
なんじゃ…?
モノステートの定義によるのかもしれんが、↓ここ式の定義を採用するとして、
http://www.geocities.co.jp/bleis_tift/cpp/singleton.html シングルトンにできてモノステートにできないこととして、抱えているオブジェクトの遅延生成が挙げられる
抱えているオブジェクトが複数あって、相互に依存性があり、
かつ本体のリンケージ単位が分かれていて初期化順序不定、と言う場合
シングルトン1択(コンストラクタできちんと生成順序を指定して遅延生成する)になる
ただ、個人的にはシングルトンオブジェクトの汎用性(第三者が後にいつ生成する使い方をするかわからない)
を考えると、マルチスレッド状況下での生成も考慮せねばならず、するとメモリバリア関連の検証が必要になり、面倒なのでシングルトン嫌いだが
(そう言った事柄をプログラマが完璧に管理できる状況下なら生成タイミングと回数が管理できるということで、シングルトンでなくても良い。)
955 :
953 :2012/05/03(木) 00:37:43.14
>>954 了解;
そして>953の前段は撤回スマンス;
>953式の(誤った)モノステートが抱えているオブジェクトの初期化順序は、多分宣言した順に行われると思うし
そんな規格の微妙な条項に頼らずに初期化順序を保証したければ、
遅延生成専門のクラスFooを設けてFooのコンストラクタ中で遅延生成することにして、
Fooのオブジェクトをstaticにすれば全く安全に解決できるorz
(むしろ>953式の(誤った)モノステートが抱えるオブジェクトと外のオブジェクトとの初期化順序を気にしたが、
それも上のようにFooを噛ます方法方法で解決できる。)
>>953 そのサイトいつまで嘘を吹聴し続ける気なんだろうな
>>949 だが、
>>950-956 モノステートとシングルトンのくっきりした違いが分ったよ。
(というか
>>953 のサイトを質問前に読んでいて、混乱したクチだった)
ありがとう。もう陽も昇る頃だが、よく眠れそうだ。
今まで#define HOGE nantoka を使ってきましたがEffectiveC++曰くconst type HOGE = nantoka;を使えトのことだったので 使ってみましたが、これがヘッダファイル内だと複数のcppにincludeされて多重定義エラー externで回避できますがconst外さないと駄目ですが、そういうものですか?const外れるのが気持ち悪いのですが
すいませn extern const ができました
いやインクルードガードとは話が違う
>>958 typeが整数型なら、多重定義のエラーにならない。constの特例。
それでエラーになるなら、実はCとしてコンパイルしているのでは?
>>962 >多重定義のエラーにならない。
えっにわかには信じ難い
VS2008で「const int x = 10;」を同じcppファイル内で2回以上書くと
「error C2370: 'x' : 再定義 ; 異なるストレージ クラスです。」と言われる
>960ではないが、とりあえずは重複インクルードをガードすれば解決するんでないの
がまん大会開始
965 :
958 :2012/05/03(木) 21:00:16.38
同じcppファイル内での話ではなく違う翻訳単位の話です 問題は文字列char*でした const intは通りました。不思議
const char* const HOGE = nantoka; ってやらないと
>>965 クラス内で
class Hoge{
statyic const char* hoge = "hogehoge";
};
ってやってるんじゃないの? もっと詳細に情報書け
そもそもコード中に"hoge"とか書いた時点でそれ定数なんだから云々とかは言っちゃいけないゲームなんです?
>>966 おうふ、それで通りました
いろいろ納得
>>967 いや>965で意味が通ってるし、>966は正しい
>962の「typeが整数型なら」というのは意味不明
(クラス内のstatic const int x = 10;は確かにintでだけ可能という特例があるが)
みんな我慢大会好きだな
972 :
962 :2012/05/04(金) 23:18:35.03
すまん、ぼけていた。 整数型に限らず、constなやつはextern付けない限りみな内部リンケージだったな。
>>966 毎度だがマクロでないものを全て大文字で書くな
SLTやBoostを使ったプロジェクトに関して質問です。 メインプログラムを自分、サブプログラム(.libや.dll)を他の人が作る場合、 相互での関数呼び出しの引数にstringやvector<>を使いたい場合は、ライブラリのバージョン合わせればOKですか? コンパイラのバージョンはもちろん固定で。 (受け渡しはTCHAR使えば安全、というのは分かりますが、毎度変換しててはstring使う意味が薄れてしまう)
978 :
976 :2012/05/07(月) 18:51:27.81
>>977 あ、TCHARだと環境がUNICODEかどうかでchar/wcharになっちゃいますね。
そこはスルーでお願いします。
>毎度変換 えっ?
dllとの境界はC互換にした方がいいと思うが・・・
えっ?
質問の意図や前提をくみ取れない糞質問 が多い。それで回答者が逆質問をしたり 悪口を言ったりする。それを前もって思 い描く力が絶望的に欠如してるに違いない。 スーパーハッカーだけが意図を理解できる。 レアなそういう神が颯爽と登場する予感。
えっ?
意味不明な質問するやつは出直してこいよ 以降スルーで
ポイントカードはお餅でしょうか
読み取れない方の日本語能力に問題があるだろ
>>976 LIBは問題ないだろうが、DLLは地雷を踏んでも泣かない覚悟があるならどうぞ
しかし皆分かっててやってるという
地雷って単語使うやつってオヤジだよね
最近のトレンドは機雷だよな
ジライヤ いやそんなことより次スレ誰か
ファイティングニンジャw
うめ
次スレ建つまで待ってろバカ
(#゚Д゚) さっさと立てろ ゴルァ!!
(・3・)ノおつ!
(#゚Д゚) お疲れ様です ゴルァ!!