つまるところc++ではデストラクタに頼るべき。
C++はつまるところデストラクタのことだからな closeさせといてガベージコレクタがあるとか抜かす言語は笑えるな intは回収できるが巨大なファイルリソースはリークするわけだ
日本語でおk
>closeさせといてガベージコレクタがあるとか 禿げあがる程同意。 C#はusing(o1,o2,...){}があるから多少マシだけど、 forみたいにusing用のスコープ作るから スコープ違いが混じるとネストして見辛くなる。 どう考えてもc++みたいに対象の変数のスコープでDisposeした方が良いと思う。 javaのtry-finally-closeに至っては論外。 しかもcloseで例外出たらfinally内で潰さないと try内で発生したより重要な例外が消されるし・・・。
>どう考えてもc++みたいに対象の変数のスコープでDisposeした方が良いと思う。 そして言語はC++/CLIへと進化するのであった、まる
using Hoge hoge = new Hoge(); とか Hoge hoge(); とかと書かせるようにすれば良かったのにね。C# も。
502 :
デフォルトの名無しさん :2008/02/15(金) 21:28:46
>>469 比較関数が例外を投げないんだったら、比較の順序ごとに
std::set<Base *, Compare>を用意して挿入関数を注意深く書けばいい。
multisetにすると削除のとき最悪O(N)の時間がかかるから、
比較関数にポインタの比較を入れてsetで扱う。
比較関数が例外を投げる場合、同じ方法だと削除関数が
例外を投げることになって相当扱いにくくなる。
OpenBSDのtree.hみたいのを使って侵入型コンテナにするのが現実解かな。
無名名前空間ってちゃんと働く? vc8で // hoge.hpp namespace { class A { public: A() {} }; } // main.cpp #include "hoge.hpp" int main() { A a; } でmain.cppからAにアクセスできてしまうけど。 なんか理解がおかしい?
インクルードしたらアクセスできて当然だろう・・・
無名名前空間ないのクラスは同一ファイルのものからじゃないとアクセス できないってみたけど。 というかmain自体が無名名前空間で定義さてれいてAが見えるってことか?
>>505 同一ファイルじゃなくて同一コンパイル単位
インクルードしてたら同じコンパイル単位に含まれるよ
#includeの行を消して、 代わりに.hppの中身全体をその場所にコピペしてみろ。 #includeとはそういうことだろ?
>>509 要はstatic変数の代用だ
Cではグローバル変数が他のコンパイル単位とぶつからないようにstatic変数ってものがあったが、
static構造体とかstatic typedefといったものはなかった
C++では無名名前空間がそういった役割を果たす
もちろん従来のstatic変数も残ってはいるが
>>509 不正確な記事だな。著者に連絡しとくといいよ。
>>511 コンパイラはプリプロセッサの処理の後に動くから、
そういう風に考えれば同一ファイルのみと考えていいんじゃね
>>509 a.cppとb.cppがそれぞれコンパイル単位内で使うために
class Foo {
void f();
};
void Foo::f() { ... }
のように定義すると、リンクのときにFoo:f()が衝突してしまう。
typedefや構造体の定義そのものはコンパイル単位内で完結しているから、
Cの場合は関数、変数にstaticを付けるだけで衝突を防げたけど、
C++の場合普通の関数、変数の他にクラスのメンバ関数やstaticメンバ変数があるから、
それらがリンク時に衝突しないように無名名前空間が考案された。
「MOJO」ってのはただ単に一時オブジェクトを移動させるためのもので、 「swapで交換」とはまた別? ぁー理解できんorz
C/C++でプリプロセッサ命令以外でファイル単位と言ったら、 それはつまりコンパイル単位のこと。 プリプロセスとコンパイルは分けて考えないと駄目だよ。 複数のファイルを扱うのはプリプロセスとリンク。 コンパイルは(結合、加工後の)単一ファイルしか扱わない。
>>514 move semanticsの汎用的な実装方法のとして
「デフォルトコンストラクト直後のオブジェクトとswap」がある。
でもauto_ptrみたいにswapでなく、メンバをNULLにするような方法もある。
MOJOはswapで移動させるとか限らない。
・・・って感じじゃない?。俺もMOJO詳しくないけどw
× とか限らない ○ とは限らない
>>512 ,515
そんなんだから >505 みたいな勘違いするんだよ。
入門用の記事なんだから、読み手がコンパイルとプリプロセスを
分けて考えてるとも期待できないだろうし。
>>519 だから何?「ファイル」と不正確な記述にしておいたほうがいい理由でもあるの?
521 :
デフォルトの名無しさん :2008/02/16(土) 10:47:33
>>520 コンパイル単位という専門用語はあまり知られていない。
Cを知っている人の間ではファイルと呼んだ方が通りがいい。
あと、日本語では「〜単位で」が「〜ごとに」という
意味になる場合があって、
「しておいたほうがいい理由」は無い。 しかし、C言語経験者を想定してるなら 「不正確だから修正が必要」という程のことでも無いと俺は思った。 その記事はstaticとexternを引き合いに出してるし、 それらは(特にC言語で)ファイルスコープと呼ばれる上に、 モロ翻訳単位のことだから。
523 :
522 :2008/02/16(土) 10:52:15
だれも修正が必要なんて言ってないんだよ。
C/C++にはコンパイル単位って用語がある。 あまり知られてないとか、ファイルの方が通りがいいとかどうでもいい。 それ以上は自分のブログででも主張したらいい。
そうだね
「連絡しとくといいとは言ったが、修正が必要とは言ってない」 っていう、二次成長期の真ん中へんに居る子みたいな言い逃れが来ると思うよ。
>>525 ブログも2chのレスも大して変わらんよ。
「著者に連絡しとくといい」なんてレスに比べれば
個人的な主張なんてかわいいもんだろ。
というか、「どうでもいい」なんて反論?は止めた方がいいかと。
>>521 専門用語ではあってもstandardで使われているので
重要だと思う。
おれも100%知ってるわけではないけど。
翻訳単位というのはstandardに従えば必ずしも
ファイルである必要はない。たまたま現存する実装ではそうな
っているものがほとんどであるということに過ぎない。
別にヘッダをローカルファイルではなく、データベース、ネットワーク
経由で何らかのconfigurationで展開してもstandard準拠といえる。
上にも書いてる人がいるけど翻訳単位とはプリプロセス
(マクロ、ヘッダの展開etc)終了後のエンティティを指す。
リンケージの話は翻訳単位に対して行うものだと思っている。
実際このくらいは知ってないと理解が難しくなる本もある。
カーニハンやジョスティスの本にも頻繁に出てくる。
著者本人以外が「修正の必要はない」と繰り返し主張する意味がわからない。 もしかして本人なのかもしれないけど。
>>509 が明らかに勉強不足で理解不足だからだろ。
著者のせいにしたければ勝手に連絡すればいい。
別に止めんよ。
それはつまり、他人の「問題」を2chに書き込むのはおかしくないけど、 「問題の無さ」を2chに書き込むのはおかしい、ということ? 俺にはその感性のほうが意味わからないかも。 Xへの突っ込みが変なせいで、X以外の人間に突っ込まれるなんて、よくあることじゃん。 あと、「繰り返し」っていうのは多分、さりげなく「必死だな」って言いたくて書いてるんだと思うけど、 これは単に、「修正が必要だ」っていう意見の子がまず「繰り返し」書き込んでいるから、 それへの反応も複数回になって「繰り返し」になっているだけだろう。
>>532 「不正確」に対する反論がそんなに不思議?
こちらは一応根拠を示しているつもりなんだが、
それに対し、根拠も書かずに件の説明が間違っている前提なのが、
むしろ俺は不思議に思うんだけど・・・。
件の入門記事にある不正確な記述を読んで誤解した人が少なくとも 一人いたのは事実。それを著者が知れば、修正するかもしれないし >512,533 のように判断して修正しないかもしれない。それは著者の自由。 修正が必要だという主張も不要だという主張も同じぐらいに的はずれ。
>>533 509が見るサイトを間違えてる気はするよな。
普通のc++入門サイトとか見た方が良いだろうから。
ところで、ヘッダファイルのみで通じる宣言ってやりたいよなあ。
>>536 上から目線を楽しみたいのはわかったけど、ちょっと変。
「修正が必要だという主張も不要だという主張も同じぐらいに的はずれ」という箇所から察するに、
この件についてどっちでもない立場がある、という前提で言ってるんだよね?
なのに、「修正が必要だという強弁に反論した」だけで、それを「不要だという意見」に括るのはおかしいよ。
右翼の意見に反論したら即左翼かよ、みたいな。
>>535 不正確だというのに反論するなら、件の記事の「ファイル」という記述が正確だ
ということになるが、そうじゃないだろ?
ファイルと翻訳単位では確実に意味が違う。
>>540 今までの、その「不正確」への反論は全部スルーなのは何故?
>>540 で、連絡したの?
別に、連絡することは絶対に許さんぞとか、俺はスーパーハカーだから
もし連絡したらお前を社会的に抹殺してやるぞとか、そーゆーこと言ってるわけじゃないんだから
さっさとすればいいのに。
>>539 どっちでもない立場である「著者に連絡しとくといい」を、
「修正が必要だという強弁」に誤読して反論してた人が
「修正が不要だという意見」を持っていた、というお話。
「ファイルスコープ」 という言葉にも文句を言って欲しい物だな。
>>543 ああなんだ、「お話」の内容を語っていたのか。
やけに現実と異なると思った。
>>541 >525 や >531 は読んでないのか?
2 Lexical conventions p1 The text of the program is kept in units called source files in this International Standard. A source file together with all the headers and source files included via the preprocessing directive #include, less any source lines skipped by any of the conditional inclusion preprocessing directives, is called a translation unit. 翻訳単位はソースファイルであると規格に書かれている。 そして、「ソースファイル」 はまとまったプログラムのテキストであると定義されているだけで、 別に OS のファイルの定義と等しくある必要は無い。
> 翻訳単位はソースファイルであると規格に書かれている。 不正確w
この国際標準規格においては、 ある単位でまとまったプログラムのテキストのことを「ソースファイル」と呼ぶ。 #include 指令によりインクルードされる全てのヘッダとソースファイルと一緒になったソースファイルのことを「翻訳単位」と呼ぶ。 ただし、プリプロセッサ指令により除外される行は除外する。
↓こんな感じかなぁ。 プログラムのテキストはこの国際規格で「ソースファイル」と呼ばれる単位に保持される。 ひとつのソースファイルと #include を通して取り込まれるヘッダやソースファイルを すべて併せ、 #if などでスキップされる行を減じて、「翻訳単位」と呼ぶ。 JIS の訳はどうなってんだろ?
551 :
550 :2008/02/16(土) 13:01:18
うは。被った。
言葉は悪くない。
悪いのは
>>503 を生み出したゆとり教育。
金毘羅様を疑う前にまず自分を疑え。
比較検討しろ。試行錯誤しろ。すぐ2ちゃんに泣きつくな。
規格の話にまで行っちゃったなw有りだけど、入門サイトの話題だぜw 俺としては、 ・c言語経験者前提 ・ファイルスコープという言葉は一般に使われている から、件の文脈でファイル==翻訳単位と分かる。 503、509はサイトの前提には満たなかっただけ。 つまりサイトの選択ミス。 ・c++入門者用のサイト から、厳密性より分かりやすさ優先することは妥当。 と考える。 大体、cユーザーがFILEと言いつつストリームだったりするのはザラ。 翻訳単位はコンパイラにとってストリーム。
一体どう読めば翻訳単位=ソースファイルになるんだ・・ 不思議だな
翻訳単位=加工されたソースファイル
556 :
553 :2008/02/16(土) 13:28:19
補足。 俺は503が悪いとは思ってない。 学習には積み重ね、つまり順序が必要。 2chにレスして、足りない知識に指摘されたなら、その基礎を学べば良いだけ。 まぁ、試行錯誤が重要なのも間違い無いけどね。
「ファイルスコープ」は C の規格で翻訳単位全体にわたるスコープとして使われてたけど、 C++ の規格では使われなくなってるみたい。やっぱり誤解する人がいたからなんだろうね。
558 :
469 :2008/02/16(土) 13:53:47
>>502 thx
比較関数にポインタの比較を含める手法があるんですね。参考になります。
いくつかのコンテナを同期させる手間がかかってしまうのは仕方ないですか。
おはなしにならない
規格の話するのに規格以外のリファレンス持ってくるとかあり得ない
ですよね〜w マイクロソフトとBoostも、 ファイルスコープなんて単語使ってもらっちゃ困りますよねw
CFactoryTemplate g_Templates[]= { L"Dump", &CLSID_Dump, CDump::CreateInstance, NULL, &sudDump }; ↑これってCFactoryTemplateクラスの配列(要素は1個)を作ってL"Dump",&CLSDI_Dump,...をコンストラクタに渡しているってこと? ちなみにCFactoryTemplateはコンストラクタが定義されていないんですけど、こういうのアリなんでしたっけ? class CFactoryTemplate { public: const WCHAR * m_Name; const CLSID * m_ClsID; LPFNNewCOMObject m_lpfnNew; LPFNInitRoutine m_lpfnInit; const AMOVIESETUP_FILTER * m_pAMovieSetup_Filter; BOOL IsClassID(REFCLSID rclsid) const { return (IsEqualCLSID(*m_ClsID,rclsid)); }; CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr) const { CheckPointer(phr,NULL); return m_lpfnNew(pUnk, phr); }; };
>>564 Cの構造体や配列の初期化と一緒。
そういう初期化ができる型を集成体と言う。
>>566 そうなんだ。。いままで知らなかった。。
ありがと
>>565 おお、GJ。
>>557 が「やっぱり誤解する人がいたからなんだろうね」
って書いてたから、使わなくなった理由とかを探してた。
それ読んでやっと分かった。
誤解する人がいたから、ではなく、
namespaceが追加されたから、
名前空間スコープ、無名名前空間スコープ(グローバル名前空間)
という上位概念で置き換えたってわけか。
>>568 無名名前空間スコープとグローバル名前空間スコープとは違うスコープだぞ、いちおう。
規格厨消えた?
この場合、どれが規格厨?
573 :
デフォルトの名無しさん :2008/02/16(土) 21:41:48
汎整数拡張の勉強をしていて、intとunsigned intはどうなるのだろうと思い実行してみたところ、 intは予想通りの動作をしたんですがunsigned intがよく分からない動作をします。 unsigned int i = 0; unsigned int j = 0xFFFFFFFF; unsigned int k = 0xFFFFFFFE; unsigned int l = 0xFFFFFFFF; i += 0xFFFFFFFF; printf("i=%d, j=%d, k=%d, l=%d\n", i, j, ++k, +l); これが全部-1になってしまいます。 汎整数拡張とは違うと思うのですが、理由が分かりません。 どうしてこうなるのですか?
>>573 "%d"してるからだろ常考。%uとかprintfの書式調べろ。
あと0xFFFFFFFFというバイトパターンは符号付整数型だと-1を表すからだろ。
575 :
573 :2008/02/16(土) 22:21:54
ありがとうございます! %dは符号付表現だったのですね。勉強になりました。
576 :
デフォルトの名無しさん :2008/02/18(月) 03:45:36
class の変数部分だけを extern C してstruct扱いにしてcから(c++でなくて)参照できますか?
仮想関数テーブルがなければ大丈夫かもしれないが どちらにしろカプセル化を壊すからやるべきでないことだけは確かだ。 アドレスだけ受け取って、 そのアドレスを渡して処理するヘルパ関数を使うとか。
578 :
デフォルトの名無しさん :2008/02/18(月) 11:18:27
>>577 メンバ関数を呼ぶときにthisを積むことができない時点で無理。
>>578 メンバ変数をアクセスしようってのに、メンバ関数を呼べないから
ダメというのは漏れにはちょっと途中のロジックがわからない・・・
580 :
576 :2008/02/18(月) 12:47:08
python.ctypesがstructにはアクセスできるけどclassが無理みたいなので 既存のc++コードのclassにpython.ctypesからアクセスするにはどうするか 知りたかったのです。結構難しいみたいですね。 class hoge { public: char *data int size }; のdataとsizeにextern Cからアクセスしたかったのです
C++初心者です。 C++ではクラスと構造体にはデフォルトのアクセス指定が違う以外に差異は無い、と入門書で読んだのですが、ということはC++では構造体は使わないで良いということでしょうか。
そうでもない。 typedef struct cordinate{ double x,y,z; }CORDINATE; こんなのは構造体で使う。
public: と書くのも面倒だったらstruct使う。その程度。
どちらも仮想関数テーブルを持った構造体になりうる
>>576 C互換の構造体を基本クラスにすれば?
ATL/MFCのCRectとかはそうやってる。
struct C_Struct { };
class CPP_Class : public C_Struct { };
588 :
デフォルトの名無しさん :2008/02/18(月) 18:12:59
>>580 data, sizeというメンバがpublicになっている時点で、
hogeは実質ただの構造体なのでは?
コンストラクタやデストラクタを自分で特に定義していなくて、
メンバ関数もカプセル化じゃなくコードの再利用だけを目的にしているような。
だとすれば、メモリ上ではCの構造体と同じだから直接python.ctypesに渡せばOK。
ちなみに仮想関数を持っている場合はダメ。
>>586 の方法なら一応動くけど設計を見直した方がいい。
>>587 // C
struct C_Struct { };
void c_func(C_Struct*);
// C++
class CPP_Class : public C_Struct { };
CPP_Class hoge;
c_func(&hoge);
>>576 がどういう使い方するのか知らんが、C互換の部分だけ見せる事はできるぞ。
public 継承は怖いなあ。 そんなことしなくても不完全型使えばいいんじゃね。
591 :
デフォルトの名無しさん :2008/02/19(火) 00:00:40
Modern C++ Designを読破した人でお分かりになる人 がいたら教えてください。 『第4章 小規模オブジェクトの割り当て』 のP88にチャンクのブロック数をunsigned charに収まる値に 制限した理由について、もしこれをunsigned shortにした 場合、sizeof(unsigned short)よりも小さなサイズのブロック を割り当てることができなくなることが書かれていますが、 何故だか分かりません。ブロックサイズとブロック数は独立 に管理してるものなのでブロックサイズは1バイトだろうが何バイト だろうが任意に指定できるはずです。
その本は読んだことないけどエスパー回答してみる フリーブロックの管理が連結リスト方式だとすると、あるブロックが解放されたとき、そこに次の空きブロックの位置を書き込まなければならない 総ブロック数がunsigned charの最大値以下なら、空きブロックの位置を保持するのに1バイトで足りるが、 総ブロック数がそれより多いなら、空きブロックの位置を保持するにはもっと領域が必要だ 解放されたブロックのサイズが1バイトでは、そこに次の空きブロックの位置を書き込むことはできない
struct A { template<class T> struct tmp{ T *pt; tmp( T *p ){ pt = p; } }; operator struct tmp(){ return tmp<struct A>( this ); }; A( tmp<struct A> &tmp ){ ... }; }; 上の方でもでてたけど、こういうコードって何の意味があるの?
594 :
デフォルトの名無しさん :2008/02/19(火) 01:06:43
>>592 すごいです。クリアになりました。
確かに未使用ブロックの先頭には次の利用
可能なブロックのインデックスを書き込みます。このインデックスのサイズが
もし2バイト(unsigned short型)なら、ブロックサイズを最低でも2バイト確
保しなければインデックス自体を書き込めないことになりますね。
>593 >489 に //非const参照で一時オブジェクトを受け取る対応。 って書いてあるやん。 俺の理解によると、その意味で A( tmp<struct A> "&" tmp) にしちゃ駄目ぽ。 通常の非 const 参照は一時オブジェクトを受け取れないので代わりに参照の働きをする tmp_ref を自前で導入してる。 tmp_ref<A> は A& を表していて、tmp_ref<A> への変換演算子が A → A& (ただし A が一時オブジェクトでも OK)の変換に相当してると思えば OK?
場違いだったらすまん、 if文で、if (音を感知したら) do ○○ っていうプログラムを考えているんだけど その音を感知する部分で何か有効的な物ある?
struct foo{ struct foge{}; }; struct bar : foo{ struct foge{}; }; で、barの型からfogeと言う名のstructを導出する時、fooのものを選ぶかbarのものを選ぶかってどうやるんですか?
お願いだからコンパイルの通るコードを書いてくれ
通るけど?
foge ← bar のやつ foo::foge ← foo のやつ
基底クラスに宣言した型を返すタイプの演算子オーバーロードって継承先では使用できないのでしょうか? // ■ペースクラス template <typename T> class BASECLASS { protected: unsigned long val; public: BASECLASS() { val = 0; }; ~BASECLASS() {}; // 継承する型によって変化させたい T& operator =(unsigned long val32) { val = val32; return *this; } operator unsigned long() { return val; } };
>>602 続き
// ■クラスA
class ChogeA : public BASECLASS<ChogeA>
{
};
// ■クラスB
class ChogeB : public BASECLASS<ChogeB>
{
};
// ■メイン
void main()
{
ChogeA hoge1;
ChogeB hoge2;
unsigned long tmp;
tmp = hoge1; // ○コレは動く
hoge1 = hoge2 = 10; // ×コンパイルエラーの位置
}
エラーメッセージ:'Choge::operator = (unsigned long)'に一致するものが見つからない
うまいこと引き継がれていないみたいで・・・
代入演算子は継承されないとオモタ
operator =は自動的に基底クラスのものを参照するようにならないメンバの一種。 規格では、派生クラスのデフォルトので上書きされるためと説明されていたはず。 派生クラスでいちいち定義すればいいのだけど、面倒と言われればそれまで。 class ChogeA : public BASECLASS<ChogeA> { public: ChogeA& operator =(unsigned long val32) { return BASECLASS<ChogeA>::operator =(val32); } };
派生クラスで using BASECLASS<ChogeA>::operator =; って宣言すればおk あと return *this; の部分はダウンキャストが必要な気がする
607 :
デフォルトの名無しさん :2008/02/19(火) 17:23:22
>>603 今の場合、コンパイラが暗黙に定義するコピー代入演算子が
派生クラスには存在している。基底クラスとはスコープが
異なるためオーバーロードにはならず、以下のものしか
候補にならないた一致するoperator=が無いと怒られる。
ChogeA& operator=(const ChogeA&);
ちなみに危険ではあるが
T& operator =(unsigned long val32) {
val = val32;
return *static_cast<T*>(this);
}
}
};
class ChogeA : public BASECLASS<ChogeA>
{
public:
using BASECLASS<ChogeA>::operator=;
};
// ■クラスB
class ChogeB : public BASECLASS<ChogeB>
{
public:
using BASECLASS<ChogeB>::operator=;
};
として可視にすればオーバーロードのセットに入るので
これでも動くかと。
608 :
602 :2008/02/19(火) 20:01:13
>>602 継承される可能性のあるクラスはコピーコンストラクタやoperator=をprivateにするのが原則。
class Base {
public:
Base &operator=(const Base &);
};
class Derived {
public:
Derived &operator=(const Derived &);
};
void foo(Base *p, const Base *q)
{ *p = *q; }
void bar() {
Base b;
Derived d;
foo(&d, &b); // 何が起こるだろう?
}
>>609 privateにしてしまうと、派生クラスのオブジェクトの正しいコピーと代入
が行えない。(Effective C++ Item12)
せめてprotectedにすべきではないか。
>>608 最後にキャストしてるから特に危険ではなかったか。
ただ、クラスのデザインとしては。。
やはり、
>>605 のように基底クラス部分の代入は
基底クラスの代入演算子に行わせて、派生クラス部分
は派生クラスの代入演算子に行わせるのが正等かつ
可読性が良いと個人的には思う。
>>610 のメイヤーズのとおり。
>>610 ポリモーフィズムを前提にするようなクラスに対して、
コピーはまだしも代入をまっとうに定義できるケースは珍しいだろ。
継承されないクラスでもコピーや代入は出来なくて当たり前。
コピーだけが意味を持つ場合はこうする。
class Base {
protected:
Base(const Base &);
private:
Base &operator=(const Base &);
public:
virtual std::auto_ptr<Base> clone() const
{ return std::auto_ptr<Base>(new Base(*this)); }
};
>>612 漏れは「継承される可能性のある」と、「ポリモーフィズムを前提にする」は
結構違うと思う。違わないようにするべきだという立場もわかるけど。
>>612 継承される可能性のあるケースとは継承されないケース
もあるわけで、盲目的にコピー、代入を禁止するのは
柔軟性を損ねる。cloneによる深いコピーにしても
実行コストを考えると使いたくないケースは
特に組み込みではよくある。残念ながらnewは小さい
オブジェクト用のアロケータではない。
クラスの使用方法を明確に規定するのが前提だが
そうでないケースでは様々な拡張に応じられるように
しておくべきだと思う。
>>613 std::unary_functionみたいのを除けば
デストラクタがvirtualかどうかではっきり決まると思うけど。
>>614 どういうクラスを想定してるの?
子クラスのインスタンスに親クラスのインスタンスを代入した場合の動作なんて、
いちいち決めても不毛なだけだと思うけどなあ、普通は。
元のインスタンスの決まった属性だけ読み出すという処理なら割と自然だと思うけど。
class Base {
public:
explicit Base(const Base *);
void assign_basic_attributes(const Base *);
};
class Derived {
public:
explicit Derived(const Derived *);
void assign_all_attributes(const Derived *);
};
>継承される可能性のあるクラスはコピーコンストラクタやoperator=をprivate>にするのが原則。 流れからして、このレスが明後日のほうへ行ってしまってると感じた。
だからsealedを導入しろって兄ちゃんがあれほど
C++プログラマのオマエらからしてC#はどうなの?
>>618 Javaじゃん。
つーか、仮想マシンが必要な言語と比較対照にはならんでしょ。
むしろライバルはD
.NETがLinuxに移植されたらC#もありかなと思って。
つMONO
Dいいね
C#は大人しくJavaと闘ってなさい。C++とはどちらも無縁です。 Dもまた同じく。必要のある所ではC++もDもC#/Javaも必要なのは変わりないのです。
Dが必要な場所が思いつきませんw
もうOOPも手続き型も飽きたな。 関数型言語を使う仕事がしたい。
OCamlとF#の出番だな。
民間企業は面白くない。 研究室とかに篭ってシコシコ勉強がしたい。
C#やったあとにJavaをやったら、C#が後発と言うだけあってC#が素晴らしく見えた。
>>618 LINQはSTL並に面白そうだと思っているんだけど、遊んでいる暇がない。
俺の仕事で、関数型言語を覚えてまで使う理由が見当たらない。 こうぶんきなんて解析せんし、無限計算もやらん。遅延評価も 価値を持ちそうにない。なんではやってるんだ。 Dのがいい。
>>630 コンパイラはLispとかで書かれてることもあるんじゃね?
>>630 自分の知らない計算パラダイムを知ることによって世界が広がるぞ、マジで
あんたの言ってることは「2次方程式なんて実生活で使わないから
学校で勉強する意味がわからない」とかぬかすガキと似たようなもんだ
>>631 コンパイラはMLとかHaskellの方がやりやすいと思う
>>618 Windowsでしか走らない時点で興味ない。
>>633 LinuxはLispと聞いたことがある。
>>634 > Windowsでしか走らない時点で興味ない。
つMONO
>>633 実際の話、理数系が苦手だった奴って
日常会話でもアホすぎてむかつくことが多いもんなw
◯理数系が苦手だったと得意気に言う香具師
俺はそんな奴をプギャーしておこう。
○理数系が得意だったとは決して言わない香具師
>>618 昔なら「こういうのはVBで書けば5分でできるんだろうな。VBなんか使い方しらんけどpu」と
思ってたような種類のアプリをサラッと書くのに使ってる。UI 作るのが楽なので重宝してる。
おまえらの開発プラットフォームは何? 1.Windows 2.Unix系(Linux含む) 3.組み込み 4.その他 ほとんどが1,2だろうな
Unix系にはMacを含みますか?
おう、こうするよ。 1.Windows 2.Unix系(Linux含む) 3.組み込み 4.Mac 5.その他 ほとんどが1,2だろうな
組込みがターゲットの開発は、ふつうクロスだろ上皇
まあそうだけど、例えばルネサスのコンパイラとか 68kのコンパイラとかっていう程度でいいじゃん。 どっちもWindowsのツールになるが。 あまり興味ないから、質問取り消すわ。
2と3なら3が多いと思うのだが・・・どうでもないのか?
質問が二つほど。 関数宣言と関数中身は一対一とおもってたんですけど、 すでにライブラリに入っている関数中身をプロジェクト内に書くということは 問題ないのでしょうか? sprintfで書き込むのに必要な配列のサイズを知る方法ってあるのでしょうか?
C++でsprintfで書き込むのに必要なバッファの大きさを知る一般的な方法はないね。 C99だと書込先にヌルを指定すれば、戻り値でわかるようになったんだけど。 VC++の_scprintfのように独自関数を使ったり、 ヌルデバイスをfopenしてfprintfしたりという環境依存の方法か、 標準ライブラリのものを使うのを諦める。 (自分でバッファサイズが分かるものを作ったり、あるいはBoost.Formatのような既製品を使ったり)
>>649 普通はダメ。
ただし、主に移植性を重視するUNIXのプログラムで、
システムが提供するライブラリ関数と同名の関数を自分で再定義する場合はある。
例えばbasename(3)は標準化される前から多くのUNIXで提供されていて、
しかも挙動が微妙に違っていた。そこで、basenameが無かったり、
あっても標準と違っているOSではbasenameを自前で定義することがある。
そういうコードをリンクできるか、再定義した関数をリンクしたライブラリから
隠すことができるかどうかはリンカ次第。
右辺値参照が導入されたら、これまでの左辺値参照の存在意義はどうなりますか? struct X {}; X f(); X&& = f() //OK Xは右辺値参照 X obj; X&& = obj; //OK Xは左辺値参照 &&があれば、両方で使えますよね。
間違えた。 右辺値参照が導入されたら、これまでの左辺値参照の存在意義はどうなりますか? struct X {}; X f(); X&& x = f() //OK xは右辺値参照 X obj; X&& x = obj; //OK xは左辺値参照 &&があれば、両方で使えますよね。
両方で使えるのか? 区別できるからこそ(ry
RVOをさせたくない場合、どう書けばいいですか? gccが頭よすぎで、全部RVOされます
代入演算子が呼ばれたのでいいなら 初期化じゃなく代入にすればいいが、 どうしてもコピーコンストラクタが呼ばれて欲しいとなると、 一旦一時変数を作ってそれで受けて、 さらにそれをコピーするしかないのかな。 ただ、RVO に依存して挙動の変わるコードは感心しないので 何らかのチェックのために行うのでなければ、そういうことはしない方がいい。
>>649 ostringstream foo;
foo << "hoge hoge pu-";
foo.str().c_str(); <- 文字列へのポインタ
>>649 >>651 <new>のoperator new, new[], delete, delete[]は自分で定義してもよい。
ユーザが定義しなければライブラリの実装が使われるって規定がある。
>>655 呼ぶ側と呼ばれる側の翻訳単位分けてみたらどう?
RVO は翻訳単位関係ないぜよ。
処理系依存なんだし、関係無いかどうかはgccの実装次第じゃね? 翻訳単位分ければインライン化は阻害される思うし(多分)、 そしたらRVOも阻害される可能性はあるかと。 リンカが頑張ってたら駄目だろうけどね。
>>656 move semanticsしたのと、してないのを比べたいんじゃね?
コストが掛かるはずの普通の代入でも、RVO効くとコピーコスト0になるから。
>>653 多重定義したときに区別を付けるために必要。
>>653 左辺値参照と右辺値参照の区別があって一番うれしい場面は,
関数の実引数が右辺値なのか左辺値なのかを関数の定義内で
識別できるところです.例示しているコードにおいては,
右辺値参照が一時オブジェクトを束縛できることを除いて
x を右辺値参照型にで宣言しようが左辺値参照型で宣言しようが
本質的な違いが現れることは無いように思います.
>>655 試していないのでアレですけれど
struct X{ X(int i) : p_(new int(i)) {} ~X(){ delete p_; } int* p_ };
X f(bool b){
if (b) { return X(42); }
return X(43);
}
あたりだとRVOが阻害されませんか?
-O0 でも RVO するね。
667 :
デフォルトの名無しさん :2008/02/22(金) 14:46:39
そこそこ大規模なプロジェクトで,使われる例外についての 統制を取りたいと思ったとき便利な方法はないだろうか. どこかの馬鹿が int を throw するなどというバカげたことを していないということをコンパイル時に保証するのは無理? プロジェクト全体として std::runtime_error と std::logic_error から派生させたいくつかのクラスを 投げることを規約としているのだけど,馬鹿が適当な ものを投げてくるかもしれない. 結局 throw を全部見て回るしかない?
例外禁止がベスト、オプションで切っとけ
669 :
デフォルトの名無しさん :2008/02/22(金) 15:04:03
>>668 ちょ・・・それわ,無理w
マージ担当者にされてあたふたしてる.
670 :
649 :2008/02/22(金) 15:15:10
672 :
671 :2008/02/22(金) 16:10:16
って、コンパイル時のチェックにはならないんだっけかそういえば・・・
>>662 まさに言う通りのことを試したいんです。
-O0でもRVOします。
volatile int norvo(){ ... }
つ -fno-elide-constructors
>>671 無理
例外指定しても投げようと思えば何でも投げられる。
unexpected exceptionにはなるが。
C++の例外は破綻しているから使っちゃ駄目だって
破綻してないヨ。
破綻してないアル!
681 :
デフォルトの名無しさん :2008/02/22(金) 20:48:10
C++0x では例外周りでの新機能ってあるんですかね. っていっても自分でも新機能を思いつかないんだけど.
move semantics ほしいな
>>681 例外用の関数がいくつか追加されてたはず。
例えば catch(...) でも例外が取得できるようになった、とか。
>>667 そんなもんヌルポインタにアクセスしたり整数オーバーフローさせたり
無茶なキャストでコンパイラ黙らせたりしてるのと同じで、馬鹿が混ざっている
という前提ではどうしようもないもんだろ。
なんで例外だけ取り立ててどうにかしようと思うの?
main()でcatch (...)して、全開発者に同報メールを送るようにでもしておけばいいじゃんw
686 :
デフォルトの名無しさん :2008/02/23(土) 04:36:35
>>684 マージ担当の引き継ぎ事項に書いてあったから.
例外クラスに命名規則をつけておけば、 それに従っていない例外を投げている throw 式を 正規表現検索できると思う。
>>685 int main() {
try {
// main の中身
} catch(const std::runtime_error& e) {
// ここは規約通り
} catch(const std::logic_error& e) {
// ここは規約通り
} catch(...) {
// ここに飛んできたらおかしい
}
}
実際に飛んでこないと分からないがな。
>>686 そういうことなら throw と catch を検索して様子を見るぐらいで十分でしょ。
それ以上は他の未定義動作や禁じ手と同じで、完全なチェックは無理だと思うよ。
690 :
デフォルトの名無しさん :2008/02/23(土) 05:12:46
pimpl イディオムを使うとき、ポインタはどれがいいんでしょう? const std::auto_ptr<Impl> かな、と思うのですが、 boost::scoped_ptr<Impl> でもよさそうだし、 あんまり意味ないかもしれないけど boost::shared_ptr<Impl> でも。
>>690 普通は boost::scoped_ptr 。
std::auto_ptr は少し安全性が落ちる。
boost::shared_ptr は冗長。
>>686 throw を次のようにマクロで置き換える。
#ifndef NDEBUG
#define throw DEBUG_CHECK_EXCEPTION_(),
struct DEBUG_CHECK_EXCEPTION_ { };
template <typename T>
void operator,(DEBUG_CHECK_EXCEPTION_, const T& e) {
BOOST_STATIC_ASSERT((
::boost::is_same<T, ::std::runtime_error>::value ||
::boost::is_same<T, ::std::logic_error>::value ||
::boost::is_base_and_derived<T, ::std::runtime_error>::value ||
::boost::is_base_and_derived<T, ::std::logic_error>::value));
std::cout << typeid(T).name() << std::endl;
throw e;
}
#endif
これで静的にチェックできるはず。
ミスった。引数が逆だ。 #ifndef NDEBUG #define throw DEBUG_CHECK_EXCEPTION_(), struct DEBUG_CHECK_EXCEPTION_ { }; template <typename T> void operator,(DEBUG_CHECK_EXCEPTION_, const T& e) { BOOST_STATIC_ASSERT(( ::boost::is_same<T, ::std::runtime_error>::value || ::boost::is_same<T, ::std::logic_error>::value || ::boost::is_base_and_derived<::std::runtime_error, T>::value || ::boost::is_base_and_derived<::std::logic_error, T>::value)); std::cout << typeid(T).name() << std::endl; throw e; } #endif
あ、テストコードまぎれてる。 typeid のところは無視して。
>>693 <: が [ の代替表現に引っかかる。 < ::std... とスペース一個空けとかないといけない。
throw する型によってエラーが出るのは確認できた。役に立ちそうな予感はする。
ただ、 ~T() throw () {} みたいなのがコンパイルできないのがマズイ感じ。
標準ライブラリの中に throw () とか付いてる可能性を考えると、致命的かも。
696 :
デフォルトの名無しさん :2008/02/23(土) 08:08:44
>>690 COW実装したいときはshared_ptrが便利
698 :
デフォルトの名無しさん :2008/02/23(土) 11:07:20
D言語を使う場合、いいGUIツールがありますか? それがない限り、使う気になりません。 それとどんな言語でも最初は仕様がキレイなんですよね。 あのC++だって当初はキレイだったんですよ。 ところが実用的に使われ始めて呪文のような コードになってしまった。 C#もだんだん仕様が汚くなりつつあると聞いてます。 仕様がすっきりしてる言語なんて全く信用してません。
>>698 で、C++についてのどういった相談事でしょう?
D言語のことはD言語スレへ、C#のことはC#スレへお願いします
>>695 例外指定か・・・。なるほど。
throw じゃなくて THROW か何かを使わせることができるならそれが楽なんだが、
その規約を守らない人が出てくると・・・だしなあ。
Java みたいに throws ならいいのに・・・。
701 :
デフォルトの名無しさん :2008/02/23(土) 14:15:12
D の IDE なら Descent だろうかね。
>696 ふつーは、derived_class.BaseClass::Greeting()とかって書けばいいから ポインタ一個分のオーバーヘッドが無駄と言えば無駄だけど、 まー別にいいんじゃねーの。
>>696 あり得ない解決方法。
別メンバ関数(非仮想)を用意して、
そこで基底クラスの関数へ委譲すべき。
Greeting は仮想関数にした上で、ね。 あるいは、Derived の Greeting を別関数にするか。
SYSTEMCの勉強をしている、IC設計者です。 C++は初心者です。 C++で、class Signal を定義し、その中に、 string signal_name があったとき、 classを使う側で、 Signal sig1(); とだけすると、 そのsig1がsinanl_nameに自然に入るなんてことは できないのでしょうか。 コンストラクタの工夫などで。 やはり、Signal sig1("sig1"); として コンストラクタの中で渡されたstringで signal_nameを初期化する処理を書いて、 をしなければなりませんか。 同じ sig1 をいう名前を Signal sig1("sig1"); のように2回書くのがどうもなーと 思ったものですから。
>>706 コンストラクタの工夫では無理だろう
工夫する余地があるとすればプリプロセッサマクロだが・・・
#define sig1() sig1("sig1")
・・・は無理矢理すぎるか
#define DECLARE_SIGNAL(name) Signal name(#name)
で
DECLARE_SIGNAL(sig1); → Signal sig1("sig1")
に展開させるくらいじゃないかな
708 :
706 :2008/02/23(土) 18:34:24
>>707 なるほど、マクロかあ。
そういう方向で考えて見ます。
どうもありがとうございました。
709 :
デフォルトの名無しさん :2008/02/23(土) 18:41:19
fatal error C1060: ヒープの領域を使い果たしました。 テンプレートプログラミングの末路を見た。
プリプロセッサでごにょごにょすりゃ出来るけど、 何か変なことをやろうとしているような気がする。
>>709 コンパイラオプションでヒープをもっと増やせばいいだけ。
コンパイルに使うヒープを増やせるのか?
テンプレート関連のコンパイルで内部的にループにでもなったとか。 Zmで解決すれば良いけど
715 :
709 :2008/02/23(土) 21:47:56
Zm2000にしても無理だったんだ。
716 :
709 :2008/02/23(土) 21:54:15
どうやら無茶なことをしようとしていたようだ。 あきらめるわw
ちょっと質問です。VS2005、XP です。 大きさの等しい、文字列の配列と整数の配列がそれぞれあるとします。 文字列の配列を、整数の配列の値の順にソートしたいと思います。 std::sort など既存のソートアルゴリズムを使って、これを行ううまい方法はないでしょうか? 例: std::string a[] = {"aaa", "bbb", "ccc", "ddd"} int b[] = {7, 1, 5, 4} の場合、a を "bbb", "ddd", "ccc", "aaa" の順に並び替えたいと言うことです。 実際は文字列だけでなくいろいろな型を使うので、 文字列と整数をメンバとして持つ構造体を作って operator < を定義して std::sort にかける・・・というのは、少し長すぎて気が引けます。 よろしくお願いします。
>>717 構造体なんかつくらずにpairにしてvectorにでもいれて
比較関数を書いてsortさせるとか。
あるいは、いったんmapに突っ込んで取り出す。
ああー、pair を使うってのは思いつきませんでした。 pair なら比較関数をかかなくとも、first の方にキーを入れれば、std::sort でソートできますね。ありがとうございました。
>>690 auto_ptr は不完全型に使っちゃいけないことになってるから、候補からは外れると思うよ。
>>667 もしcppに細工することが出来るなら、
template <class T> inline void do_throw(const T &ex)
{ BOOST_STATIC_ASSERT((...)); throw ex; }
#ifdef NDEBUG
#define THROWS(spec)
#else
#define THROWS(spec) mycpp_throws spec
#endif
#define THROW(ex) do_throw(ex)
と定義しておいて、偽cppは本物のcppを実行してから#lineを見て
自分のプロジェクト内のコードにdo_throw以外のthrowがあったらエラーにする。
最後にmycpp_throwsをthrowに置換してコンパイラに渡せば一丁あがり。
一度これをやっておけば、コストを気にせず例外仕様をがんがん付けて
実行時の問題をデバッグすることも出来る。
>>721 たいていの実装ではそうなんだけど、規格はテンプレート引数に不完全型を使った時点で
その効果は未定義としている。
724 :
723 :2008/02/24(日) 01:15:41
あ、記載があるのは 17.4.3.6 ね。
BCC で変になってたとかいう話があったのはそれが原因か。
最新のドラフトだと個別に許可されていればおkのようだな。 多分 shared_ptr 絡みで追加されたんだと思うが。 実際、許可されてるクラスは shared_ptr, weak_ptr, enable_shared_from_this の3つだけだ。
横から補足すると、これはあくまでも標準ライブラリ側の制限なので、 scoped_ptrや自前auto_ptrなら問題ない。 ただし不完全型をdeleteしたらundefined behaviourなので (どう考えてもill-formedの間違いだと思うけど)、 自前auto_ptrを作るとしたらboost::checked_deleteを使うべし。
728 :
デフォルトの名無しさん :2008/02/24(日) 09:45:19
checked_delete なんてのがあるのか. しかしその実装を見てもなにやってるのかわからん. まんなかの (void) sizeof(....ってなにやってんの? template<class T> inline void checked_delete(T * x) { // intentionally complex - simplification causes regressions typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; (void) sizeof(type_must_be_complete); delete x; }
実際に何らかの形で使わないとエラーにならない処理系でもあるんじゃない?
730 :
デフォルトの名無しさん :2008/02/24(日) 10:02:04
>>729 使わないと最適化ですっ飛ばされちゃうこともあるのかねぇ.
>>728 sizeof(T)? 1: -1
sizeof(T) が 0 になることなんてあるの?
不完全型
struct Hoge {}; printf("%d", sizeof(Hoge)); →1 エーッ
サイズ0だと色々困る 例えば Hoge hoge[2]; &hoge[1] - &hoge[0] == 0 とかじゃまずい
>>733 不完全型とはvoidとか
class Widget;
のこと?
だったらsizeof(void) sizeof(Widget)はコンパイルエラーになるんだけど。
>>733 不完全型にはsizeof演算子は適用してはいけないと書かれてるんだが。
>>736 コンパイルエラーになってほしいんだからそれでおk
仮に 0 になる処理系があっても大丈夫という寸法なんだろう。
>>736-737 それを利用してコンパイルエラーにさせるから、"checked_" だろ
boostが使ってるね
その boost の話なんだが・・・
>>726 最小のフットプリントで不完全型を渡せる scoped_ptr の代替はないんだな。
unique_ptr でも不完全型を許可してほしいなぁ。 checked_delete 相当の
default_delete とか使うんだから、問題になることはないはず。
default_delete は不完全型の時には診断が要求される (A diagnostic is required if T is an incomplete type.) って書いてあるな。 デリータがテンプレートパラメータになってるから デリータを自分で指定すれば好きに出来そうではある。
>>744 そこまで書いておきながら、 unique_ptr に不完全型を許可する記述が無いのは
おかしいな。もしかして、書き漏らしてるだけ?
>>738 >>740 typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
仮に、sizeof(T)が0に評価されたときに
配列が-1という要素を持つことが許されないという理由でコンパイルエラー
にするという意図ならわかるが、
>>733 が言ってるとおりだとすると単に
不完全型だということなら、そもそもsizeof(T)自体がエラーの原因になるだろ。
だが、規格ではsizeof(不完全型)は許されていない。
規格に従えば、不完全型Tに対してsizeof(T)が0になることはない。
>>739 それなら納得
よく考えてるなぁ
全てのコンパイラが規格に従ってたら BOOST_WORKAROUND なんてもんは必要ないな。
>>745 デリータ次第だから default_delete に記述があれば十分だろう。
というか、これは不完全型は許可してないという記述じゃないのか?
いや、まあ挙動が定義されているからある意味許可はされているのか。
>>749 default_delete については不完全型を許可している(コンパイルエラーになると
規定している)ように読めるけど、それは unique_ptr に不完全型を渡した場合の
動作について何か言っていることにはならないでしょ。 default_delete 以外も
使えるんだし。
デリータはユーザが作った物も指定できるんだから、 規定できるわけないとまではいわんが 規定が無いのならユーザが自由にできるってことでしょう。
>>746 733は不完全型の場合にsizeof(T)が0になることがあるって意味だろ?
同じこと言ってると思うぞ
規格では不完全型で sizeof (T) するとエラーにならないといけないが、 エラーにならず 0 になる処理系があって、その対策なんだろうという話だな。
>>752 ああ、あああ、ああ、そうか。
じゃあ未定義なんだろうな。
>>755 俺に言われても知らない。733に聞いてくれ
>>757 誤解を招くってのは分かる
けど
>>732 に対して
>>733 なら「なることがある」だろ
# というか733みたいなおそらく一例を挙げただけの即答にツッコミ杉w
このスレに居るなら「すべきである」「しなければならない」みたいな違いに敏感だろうに・・・
肩凝ってしょうがねえ
&&の右辺値参照ってのは、右辺値を渡したときに渡した元のオブジェクト はどうなってもいいという前提なの?これがmove semanticsというもの? @ void f(X&& r); f(X()); // move semantics X()の状態は保障されない。 // r は右辺値参照。 A void f(X&& r); X x; f(x); //この場合(X&& r = x)は、rは左辺値参照。 B void f(X& r); X x; f(x); AとBは等価という理解でいい?
>>761 元のオブジェクトがどうなってもいいっていうのが非 const 右辺値参照でしょ。
2がコンパイルできるようだと右辺値参照の意味がないような気がする。
コンパイルエラーになるんじゃね?
template<int Value> struct base{}; struct a : base<0>{}; struct b : base<1>{}; struct c : base<2>{}; struct d : base<3>{}; ...... 何らかの型がbase<*>を継承している場合、その何らかの型とbaseの情報だけで baseに指定されたテンプレートパラメータを取得する方法はありませんか?
baseにpublic:enum{ VALUE=Value}とでもつけときゃいいじゃん
どういう状況で取得したいのかわからないから、 これが使えるかどうか自信がないけど。 template<int n> void f(base<n> const&) { }
>>763 intならenum
typeならtypedef
で保存
>>762 draftに以下の記述があるんだけど、これはどういう意味?
struct A {};
A a;
A&& ar = a;
The expression ar is an lvalue of Type A.
派生クラスもテンプレ化するとか
>>767 「 ar という式は型 A の左辺値である。」
・・・読んだまんまなんだが、こんな答えでいいのか?
>>767 は
>>762 の「2はコンパイルエラーになるかも」を受けての質問だろ?
draftにそうあるなら左辺値になるんだろうな。
それを
>>761 の(2)と(3)でオーバーロードされたfに渡したら
左辺値扱いなので(3)の方が選ばれる・・・とか? 俺も仕様知らないけど
>>770 説明不足だった。
ABのそれぞれの関数f()は、オーバーロードというつもりで
書いたわけじゃなくて渡す引数が左辺値なら、f()をどっちで定義しても
同義じゃないかと思った。
A
void f(X&& r);
X x;
f(x); //この場合(X&& r = x)は、rは左辺値参照。
B
void f(X& r);
X x;
f(x);
>>771 2が通るんなら右辺値参照受け取る関数なんて恐ろしくて作れない。
>>772 Aはとおるだろ。で、左辺値参照になるだけじゃねーの?
774 :
770 :2008/02/24(日) 22:59:32
>>771 説明不足なのはむしろ俺かwすまん
オーバーロードの意味じゃないのは分かってる
で、よく仕様知らないと言いつつ770で想定したのは↓
A a;
A&& ar = a;
f(ar); //arは左辺値扱い(?)なのでオーバーロードがあったら f(A&); の方が優先的に呼ばれるかも
で、arについての話だけ。
で、本題だけど、f(A());のケースだとf(A&&)しか呼べないだろうけど
引数が左辺値ならf()はどっちでも同義だと思う。
775 :
770 :2008/02/24(日) 23:00:39
「で、」が多いのは気にしないで下さい><
>>774 同じ認識になりますた。
で、オーバーロードの場合だと、左辺値引数を渡したら
左辺値参照を好むから void f(X&); が呼ばれるはず。
777 :
770 :2008/02/24(日) 23:06:56
>>772 もしコンパイルエラーにならなくても、
左辺値がオーバーロードでf(A&);に行くなら心配無いよな?
両方書いて、少なくともf(A&&)の方は「壊して良い」ってことになるから
778 :
772 :2008/02/24(日) 23:32:57
あー。 右辺値参照引数に左辺値が渡せないと、 unique_ptr みたいに移動だけを行うような モノが作れないな。 しかし「左辺値参照になる」ってのは解せないな。受け取った側では実引数が 左辺値か右辺値かによらず、扱いは同じ(式中の仮引数の型は左辺値参照)だろ。
const でない以上、壊されても文句は言えないっしょ。
すみません、ちょっと質問です。 あるstaticメンバ関数が指定のクラスに所属しているのかを見分ける方法はありますか? struct A { static void a() {}; static void ab() {}; } struct B : public A { static void ab() {}; } // メンバ関数がBに属するのかどうかを知りたい some_check_method<B, B::ab>() // true some_check_method<B, B::a>() // false といった感じにしたいのですが……。
>>780 そんな判別はできなさそうだなぁ。存在すらしてなければエラーになるし。
public 継承した上で、継承された名前が派生クラスのメンバと区別できるような
点が思い当たらないし。
なんでそんなことしたいのか、目的を言ってもらえればもうちょっと別の道が
ありそうな気はするんだけど
>>778 右辺値参照引数に左辺値を普通に渡すことはできない。
明示的にstatic_castするか、右辺値参照を返す関数を経由することで渡す。
void f(X&& r);
template <class T> inline typename remove_reference<T>::type&& move(T&& x)
{ return x; } // return文に限っては引数を暗黙に右辺値にキャストする!
X x;
f(x); // error
f(static_cast<X&&>(x)); // ok
f(std::move(x)); // ok
引数が左辺値の参照渡しに「なる」のは関数テンプレートだけの特殊なルール。
例えば上のmoveに左辺値xを渡すと、TとT&&はともにX&になってしまう。
fのように右辺値参照をとる非テンプレート関数に左辺値を渡せば単にエラーになる。
>>782 右辺値参照を取る非テンプレート関数に
キャストなしで左辺値を渡せると思いますよ
>>782 draftには
struct A {};
A a;
A&& ar = a;
これは可能ということになってる。独立右辺値参照は
左辺値で初期化可能で関数渡しはNGということは
右辺値参照に関しては、これまでの考えが通用せず
”右辺値参照パラメータの関数の引数渡しは初期化の
セマンティクスとは異なる”
ということになるの?
>>782 >引数が左辺値の参照渡しに「なる」のは関数テンプレートだけの特殊なルール>。 例えば上のmoveに左辺値xを渡すと、TとT&&はともにX&になってしまう。
これは、move(x)がmove<X&>(X&&& x)となり、&&&は&となるというルールだよな?
lvalue-to-rvalue conversion がかかるんで普通に渡せるんじゃない? static_cast とか std::move を使うのは overload の解決を制御するためだと思う。
787 :
782 :2008/02/25(月) 22:44:49
>>786 ものすごく細かい話になりますけれど, N2521 読む限りでは
>>784 のような例だと右辺値参照も左辺値参照も
全く同じ初期化の規則が適用されるように思われるので,
lvalue-to-rvalue conversion は適用されないんじゃないですかね?
lvalue-to-rvalue conversion があるので,右辺値で初期化できて
左辺値で初期化できないのは不自然に感じられるという意味なら
その通りだと思いますけれど.
>>786 void f(A&& rv);
A a;
f(a);
の場合、引数渡しでコピーは発生せずに rv は a を左辺値
として扱える(rvはaの別名)ということでOK?
791 :
デフォルトの名無しさん :2008/02/25(月) 23:20:35
void f(const A&); //@ void f(A&&); //A A g(); A a; f(a); //bound to @ f(g()); //bound to A これは間違いなさそうなんだけど、もし@が無くAだけだった場合は f(a) はエラーのような気もする。その場合は右辺値参照キャスト f(static_cast<A&&>(a)) or f(std::move(a)) を行う必要がある。 これが正しいのかな?
792 :
789=791 :2008/02/25(月) 23:23:57
>>790 >>788 を見て、
>>789 はNGかなと思ったんだけど、やっぱ正しいのかな?
それなら、
>>791 の内容は間違いで
f(static_cast<A&&>(a)) も f(std::move(a)) も必要ないな。
>>791 >もし@が無くAだけだった場合は
f(a) はエラーにはならないということでよいと思います.
>>792 788で本筋とあまり関係ないことを書いて混乱させたみたいですいません.
>>789 は適切という解釈でよいと思います.
スコットメイヤーズとかハーブサッターとかニコライジョスティスは 新規格が出たらまた本をたくさん出すんだろうな。 出たら欲しいもの 超簡単な初心者本 The C++ Standard Library (second edition) by ジョスティス Effective C++ (fourth edition) by メイヤーズ Effective STL (second edition) by メイヤーズ
ある程度の罠が減って、いくつかの罠が増えると
Modern C++0x Design
>>793 追記
A a;
A&& ar = a;
が正しくて、
void f(A&&);
f(a);
が正しくないとなると
”関数の引数渡しのセマンティクスは初期化のセマンティクスと同じである”
というこれまでの概念が崩れてしまうもんね。ちょっと安心した。
>>797 それは正直もういい。Singletonなんて考えすぎだろ。
確かにフェニックスパターンにはワラタ あれは考えすぎ
Modern C++0x using mpl (first edition) by ジョスティス なら欲しい。
小規模アロケータがデフォルトアロケータよりも遅かった という実験結果もWebに載ってたな。Efficient C++の シングルスレッド版は試したが確かに速かった。バグがあって ちと苦労したが。
803 :
780 :2008/02/25(月) 23:47:24
>781 理由は、 「ファクトリー関数を使用すると決めたけれども、派生クラスで関数の実装を強制できないと不安」 ということです。 #実際にはファクトリー関数みたいなものですが。 派生クラスを作成したときに必ずどこかでミスりそうなので、もしトラップする方法があったら 予防線を張っておこうかと考えました。
溺れてら
807 :
804 :2008/02/25(月) 23:57:38
>>805 runtime check で良いなら関数へのアドレス調べればよいだけだと思ったんですが
#include <iostream>
struct A
{
static void a() {}
static void ab() {}
};
struct B : public A { static void ab() {} };
int main()
{
std::cout << (&A::a == &B::a) << std::endl;
std::cout << (&A::ab == &B::ab) << std::endl;
}
compile-time check が要ったりしますか?
808 :
805 :2008/02/26(火) 00:04:20
& 体育座り
810 :
804 :2008/02/26(火) 00:39:50
うーん, compile-time check でメンバが存在しなくてもエラーにならないのを 考えてみましたけれど, MSVC7.1 では内部コンパイラエラーになる……orz GCC4.1.2 では通るんですが…… #include <iostream> struct A { //static void a() {} static void ab() {} }; template<class C> char (&has_a_helper(int))[sizeof(&C::a)]; template<class C> char (&has_a_helper(...))[sizeof(void (*)())+1]; template<class C> char (&has_ab_helper(int))[sizeof(&C::ab)]; template<class C> char (&has_ab_helper(...))[sizeof(void (*)())+1]; int main() { std::cout << sizeof(has_a_helper<A>(0)) << std::endl; std::cout << sizeof(has_ab_helper<A>(0)) << std::endl; }
struct A {private: //←追加 static void a() {} static void ab() {} }; struct B : public A { static void ab() {} }; でなんか問題アルの?
812 :
780 :2008/02/26(火) 01:05:48
>807 手動で関数へのアドレスを確認するのは面倒な気が…… >811 struct Aが使い物にならなくなります……。 一応、「登録したクラスと関数が一対一になっているかどうかを判別する」というところまでは 下記のコードで実現しています。 あくまで一対一対応の判別なので、クラススコープ内の関数かどうかは判別できませんが…… unsigned int count() { static unsigned int r(0); return r++; }; template<class type_t> unsigned int number() { static unsigned int r(count()); return r; }; template<typename member_t, member_t member> unsigned int number(unsigned int n) { static unsigned int r(n); return r; }; template<class type_t, typename member_t, member_t member> static bool check() { static unsigned int n(number<member_t, member>(number<type_t>())); return (n==number<type_t>()); }; struct A { static void a() {}; static void ab() {}; }; struct B : public A { static void ab() {}; }; BOOST_CHECK_EQUAL((check<A, void(*)(), A::ab>()), true); BOOST_CHECK_EQUAL((check<B, void(*)(), B::ab>()), true); BOOST_CHECK_EQUAL((check<A, void(*)(), A::a>()), true); BOOST_CHECK_EQUAL((check<B, void(*)(), B::a>()), false); ちなみに、このコードに興味ある人います?いるんでしたらフロ入った後に解説書きますけど。
よくわからんなー。struct Aは要するにインターフェースで、 static voidなa,abは要するに仮想関数なわけでしょ? で、オーバーライド必須にしたい、みたいな。 それのテンプレート版、という話と理解したけど、 ならNVIイディオム使えば終わる話じゃねーの?
814 :
780 :2008/02/26(火) 02:16:16
いや、>803にも書いたけど 「ファクトリー関数を使用すると決めたけれども、派生クラスで関数の実装を強制できないと不安」 ということですね。struct Bからさらに派生する場合も対応できるようにしたいです。 あとstaticメンバ関数は仮想にできないのでNVIはムリですね。
>>814 正直どういう風に使いたいのかよく分からん。
どういう風な事がやりたいのかとりあえずコード書いてくれ。
コンパイル通らなくてもいいから。
すみません、質問お願いします。 下のコードでパターン1と2をコメントアウトで切り替えると速度が大きく変わります。 原因わかる方いらっしゃいますか? for( i = 0; i < 1200000; i++ ) { *(pDst + 0 ) = *(pSrc + 0); *(pDst + 300) = *(pSrc + 1); *(pDst + 600) = *(pSrc + 2); *(pDst + 900) = *(pSrc + 3); pSrc += 4; // パターン 1 pDst += 1200; // こっちだと60msくらいかかる // パターン 2 pDst += 300; // こっちだと17msで終わる }
メモリのヒット率?
>>817 環境が判らんから何とも言えんが、恐らくは>818。
しかし、何でまたそんな小汚いコードを書いているんだ?
普通にpDst[900] = pSrc[3]と書けばいいものを。
>>817 そこだけならキャッシュのヒット率だと思うけど…
LinuxでIntelのx86使ってるならVTuneがタダで使えるよ
1200 * 1200000 = 1440000000 だけど、 そんなにメモリ確保してあるの? 確保してるとしても、ページフォールト起こしそう。 キャッシュよりそっちのが問題かもしれない。
みなさん回答ありがとうございます。
メモリのヒット率ですか・・・
そうだとするとここから先の高速化は難しそうですね・・・
ちなみに環境は以下の通りです。
Intel Core Duo T2500
メモリ1GByte
WindowsXP
VisualC++6.0
>>821 >1200 * 1200000 = 1440000000 だけど、
>そんなにメモリ確保してあるの?
ごめんなさい間違っていました。
1200000ではなく、300000です。
メモリは物理メモリ内に確保できています。
823 :
805 :2008/02/26(火) 20:26:04
ビョーン・ストラウストラップ氏はどこの国の人ですか?
ビャーネ・ストロヴストルップ(Bjarne Stroustrup, 1950年6月11日 - )は、 デンマーク・オーフス生まれのコンピュータ科学者。
>>824 thx
デンマークか。C++はアメリカ発信じゃないのがいい。
でも、C++はベル研生まれでアメリカ発信でそ?
ヨーロッパはやっぱりレベル高いよな。フィンランドとか凄いらしいな。
>>814 ファクトリーをstaticメンバ関数じゃなく関数テンプレートの特殊化にするのはダメ?
template <class T> T *factory();
class Base {
friend Base *factory<Base>();
protected:
Base();
virtual ~Base();
};
class Derived : public Base {
friend Derived *factory<Derived>();
protected:
Derived();
virtual ~Derived();
};
sizeof(空のクラス) = 1; sizeof(空の構造体) = 1; なぜ0バイトでなく、1バイトになるんでしょうか?
FAQ: EmptyRect kara[4];とかやってインスタンス化したとき、 サイズが0だと&kara[0] == &kara[3]とかになっちまってまずい。
>>829 複数のオブジェクトを作ったときにオブジェクトして何らかのサイズを持って
存在していないとuniqueなオブジェクとしてトアドレスが決まらない。
詳しくはInseide The C++ Object Modelに載ってる。
C++のSTLは便利なんですけど、 一行が助長に長くなってしまって耐えられません。
"助長に長く"の検索結果 2 件中 1 - 2 件目 (0.44 秒)
>>832 typedefを程よく使うしかないね。「程よく」ってのがまぁ、人それぞれなんだけど。
typedef std::vector<MyClass>::const_iterator Iter;
for (Iter i = vec.begin(); i != vec.end(); ++i) {
なんてのは、結構やる人多いはず。
Iterがこれ以降出てこない場合、このtypedefは全体としては「短縮」にも「簡略」にも
なっていないわけだけど、それでも「forの行を短く見せたい」というだけの理由で、俺はよくこう書いてる。
もちろん人によっては、「程よく」の範囲を超えた、余計な足踏みみたいに感じるのだろうけどね。
> 助長に長くなってしまって
このレス書き込む前にリロードしたらもう突っ込まれていたので、突っ込むのやめるw
C++0xのautoなら・・・いやなんでもない
言いかけて引っ込める意味がわからん。
態々それだけのためにレスをつける意味がわからん。 それはさておき、1行の長さを抑えるためにもインデントは4カラムにするのが定着した私。 >834みたいなことをすると、同じブロック内で別のイテレータ使いたくなるときに困ると思う。
ITE!救命阿!
#include <iostream> #include <vector> int main() { std::vector<int> v{ 1,2,3,4,5 }; for(auto i = v.begin(); i < v.end(); ++i) std::cout << *i << std::endl; }
BOOST_FOREACH()おいしいです
>>840 C++0xのSTLには採用されるのか?
>>842 禿が生きてる限り、標準ライブラリにプリプロセッサ使ったブツは追加されないんじゃね。
必要だってことになったら、言語に組み込む方法に持っていかれるだろ。
>>843 そういやマクロだからな
言語に組み込むなら、もっと詳細を詰める必要がありそうだな。
for (int x : v)のような構文でC++0xへ提案があったはず。
とりあえずまだ最新ドラフトには載ってない。
実は n2521 が出てる。
vc は独自拡張で for each なんて作っちゃってるよな
C++/CLIをVCの独自拡張とか言わないで欲しい
C++/CLIはVCの独自拡張。間違いない。
for eachはC++/CLI関係なく、ネイティブC++でも使用できる。 これは、C++でもC++/CLIでもないのだからVC++の独自拡張としか言えない。
むしろ独自拡張以外になんとお呼びすればよいのでしょうか的な
方言。
foreachとかrangeとか、ちょっと節操無さすぎだと思う。 今のC++への不満を直球で解決しようとしてるだけで、 STLが目指してきたものを蔑ろにしている。 autoとλを組み合わせて制御構造そのものはいじらないのが 正常な進化の方向だと思う。
859 :
デフォルトの名無しさん :2008/02/27(水) 23:24:30
#include <iostream> namespace{ void foo(){ std::cout << "anonymous foo" << std::endl; } } void foo(){ std::cout << "global foo" << std::endl; } int main(void) { //foo(); //コンパイルエラー ::foo(); //global foo } ここで無名名前空間のfooを明示的に呼ぶ方法はあるんでしょうか
ない
861 :
859 :2008/02/28(木) 00:46:45
まじすか・・・
無名名前空間って、staticの代わり以外に使い道ある?
>>862 ファイルローカルなクラスや列挙体を囲って ODR 違反を回避する。
namespace_start.hpp------ namespace{ namespace_end.hpp------ } #include "namespace_start.hpp" //... #include "namespace_end.hpp"
>>863 それってつまりどういうこと?
kwsk!!
>>866 // A.cpp
struct X { char x; };
// B.cpp
struct X { char y; };
両方コンパイルしてリンクすると同じクラスに対する2つの定義が異なるという
ODR 違反になり、未定義動作となる。
それぞれ無名名前空間で囲っておけば別々のクラスになるので問題なくなる。
868 :
デフォルトの名無しさん :2008/02/29(金) 02:25:40
class MyClass { private: int a; double b; char c; public: MyClass(int, double); ~MyClass(); void Func(int); }; int main() { MyClass myclass; myclass = MyClass(1, 2.0); } とした場合、myclass = MyClass(1, 2.0)は引数にある変数だけがコピーされるんですか? それともコンストラクタを実行した後のクラスの中身が全部コピーされるんですか?
代入演算子はデフォルトの動作はビットコピーだから
>>869 各メンバに対してoperator=を呼ぶんだと思ったが
どなたかわかる方いれば教えてください。 CE環境のプログラム上で、プログラムカウンタを参照する方法ってありませんか?
関数テンプレートHogeがあるとします。 HogeはT型のオブジェクトtを引数で受け取り、そのオブジェクトのメンバ関数Fugaを呼び出します。 ここで、Hogeに渡したtがFugaを持ってない場合、コンパイルエラーになりますが、 コンパイルエラーにせず、Fugaを呼び出さない別の実装に転送する方法はないでしょうか?
>>872 extern int* puroguramu_caunta asm ("pc");
使えるかどうかはしらね
っつうかスレ違い
>>873 コンパイル時に実装を切り替えるというのは、変態がよく使う。
本当にさまざまな方法がある。
例えば関数のオーバーロードとか、テンプレートクラスの特殊化など
詳しく知りたかったら、C++ Template Metaprogrammingを読め。
で、ある名前のメンバ関数を持っているかどうかってのは、
かなりトリッキーなコードになるので、もっとマシな方法で実装分岐させたほうがいい。
877 :
876 :2008/02/29(金) 15:17:45
>>875 ありがとうございます。
試してみます。
スレ違いになるのね…
すみませんでした。
>>877 C++ Template Metaprogrammingってよお、買ったけどboost::mplの
リファレンスじゃねーか。Webサイト見たほうがいいわ。
騙された。
881 :
873 :2008/02/29(金) 15:59:28
>>874 ,876
どうもです。
省略符号を使ったテクニックがあったんですね。
C++ Template Metaprogrammingは読んでいませんが、Modern C++ Designは読んだので大体分かります。
省略符号を使って変換可能性と継承を検出するテクニックも書いてありましたね・・。
テンプレートに関数ポインタ渡してメンバ関数の有無検出する方法、思いつかなかったorz
>>876 >で、ある名前のメンバ関数を持っているかどうかってのは、
>かなりトリッキーなコードになるので、もっとマシな方法で実装分岐させたほうがいい。
トリッキーでもいいけどC++ Template Metaprogrammingって本に何か例が書いてあるの?
>>882 >>873 がどの程度C++を知っているのか分からなかったから、出してみただけ。
ある名前を持つメンバ関数でコンパイル時の分岐がやりたいなんていいだす奴は、
そもそも何も分かってないバカか、本当に自分が言っている事を理解していて、それでもやりたい変態しかいない。
Modern C++ Desingを枕にするぐらいだったら、必要なかったね。
884 :
デフォルトの名無しさん :2008/02/29(金) 16:29:57
placement newで生成した配列データってどう解放すればいいんでしょうか? void *pvMem = AllocMemory(sizeof(CNode) * num); CNode *pcNodes = new(pvMem) CNode[num]; for(int i = 0; i < num; i++) { pcNodes[i].~CNode(); } FreeMemory(pcNodes); これだとダメみたいです。
placement deleteは呼ばなくてもいいんかい?
>>884 AllocMemory
FreeMemory
ここで何やってるんだ?
>>884 ×FreeMemory(pcNodes);
○FreeMemory(pvMem);
>>884 普通、
void FreeMemory(void*);
のシグニチャだと思うけど。
それなら、それでも良いはずなんだが。
>>885 FreeMemoryでメモリ解放するの特に必要ないかと思って・・・
>>886 AllocMemory(size)
sizeだけメモリを確保
FreeMemory(p)
pが先頭のメモリブロックを解放する
>>887 それもダメでした
890 :
885 :2008/02/29(金) 17:12:51
すまん、placement deleteは関係ないや。 (Effective C++ Item52)
>>889 >AllocMemory(size)
>sizeだけメモリを確保
特別なメモリ確保のライブラリか何か?
AllocMemoryでnew演算子を使用
FreeMemoryでdelete演算子を使用
なんてことじゃないよね?
>>884 new するときもひとつずつ placement new するしか無いんでは・・・
>>891 >特別なメモリ確保のライブラリか何か?
そうです。提供されているもので自作ではありません。ここでは関数名は変えて書きましたが。
>AllocMemoryでnew演算子を使用
>FreeMemoryでdelete演算子を使用
size分メモリ確保してるだけなのでnew,deleteはしていません。
>>884 AllocMemory(size)でreturn operator new(size);
FreeMemory(p)でoperator delete(p);
と思っていい?
>>892 そうなんですかね・・・。なんてこった
実はちょっと前にそっちのやり方で作ってたんですけど、確かにそれはきちんと動いていました。
VCでも似たような状況が再現できました。対処法はわかりませんが #include <iostream> #include <new> class CNode { public : int temp[3]; public: CNode(){ Init(); } virtual ~CNode(){} public : void Init(){ temp[0] = 0; temp[1] = 1; temp[2] = 2; } }; #define PLACEMENT_NEW 0
つづき int main() { char *buf = new char[sizeof(CNode) * 3]; #if PLACEMENT_NEW CNode *pcNode = new(buf) CNode[3]; #else CNode *pcNode = reinterpret_cast<CNode*>(buf); for(int i = 0; i < 3; i++) { pcNode[i].Init(); } #endif #if PLACEMENT_NEW for(int i = 0; i < 3; i++) { // placement newをやっていないと落ちる pcNode[i].~CNode(); } #endif // PLACEMENT_NEW=1のときは落ちない delete [] buf; return 0; }
>PLACEMENT_NEW=1のときは落ちない PLACEMENT_NEW=0のtきは落ちない、でした
確かサイズ指定しなきゃダメじゃなかったけ? そのせいで使い物にならなかった気がする。
>>900 ちょっとよくわかりません。もう少し詳しくお願いします
placement newに対しては、placement deleteを呼ばないといけない。 ちゃんとなってる? CNode::operator delete( p, buf );
>>898 ちょっとまて、placement newしているかどうかにかかわらず、
delete[]が呼び出されるのは何なんだ?
placement newしているポインタに、delete[]したら、鼻から悪魔が出てくるのは当たり前だろ。
あと、placement newしていない場合のコードも鼻から悪魔が出るな。
>>884 ところで、placement new[]に渡されるsizeはsizeof(T)*Nとは限らないぞ。
そこでメモリ破壊してるんじゃねえの。
ちょっと出直してきます。 いろいろ参考になりました。ありがとうございました
>>906 AllocMemory -> operator new(size_t) を使用
FreeMemory -> operator delete(void*) を使用
と思われる。(AllocMemoryのシグニチャでは要素数が判別できないので
内部でoperator new[](size_t)を使用することは難しい)
で、
CNode *pcNodes = new(pvMem) CNode[num];
これはマズイ。
配列用の配置newはCNodeクラスのデフォルトコンストラクタ
をnum回実行する。実装に依存するけど、例えば次のようなことが
考えられる。sizeof(delta)を配列の要素数などの管理情報を確保して
おくための領域のサイズとすると、アドレスpvMemからpvMem + sizeof(delta)
の領域に管理情報を書き込み、最初のコンストラクタはアドレス pvMem + sizeof(delta)
に対して実行される。そして最後のコンストラクタはsizeof(delta)バイトだけ
飛び出した未確保の領域まで初期化してしまう。
結局、非配列用のoperator new(size_t)の戻り値のアドレスに配列用の配置newを
使用することは危険。pvMemを自分で管理して、配列用ではない配置newをnum回実行
して初期化すべきかと。
>>905 ご使用のVCでは管理情報の領域として4バイトが使用されているのかも。
元々の環境では、違うサイズ、あるいは全く異なる実装で配列が管理
されてるのかも。
>261 のリンク先にもあるんだけどさ >SFINAE allows you to determine type information at compile-time through the usage of overload resolution. >However, it cannot prevent non-type syntax errors. An example of which you have demonstrated in your code. >The class member T::Foo does not exist, nor is it a type, as such SFINAE does not apply here. 規格上で SFINAE の根拠になるのは 14.8.2/2 だと思うんだけど、U::Hage はそこで挙がってる type deduction の失敗の例には 入らないので syntax error を引き起こすと思うんだが。いやコンパイル通っちゃったんだけどさ。 で、placement new についてだけど、>887 と >904 他が正しいと思われる。 > 5.4.3/12 > new T[5] results in a call of operator new[](sizeof(T)*5+x), and > new(2,f) T[5] results in a call of operator new[](sizeof(T)*5+y,2,f). > Here, x and y are non-negative unspecified values representing array allocation overhead; the result of the > new-expression will be offset by this amount from the value returned by operator new[]. This overhead > may be applied in all array new-expressions, including those referencing the library function > operator new[](std::size_t, void*) and other placement allocation functions. The amount > of overhead may vary from one invocation of new to another.
class Holder.....Impl のポインタを持ち、Holder() : m_pImpl(new Default_Impl()){} class Impl.....抽象クラス class Default_Impl.....Impl を public 継承 std::vector<Holder> を持つ これで、Holderのインスタンス作ったらオーバーフローになってしまいました。 調べてみたら、 1, Holder のコンストラクタ 2, Default_Impl のコンストラクタ 3, std::vector<Holder> のアロケータ 4, Holder のコンストラクタ 以下ループ っということらしいのですが、 どういう設計にすれば上のようなクラスを問題なく作成できるのでしょうか。
>>912 やりたいことが間違ってるだけにしか見えん。
違うというのなら何がやりたいのか説明してくれ。
>>913 これ以外に、関数ポインタを受け取れる Func_Impl があって、
Holder(void (*func)(Arg)) : m_pImpl(new Func_Impl(func)){}
のようにHolderを作成できて、
Default_Impl で作ったHolderは上記のような関数を保持するHolderと、
それを複数保持するDefault_Implを保持するHolderを保持したくて、
Holderの operator() で保持してる関数全てを実行するようなクラスを作りたいと思っています。
>>914 なんで Default_Impl のコンストラクタで引数無しの Holder を生成してるの?
>>915 >>Default_Impl で作った
は、
Default_Impl を保持するHolder(引数なしHolderのコンストラクタから生成)
でした。紛らわしい表現をしてすみません…。
理想としては
Holder holder;
holder.add(Holder(関数ポインタ1));
holder.add(Holder(関数ポインタ2));
holder.add(holder2); // 別のHolder
holder(); // 全ての関数を実行
という動作をさせたいと思っています。
>>875 一体何のためにPCなんか参照したいんだ?
>>911 <new>で定義されてるグローバルの配置operator new(size_t, void*)関数である
new(pvMem) CNode[num]; については、pvMemをreturnしてるだけ。
その後で、コンストラクタが必要な回数だけ実行される。その際、配列の管理が
コンパイラ依存で行われる。
>>904 は一般的な配置newについて正しいが、このケースでは<new>のものを使用している
ので
>>908 、
>>910 が上手く表現している。
>918 とりあえず placement new で領域割り当ててるわけじゃない、という点については >908 の方がより的確なのかもしれないけど。 必要なサイズは sizeof(T)*N じゃない、ぐらいの気持ちで。 もともとの placement new の位置づけからすればこっち(別の割り当て済みメモリ領域にオブジェクトを生成する)の方が主な 使い方の気もするけど、AllocMemory とか FreeMemory に突っ込みが入るようだとあまり一般的じゃないのかなぁ。 で、どっちかというと >887 で指摘されてる点があんまり言及されてないのが気になって。 <new> で規定されてるのは allocation function であって、それ自体は単に渡された値を返していたとしても、 new 演算子の結果 new(pvMem) CNode[num] については、allocation fuction から返ってきた値そのままではないよね?
>>916 だからさ、 Default_Impl のコンストラクタで引数無しの Holder を生成しなくても
できるだろ。なんでわざわざ生成して当然の無限再帰を引き起こすのさ?
921 :
868 :2008/03/01(土) 01:11:57
>>920 std::vector<Holder> を初期化するときにHolderのコンストラクタが呼ばれる、ということでしょうか
呼び出し履歴からHolderの引数なしコンストラクタが呼ばれているのは分かったのですが、
Default_Impl のどこで呼ばれているのかとその対策が分からず困っています。
具体的にDefault_Impl の実装のどこが間違っていて、どう対処すればいいのか、
ヒントだけでも教えていただけると助かります。
>>922 Default_Impl の実装を見せずにその間違いを指摘しろとは、エスパーでも募集してんのか?
925 :
912 :2008/03/01(土) 01:29:04
>>925 > Default_Impl() : m_holder(0) {}
vector(size_type n, value_type const& x = value_type()) が呼ばれてる。
空でいいなら m_holder() でもいいし、何も書かずにデフォルトの初期化に
してしまってもいい。
927 :
868 :2008/03/01(土) 01:34:27
すみません。アンカーミスです。
>>870 でした。
>>925 vector<Holder>(0)は、2つの省略可能な引数を持つコンストラクタを読んでる。
そこで、Holder()が生成される。
>>926 , 928
ありがとうございます、無事実行することが出来ました
vector(0) でコンストラクタが呼ばれるはずがない、
という勝手な思いこみで要領を得ない質問ばかりしてしまいましたが、
回答をいただけてとても助かりました。
>>919 ><new> で規定されてるのは allocation function であって、それ自体は単に渡された値を返し>>ていたとしても、 new 演算子の結果 new(pvMem) CNode[num] については、allocation fuction
> から返ってきた値そのままではないよね?
実装依存なので絶対とは言えないけど、ほとんどの実装でそうなっていると思える。
おそらくは配列の要素数を格納するための領域分ずれてる。
実際、配列の要素数は配置new演算子に渡されたアドレスの直後に置かれることが多い。
でも、あくまでも実装依存であって規格では未定義。
でも問題はそれ以前であって、強調したかったのは、規格に従う限りにおいては、
AllocMemoryが戻すアドレスpvMemを配列用の配置構文newに new(pvMem) CNode[num]
のように渡すことさえ問題が起こりうるということ。何故なら、要素数がどこに書
き込まれるかは分からないから。実装を熟知し(配列の管理情報は本当に要素数だけか?
渡すべき正しいアドレスは何か?)、移植性を考えないという条件でのみこれは許され
ることになる。つまるところ、
>>908 と
>>910 のドキュメントどおり、ユーザーが確保した
領域に対して配列用の配置構文newを使うことは難しく、常に危険を伴っている。
配置構文newにどのアドレスを渡してよいかは厳密に言うと実装を知らないと判断できない。
931 :
780 :2008/03/01(土) 03:45:16
思ったんだが、C++で生のC配列なんか使う メリットないだろ。 配列用の配置構文が使い物にならんのは つまりそういうこと。
そもそも設計がおかしくないか?
>>932 つまらないこと言うなよ。
やるなと言えばそれまでだが、やったらどうなるの?
に対する回答にはならん。
>>917 あとから確認するときに、場所を特定するために残しておきたいんです。
>>934 明らかに回答ではないんだから(現在の話題に関して「思ったこと」を書いてるだけ)、
別に回答になっていなくても問題は無いと思うよ。
質問から始まった話題について何か書き込む時は、絶対に回答としての機能を
持っていなければならない、という信念があるとしたら、もうちょっと柔軟になったほうが・・・。
規格では未定義= もしそのコードを実行してしまったら何が起こるか予測できないって事 placement new は将来のために予約されたものだと俺は思ってるから 積極的に使うものじゃないと思う。 コレ使ってるライブラリって見たことない。
>>937 std::allocatorのconstruct
C++0xでアラインメントをサポートするんじゃなかったっけ そうなれば多少マシになるんじゃないの
>>938 サンクス
ユーザレベルなら
std::allocator
boost::pool_allocator
あたり使ったほうがいいですよね?
>>940 placement new 使いたいためにわざわざ std::allocator の construct 使うの?
なんで? placement new 使えばいいじゃない。
>>935 たとえば今のPCは、今居る関数のポインタ値にだいたい近いよね。
それじゃダメなの?
__FILE__と__LINE__で何が不満なわけ?
スタックトレースでもしたいんじゃないの
ドットイートのようなゲームを作りたいんですが、 どうしてもドットを食わず、素通りしてしまいます。 自機がドットを通ると道になるようなプログラムは どうしたらできるんでしょう?
ドットを表す値が入っている変数に道を表す値を代入すればいいんじゃない。
当たり判定チェックミスってんじゃね?
>>945 今はどうやってるんだ
まずそれを説明してみろ
template <typename T> と template<class T> といった 2種類の書き方が存在するみたいだけど、どっちも一緒ですか? あと、使うならどっちが望ましいんでしょう。
どっちも一緒。 template template parameter つまり template<template <typename T> class U> の時だけは class じゃないと駄目。 趣味の問題だから好きな方を使えば良い。
template<class T> class A { private: typename T::B m_abc; } のときはtypenameじゃないとだめ
600000000000を変数に入れたいんですけど、どうすればいいのか教えてください。 unsigned long int r=600000000000 だとinteger constant is too large for "long" type といエラーが出てしまいました。
>>952 厳密な精度が要らなければ double などの不動小数点数を使うといい。
そうじゃなければ多倍長整数を使うことになるでしょう。
>>952 long long int int r=600000000000;
コピペみすったorz long long int r=600000000000;
long long は正式には C++0x から導入されるものだろう・・・。 とはいえ、今の所規格上はそういう型はないしなあ。 まあ、規格で int が 32 ビットと決まってるわけではないから int が 64 ビットの場合もあるわけだが。 まあ、環境によって typedef unsigned __int64 UINT64; か typedef unsigned long long UINT64; かを定義すればいいよ。
まず何故そんな大きな数値を扱う必要があるのか、その理由を・・・ 目的によって double, 多倍長整数, UINT64, BCD など変わってくるだろ
だからそれも C++0x から導入される(略
C99を取り込んでいるコンパイラなら大抵使えるけどな。
よーしパパboost::uint64_t使っちゃうぞー
962 :
952 :2008/03/02(日) 22:36:22
>>952 コンパイラのデータモデルを調べよう
>>958 のようにデータモデル別に定義してくれてるライブラリの型を使うのが安泰
代表的なのだと、gcc4がILP32,LP64、vc++がILP32,LLP64など、
組み込み系だとLP32なんて曲者もあるから困る
class hoge を作っておいて、list<hoge> x を生成します。 そのとき、hogeのメンバ関数も使いたいのですが、STLを使った場合だと x.piyo()みたいではアクセスできません。 どうすれば解決できるんでしょうか?
Spring is here.
>>964 xの中には複数のhogeがあるだろ?hogeのリストなんだから
どのhogeのpiyoを呼びたいんだよ?って話
全部のhogeについて呼びたいんなら、
for (list<hoge>::iterator i = x.begin(); i != x.end(); i++)
i->piyo();
勘違いしてました。 分かりやすくありがとうございました
Spring has come.
Spring to gone.
wind the spring
gone with the wind
ride the wind
cut it out
974 :
デフォルトの名無しさん :2008/03/08(土) 20:52:30
Who are you?
coutやcinのcって何ですか? console?character?
976 :
デフォルトの名無しさん :2008/03/09(日) 11:51:19
977 :
デフォルトの名無しさん :2008/03/09(日) 13:29:11
プリプロセッサフリーにいつかはなるのかな? でもincludeできなくなるのは困るな。 assertも無くなると困るな。
console
the answer is blowing in the wind...
980 :
デフォルトの名無しさん :2008/03/09(日) 16:15:09
演算子オーバーロードはネームスペーススコープでやるのとクラススコープでやるのは 何が違うんでしょうか?
メンバ関数かどうか
>>980 1.クラススコープでしかできない演算子がある。
2.クラススコープの場合、第一引数(this)に暗黙の変換が適用されない。
二項演算子などで引数の対称性を表現できない。
3.非クラススコープで、非public部へアクセスする場合カプセル化の度合い
を弱めることになる。
C++の入門書のお勧めは?
個人的には本じゃなく入門サイトを巡ってみることを勧めるが・・・
入門サイトが正しいかどうか判断できない
一番の王道は言語仕様書
Accelerated C++ あたりか?
入門してからAcceleratedしようぜ。
>>986 だから巡るんだよ
本でもサイトでも1つだけを参考にするのは良くない
>>982 1の理由が2という理解であってますか?
またstaticなメンバやグローバル関数にできない演算子は
= () -> [] の四つであってますか?
入門書はC++Primerの英語のを読んでるけど、分厚くて萎えまくりです。
巡っても結局判断できないと思うが
趣旨分かってる? 質問者は入門、つまりC++を理解し始めたいのであって、 言語仕様書の日本語訳を探してるわけじゃないんだよ
>>993 くだらないこと言ってないでサイトでも本でもお薦めを教えてやればいいのに。
いつも思うが、まずは何でもいいから自分で探してやれよ。 後々、あれは失敗だったなと思うこともあるけどそれも経験だ。 原書含め数十冊読んだが、常に手元に置くものは自然と 決まってくる。それが自分のベストセラー。
教えたくないということだな
998 :
933 :2008/03/09(日) 19:35:44
>>994 だから俺は複数のサイトを自分で巡って見たほうが良いと言っているんだが・・・
むしろお薦めの本を教えてやればいいのは、巡っても意味無いと言う
>>992 とかだろ?
だから、巡るといい複数のサイトの候補を教えてあげればいいんだよ 質問者の趣旨を汲むならね
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。