
自前でnewのような関数を作っています。
mallocで確保したメモリ領域のそれぞれの項目に対してコンストラクタを呼び出したいのですが、
テンプレートで指定されたクラスのコンストラクタを明示的に呼ぶにはどうしたらよいですか?
テンプレート関数でなく、特定のクラスに対するものならできたのですが、
テンプレートで一般的に対応しようと思った所で躓きました。
また、deleteのほうは意図通り実装できました。
struct HOGE{
HOGE(){}
};
//特定のクラスに対するものは正常
HOGE *mynew(size_t len){
HOGE *v = (HOGE*)malloc(len * sizeof(HOGE));
for(size_t t = 0; t < len; ++t){
//v[t].HOGE();//error C2274: '関数形式のキャスト' : '.' 演算子の右側で使用できません。
v[t].HOGE::HOGE();//OK
}
return v;
}
template<typename T>
T *mynew(size_t len){
T *v = (T*)malloc(len * sizeof(T));
for(size_t t = 0; t < len; ++t){
v[t].T::T();//error C2039: 'T' : 'HOGE' のメンバーではありません。
//代わりに以下のように書いてみたが若干危険で効率も悪そう
T tmp = T();
memcpy(v + t, &tmp, sizeof(T));
memset(tmp, 0, sizeof(T));
}
return v;
}
template<typename T>
void mydelete(T *v, size_t len){
for(size_t t = 0; t < len; ++t){
v[t].~T();//OK
}
free(v);
}
HOGE *h = mynew<HOGE>(3);//NG
HOGE *j = mynew(3);//テンプレート関数でない方は呼べる
mydelete(j, 3);//OK
No.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;
}
この回答への補足
返事がおそくなってすいません。
なるほど、外部で確保したポインタを渡すことで、newをコンストラクタを呼び出すためだけに使うということですね。
newの構文が複雑なので、単にコンストラクタを呼ぶというテンプレート関数にして、mallocの部分と分離してしまった方がわかりやすそうです。
この方法をとってみようと思います。
placement newの記事を探しているうちに、当初の「渡されたポインタをそのまま返すnew」を知らずに、後から知られた使い方「任意の引数を渡せるnew」を先に知ってしまい、それを自分で定義しようとしてごちゃごちゃになっていたようです。
newをインクルードして教えていただいたコードが実行できました。
ありがとうございました。
No.3
- 回答日時:
> テンプレート関数でなく、特定のクラスに対するものならできたのですが、
本当ですか?
> v[t].HOGE::HOGE();//OK
これは何をしているのか、ちゃんと理解していますか。
No.2
- 回答日時:
「これでおおよそ目的が果たせそうなのですが、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;
}
No.1
- 回答日時:
1st choice は placement new か.
あるいは適当に typename を追加する?
この回答への補足
ありがとうございます。
placement newについて調べた所、自前定義のnewが呼び出された後、勝手にコンストラクタを呼んでくれるようです。
また、自前のdeleteが呼び出される前に、勝手にデストラクタを呼んでくれるようです。
これでおおよそ目的が果たせそうなのですが、operator new[]とoperator delete[]は定義できたのですが、operator newとoperator deleteはすでに定義されてるとでて、オーバーライド(?)できませんでした。
グローバルのnewとdeleteを置き換える方法はありませんか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# leetcode 155 minstack 1 2022/05/07 16:43
- C言語・C++・C# プログラミングのペーパーテスト 実行結果を表示せよ #include <stdio.h> int h 1 2022/07/09 15:27
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- Windows 10 バッチファイルの記述法とルールについてアドバイスをお願いいたします。 1 2022/04/13 10:50
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- JavaScript JavaScriptで「〇以上▲まで」の書き方 1 2022/07/20 14:44
- HTML・CSS 全部のアクセスを指定したページに転送させたい 2 2022/06/28 16:33
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- XML XML同じ名前の要素を自動で集約するツール 1 2022/04/11 09:21
関連するカテゴリからQ&Aを探す
今、見られている記事はコレ!
-
弁護士が解説!あなたの声を行政に届ける「パブリックコメント」制度のすべて
社会に対する意見や不満、疑問。それを発信する場所は、SNSやブログ、そしてニュースサイトのコメント欄など多岐にわたる。教えて!gooでも「ヤフコメ民について」というタイトルのトピックがあり、この投稿の通り、...
-
弁護士が語る「合法と違法を分けるオンラインカジノのシンプルな線引き」
「お金を賭けたら違法です」ーーこう答えたのは富士見坂法律事務所の井上義之弁護士。オンラインカジノが違法となるかどうかの基準は、このように非常にシンプルである。しかし2025年にはいって、違法賭博事件が相次...
-
釣りと密漁の違いは?知らなかったでは済まされない?事前にできることは?
知らなかったでは済まされないのが法律の世界であるが、全てを知ってから何かをするには少々手間がかかるし、最悪始めることすらできずに終わってしまうこともあり得る。教えてgooでも「釣りと密漁の境目はどこです...
-
カスハラとクレームの違いは?カスハラの法的責任は?企業がとるべき対応は?
東京都が、客からの迷惑行為などを称した「カスタマーハラスメント」、いわゆる「カスハラ」の防止を目的とした条例を、全国で初めて成立させた。条例に罰則はなく、2025年4月1日から施行される。 この動きは自治体...
-
なぜ批判コメントをするの?その心理と向き合い方をカウンセラーにきいた!
今や生活に必要不可欠となったインターネット。手軽に情報を得られるだけでなく、ネットを介したコミュニケーションも一般的となった。それと同時に顕在化しているのが、他者に対する辛らつな意見だ。ネットニュース...
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エディットコントロールでEnter...
-
FriendとPublicの違い。。。
-
C# 別プロジェクトのフォームを...
-
(UWSC) 「#32770」の意味わかり...
-
【ASP.NET】 独自で作成したク...
-
Homepage Managerの事
-
ダイアログ表示時にチェックボ...
-
名前空間について
-
イベントにAddHandlerされてい...
-
OnInitDialog()の関数の組み込み方
-
VC++ 7.1 で メインウィンドウ...
-
関数の呼び出し元の検索
-
MFCのドラッグ&ドロップについて
-
DataContextについて
-
MFCアプリのコマンドラインでパ...
-
既定のコンストラクタがない?
-
ダイアログクラスのコントロー...
-
ボタンのオーナードローについて
-
ヘッダーファイルでは、他のヘ...
-
リストコントロールをウィンド...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBA チェックボックスをオーバ...
-
FriendとPublicの違い。。。
-
既定のコンストラクタがない?
-
イベントにAddHandlerされてい...
-
(UWSC) 「#32770」の意味わかり...
-
ボタンのオーナードローについて
-
MFCアプリのコマンドラインでパ...
-
ダイアログ表示時にチェックボ...
-
【ASP.NET】 独自で作成したク...
-
エディットコントロールでEnter...
-
MFCのドラッグ&ドロップについて
-
オーバーライド関数の呼び出し...
-
DataGridViewのセルに斜線を引...
-
MFCのCListCtrlでスクロールを検出
-
C++ protectedにアクセス不可
-
ダイアログクラスのコントロー...
-
クラスのアドレスを引数として...
-
エディットコントロールのイベ...
-
個々の関数について継承してい...
-
WindowsAPIのリストビューの...
おすすめ情報