オブジェクトのメモリが既にある場合、new
を使用せずに明示的にコンストラクタを呼び出すことはできますか?
class Object1{
char *str;
public:
Object1(char*str1){
str=strdup(str1);
puts("ctor");
puts(str);
}
~Object1(){
puts("dtor");
puts(str);
free(str);
}
};
Object1 ooo[2] = {
Object1("I'm the first object"), Object1("I'm the 2nd")
};
do_smth_useful(ooo);
ooo[0].~Object1(); // call destructor
ooo[0].Object1("I'm the 3rd object in place of first"); // ???? - reuse memory
並べ替え。 placement new を使用して、既に割り当てられているメモリを使用してコンストラクターを実行できます。
#include <new>
Object1 ooo[2] = {Object1("I'm the first object"), Object1("I'm the 2nd")};
do_smth_useful(ooo);
ooo[0].~Object1(); // call destructor
new (&ooo[0]) Object1("I'm the 3rd object in place of first");
したがって、new
キーワードを引き続き使用していますが、メモリの割り当ては行われません。
新しいプレースメントを探していると思います。 C++ FAQ Lite には、これを行う方法の概要があります。このエントリからいくつかの重要な落とし穴があります。
#include <new>
配置の新しい構文を使用します。建設と破壊の両方で、それをどのように行うことができるかについていくつかのコードを紹介しましょう
#include <new>
// Let's create some memory where we will construct the object.
MyObject* obj = (MyObject*)malloc(sizeof(MyObject));
// Let's construct the object using the placement new
new(obj) MyObject();
// Let's destruct it now
obj->~MyObject();
// Let's release the memory we used before
free(obj);
obj = 0;
上記の要約が物事を明確にすることを願っています。
文字通り、いや、「新しい」キーワードなしではできません。実際にメモリを割り当てずに「new」キーワードを使用してコンストラクターを呼び出す方法については、配置に関するすべての回答を参照してください。
はい、独自の割り当てられたバッファを取得したら、新しい配置を使用します。ブライアンボンディは、関連する質問でここで良い反応を示しています。
デストラクタを呼び出すことはできますが、メモリは再生されず、関数呼び出しと同等になります。デストラクタの下で2つのことを行うことを覚えておく必要があります。仕様に基づいてオブジェクトを破棄し、メモリを再利用します。とにかくスタックに割り当てられたオブジェクトに対してdtorが呼び出されるため、2回呼び出すと、未定義の動作が発生する可能性があります。
はい、新しい配置を使用します-上記のように、オブジェクトをコピーすることを意味する場合でも、ストレージを管理するための2番目のファクトリクラスを持つことを検討するかもしれません。 memcpy()は、一般に小さなオブジェクトには安価です。
次のテンプレートを使用できます
template <typename T, typename... Args>
inline void InitClass(T &t, Args... args)
{
t.~T();
new (&t) T(args...);
}
使用法:
struct A
{
A() {}
A(int i) : a(i) {}
int a;
} my_value;
InitClass(my_value);
InitClass(my_value, 5);