- ベストアンサー
テンプレート指定クラスのコンストラクタを明示呼出
- テンプレート指定クラスのコンストラクタを明示的に呼び出す方法を教えてください
- 特定のクラスに対するコンストラクタの明示的な呼び出しはできましたが、テンプレートで一般的に対応する方法はわかりません
- deleteの実装は意図通りできました
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
placement newを十分理解していないようですね。 C++で未初期化の領域に対して、明示的にコンストラクタを呼び出す方法は、placement new以外にはありません。 やりたいことは以下のようなものではないでしょうか template<typename T> T *mynew(size_t len){ T *v = (T*)malloc(len * sizeof(T)); for(size_t t = 0; t < len; ++t){ new(&v[t]) T(); } return v; }
その他の回答 (3)
- colder
- ベストアンサー率43% (30/69)
> テンプレート関数でなく、特定のクラスに対するものならできたのですが、 本当ですか? > v[t].HOGE::HOGE();//OK これは何をしているのか、ちゃんと理解していますか。
補足
ありがとうございます。 v[t]にたいしてコンストラクタを呼んでいるつもりなのですが、間違っているでしょうか。
- Tacosan
- ベストアンサー率23% (3656/15482)
「これでおおよそ目的が果たせそうなのですが、operator new[]とoperator delete[]は定義できたのですが、operator newとoperator deleteはすでに定義されてるとでて、オーバーライド(?)できませんでした。」 と書かれていますが, operator new や operator delete が突然出てきているのはなぜでしょうか? 元の質問を読む限り, 「グローバルのnewとdeleteを置き換える」必要などないはずですが. いずれにしても, エラーメッセージは正確に書いてほしいし, 「どう書いたらどこでどのようなエラーが出たのか」を秘密にするようならまともな答えが返ってこない可能性は理解してほしい.
補足
placement newを調べるとoperator newにたどり着きました。 グローバルのnewとdeleteを置き換えたときに出たエラーはヘッダにかいて__inlineを付け忘れていたため、定義の重複でした。すいません。 void *operator new(size_t sz){ return malloc(sz + 1); } error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) は既に inlineCheck.obj で定義されています。 グローバルなnewを置き換えたい理由は以下です。 1 要求された個数よりも1要素分余分なバッファを確保する 2 要求された個数分の要素に対して確保時にコンストラクタを、破棄時にデストラクタを呼ぶ。余分に確保された1要素分にはコンストラクタもデストラクタも呼ばず、0で埋める 3 intやコンストラクタを持たないオブジェクトは、未定義値ではなく0で埋める グローバルな一般的なnewを置き換えるのは、ライブラリを使うときに混乱するので、いろいろ調べた結果、余分な引数を持ったnewがあることを知ったので、それをつかって目的が果たせそうです。 (通常のnewではvoidと要求されたサイズだけが渡され、1要素分のサイズがわからなかったが、余分な引数を持つnewでそのサイズが渡せた) //配列の最後に要素0を追加して返すnull terminated new void *operator new[](size_t tsz, size_t tsz2){ tsz += tsz2; unsigned char *v = (unsigned char*)malloc(tsz); for(size_t t = 0; t < tsz; ++t){ v[t] = 0; } return v; } void operator delete[](void *v, size_t tsz2){ free(v); } template<typename T> T *ntnew(size_t tlen){ return new(sizeof(T)) T[tlen]; } template<typename T> void ntdel(T *v){ delete[] v; }
- Tacosan
- ベストアンサー率23% (3656/15482)
1st choice は placement new か. あるいは適当に typename を追加する?
補足
ありがとうございます。 placement newについて調べた所、自前定義のnewが呼び出された後、勝手にコンストラクタを呼んでくれるようです。 また、自前のdeleteが呼び出される前に、勝手にデストラクタを呼んでくれるようです。 これでおおよそ目的が果たせそうなのですが、operator new[]とoperator delete[]は定義できたのですが、operator newとoperator deleteはすでに定義されてるとでて、オーバーライド(?)できませんでした。 グローバルのnewとdeleteを置き換える方法はありませんか?
お礼
placement newの記事を探しているうちに、当初の「渡されたポインタをそのまま返すnew」を知らずに、後から知られた使い方「任意の引数を渡せるnew」を先に知ってしまい、それを自分で定義しようとしてごちゃごちゃになっていたようです。 newをインクルードして教えていただいたコードが実行できました。 ありがとうございました。
補足
返事がおそくなってすいません。 なるほど、外部で確保したポインタを渡すことで、newをコンストラクタを呼び出すためだけに使うということですね。 newの構文が複雑なので、単にコンストラクタを呼ぶというテンプレート関数にして、mallocの部分と分離してしまった方がわかりやすそうです。 この方法をとってみようと思います。