C++placement構文の理解
6782 ワード
最近のグループ読書活動はplacement newとplacement deleteについてもっと深く理解させた.
new式について
C++は、
本の上で、スタック(heap)空間に空間を申請し、大きさは に等しい.出願の空間上にオブジェクトを構築する、すなわち、呼び出しオブジェクトの構築関数 また、ユーザーがカスタムメモリ領域でオブジェクトを構築する場合は、次の構文で別の
具体的には、次のように使用されます.
第2の
delete式について##
C++が提供するdelete式の構文:
本によると、deleteは2つのことを完成したという.呼び出しオブジェクトの構造関数, オブジェクトが存在するメモリ領域を解放し、システム に戻る
特に、
標準operator newとoperator delete##
C++標準のnew expression内部呼び出しは標準の
同様に、C++標準のdelete expression内部呼び出しは標準の
placement newとplacement delete##
C++標準のnew式は大部分の需要を完成することができて、しかしすべてではありませんて、例えば:どのように既存のメモリ空間の上でオブジェクトを作成して、標準のnew式はできなくて、C++も直接rawメモリの上でオブジェクトの構造関数を呼び出すことを支持しなくて、そこでplacement newは発生して、名前
もちろん、その場で作成するオブジェクトは一部であり、placement newにはより広範なエピタキシャルがあり、placement new expressionとplacement
placement
The "placement"versions of the new and delete operators and functions are known as placement new and placement delete.
placement new expressionとは、C++構文に属し、標準的なnew expressionと同様である.異なることに、内部呼び出しは対応する
Any new expression that uses the placement syntax is a placement new expression
標準new expressionが標準
私たちが呼び出したのは標準
The reason that there is no built-in "placement delete"to match placement new is that there is no general way of assuring that it would be used correctly.
placement delete expressionがない以上、なぜplacement
placement new expressionコンストラクションオブジェクトを呼び出すと、コンストラクション関数に異常が放出されます.この場合、C++は対応するplacement
placement operator new()とplacement operator delete()
上記はexpressionとoperatorの違いを定義だけで、どのような関数がplacement
placement
nothrowバージョンのnewは、placement newとplacement deleteによって実現されるC++標準でもあることに注意してください.対応するnothrowバージョンのnew expressionは次のとおりです.
ユーザのカスタムスペース上でオブジェクトを構築することはplacement newの本意であり、C++標準でdefault placementとしても使用される.
対応するplacement new expressionは、次のように使用されます.
种植体系统
実際のアプリケーションでは、メモリプールが最も多く使用されています.説明する価値があります.メモリプールの定義は次のように仮定します.
placement newとplacement deleteを定義することによって
オブジェクトの作成:
今の問題はどのように
これにより、
あるいは2つの操作を1つのtemplateにカプセル化します.
そしてこのように呼び出します
リファレンス http://en.wikipedia.org/wiki/Placement_syntax http://www.stroustrup.com/bs_faq2.html#placement-delete http://stackoverflow.com/questions/222557/what-uses-are-there-for-placement-new
new式について
C++は、
new
キーワードとdelete
キーワードを提供し、それぞれメモリ領域の申請と解放に使用され、new
式の構文は以下の通りである.new new-type-id ( optional-initializer-expression-list )
本の上で、
new
表現は2つのことをしますsizeof(new-type-id)
new
式を呼び出すことができます.new ( expression-list ) new-type-id ( optional-initializer-expression-list )
具体的には、次のように使用されます.
void *buffer = malloc(sizeof(ClassA));
ClassA *ptr = new(buffer)ClassA();
第2の
new
式は、第1の特例のように、ステップ2を完了するだけで、ステップ1をユーザに残す.delete式について##
C++が提供するdelete式の構文:
delete type_pointer;
本によると、deleteは2つのことを完成したという.
特に、
type_pointer
をNULLに等しくするとdelete式も正しく機能するが、同じポインタに対してdelete
を繰り返し呼び出すと未定義のエラーが発生する標準operator newとoperator delete##
C++標準のnew expression内部呼び出しは標準の
operator new()
であり、その定義は以下の通りである.void * operator new (std::size_t) throw(std::bad_alloc);
operator new()
は、標準的なallocation、すなわちメモリ割り当てを完了するオペレータまたは関数である.同様に、C++標準のdelete expression内部呼び出しは標準の
operator delete()
であり、その定義は以下の通りである.void operator delete (void *) throw();
operator delete()
オペレータまたは関数でもあり、標準的なdeallocation、すなわちメモリ解放を完了します.placement newとplacement delete##
C++標準のnew式は大部分の需要を完成することができて、しかしすべてではありませんて、例えば:どのように既存のメモリ空間の上でオブジェクトを作成して、標準のnew式はできなくて、C++も直接rawメモリの上でオブジェクトの構造関数を呼び出すことを支持しなくて、そこでplacement newは発生して、名前
placement
をつけて、その歴史の出所を説明して、
で新しいオブジェクトを構築します.もちろん、その場で作成するオブジェクトは一部であり、placement newにはより広範なエピタキシャルがあり、placement new expressionとplacement
operator new()
は、通常、placement newとして一般的に混同され、概念が混同されている.placement
operator new()
とは、まず関数であり、標準operator new()
のリロード関数である.wikiでは次のように定義されています.The "placement"versions of the new and delete operators and functions are known as placement new and placement delete.
placement new expressionとは、C++構文に属し、標準的なnew expressionと同様である.異なることに、内部呼び出しは対応する
placement operator new()
であり、wikiでは次のように定義されている.Any new expression that uses the placement syntax is a placement new expression
標準new expressionが標準
operator new()
を呼び出しているように、placement new expressionが呼び出しているのはplacementバージョンのoperator new()
で、簡単にストレートに見え、混ざっても問題ないようですが、placement deleteを見てみるとplacementoperator delete()
関数を表しています.placement delete expressionは存在しないので、私たちが呼び出すとdelete pObject;
私たちが呼び出したのは標準
operator delete()
です.なぜplacement delete expressionがないのか、C++の創設者は次のように説明しています.The reason that there is no built-in "placement delete"to match placement new is that there is no general way of assuring that it would be used correctly.
placement delete expressionがない以上、なぜplacement
operator delete()
が必要なのか、重要な原因は、C++がplacementoperator delete()
とplacementoperator new()
をペアにする必要があるからである.次のように仮定します.placement new expressionコンストラクションオブジェクトを呼び出すと、コンストラクション関数に異常が放出されます.この場合、C++は対応するplacement
operator delete()
のみを呼び出し、placementoperator new()
で取得したメモリリソースを解放します.そうしないと、メモリが漏洩します.次の例では、#include
#include
struct A {} ;
struct E {} ;
class T {
public:
T() { throw E() ; }
} ;
void * operator new ( std::size_t, const A & )
{std::cout << "Placement new called." << std::endl;}
void operator delete ( void *, const A & )
{std::cout << "Placement delete called." << std::endl;}
int main ()
{
A a ;
try {
T * p = new (a) T ;
} catch (E exp) {std::cout << "Exception caught." << std::endl;}
return 0 ;
}
placement operator new()とplacement operator delete()
上記はexpressionとoperatorの違いを定義だけで、どのような関数がplacement
operator new()
とplacementoperator delete()
と呼ばれ、標準operator new()
およびoperator delete()
との違いにカスタムパラメータが追加する.ただし、以下のルールを守らなければならない.placement
operator new()
の場合、その最初の関数パラメータはstd::size_t
で、申請のメモリのサイズを表す必要があります.placementoperator delete()
の場合、その最初の関数パラメータはvoid *
である必要があり、解放するオブジェクトポインタを示す.例:void * operator new (std::size_t) throw(std::bad_alloc); //
void * operator new (std::size_t, const std::nothrow_t &) throw(); // placement
void operator delete (void *) throw(); //
void operator delete (void *, const std::nothrow_t &) throw(); // placement
nothrowバージョンのnewは、placement newとplacement deleteによって実現されるC++標準でもあることに注意してください.対応するnothrowバージョンのnew expressionは次のとおりです.
T *t = new(std::nothrow) T;
ユーザのカスタムスペース上でオブジェクトを構築することはplacement newの本意であり、C++標準でdefault placementとしても使用される.
void * operator new (std::size_t, void * p) throw() { return p ; }
void operator delete (void *, void *) throw() { }
対応するplacement new expressionは、次のように使用されます.
void *buffer = malloc(sizeof(ClassA));
ClassA *ptr = new(buffer)ClassA();
种植体系统
実際のアプリケーションでは、メモリプールが最も多く使用されています.説明する価値があります.メモリプールの定義は次のように仮定します.
class Arena {
public:
void* allocate(size_t);
void deallocate(void*);
// ...
};
placement newとplacement deleteを定義することによって
Arena
に作用するvoid* operator new(size_t sz, Arena& a)
{
return a.allocate(sz);
}
void operator delete(void *ptr, Arena& a)
{
return a.deallocate(ptr);
}
オブジェクトの作成:
Arena a();
X *p = new(a)X;
今の問題はどのように
delete
を呼び出して、私達が呼び出すことができないためですdelete p;
これにより、
operator delete()
のplacementバージョンではなく、標準のArena
しか有効になりません.そのためには、次のようにするしかありません.p->~X();
operator delete(p, a);
あるいは2つの操作を1つのtemplateにカプセル化します.
template void destroy(T* p, Arena& a)
{
if (p) {
p->~T(); // explicit destructor call
a.deallocate(p);
}
}
そしてこのように呼び出します
destroy(p,a);
リファレンス