TKernel模块–RTTI,对象句柄,引用计数
1.DEFINE_STANDARD_HANDLE(x1, x2)
#define DEFINE_STANDARD_HANDLE(C1,C2) DEFINE_STANDARD_HANDLECLASS(C1,C2,Standard_Transient)
其中:
#define DEFINE_STANDARD_HANDLECLASS(C1,C2,BC) class C1; class Handle_##C1 : public Handle(C1) \
{ \
public: \Handle_##C1() {} \Handle_##C1(Handle(C1)&& theHandle) : Handle(C1)(theHandle) {} \template <class T2, typename = typename std::enable_if <std::is_base_of <C1,T2>::value>::type> \inline Handle_##C1(const opencascade::handle<T2>& theOther) : Handle(C1)(theOther) {} \template <class T2, typename = typename std::enable_if <std::is_base_of <C1,T2>::value>::type> \inline Handle_##C1(const T2* theOther) : Handle(C1)(theOther) {} \template<typename T> inline Handle_##C1& operator=(T theOther) { Handle(C1)::operator=(theOther); return *this; } \
};
也就是最终展开为:
class C1;
class Handle_C1 : public Handle(C1)
{
public:Handle_C1() {} Handle_C1(Handle(C1)&& theHandle) : Handle(C1)(theHandle) {}template <class T2, typename = typename std::enable_if <std::is_base_of <C1,T2>::value>::type> inline Handle_C1(const opencascade::handle<T2>& theOther) : Handle(C1)(theOther) {} template <class T2, typename = typename std::enable_if <std::is_base_of <C1,T2>::value>::type> inline Handle_C1(const T2* theOther) : Handle(C1)(theOther) {} template<typename T> inline Handle_C1& operator=(T theOther) { Handle(C1)::operator=(theOther); return *this; }
};
实际上定义了一个新类型Handle_xxx,作为Handle(xxx)的另一种形态。
2.Handle(C1)
#define Handle(Class) opencascade::handle<Class>
其中:
namespace opencascade {template <class T>class handle {public:typedef T element_type;private:Standard_Transient* entity;private:void Assign (Standard_Transient *thePtr) {if (thePtr == entity)return;EndScope();// 递减先前对象引用entity = thePtr;BeginScope();// 增加新对象引用}void BeginScope() {if (entity != 0)entity->IncrementRefCounter();}void EndScope() {if (entity != 0 && entity->DecrementRefCounter() == 0)entity->Delete();entity = 0;}public:handle () : entity(0) {}handle (const T *thePtr) : entity(const_cast<T*>(thePtr)) {BeginScope();}handle (const handle& theHandle) : entity(theHandle.entity) {BeginScope();}handle (handle&& theHandle) Standard_Noexcept : entity(theHandle.entity) {theHandle.entity = 0;}~handle () {EndScope();}void Nullify() {EndScope();}bool IsNull() const { return entity == 0; } void reset (T* thePtr) {Assign (thePtr);}handle& operator= (const handle& theHandle) {Assign (theHandle.entity);return *this;}handle& operator= (const T* thePtr) {Assign (const_cast<T*>(thePtr));return *this;}handle& operator= (handle&& theHandle) Standard_Noexcept {std::swap (this->entity, theHandle.entity);// 指针交换。指针指向对象内部引用不变。return *this;}T* get() const { return static_cast<T*>(this->entity); }T* operator-> () const { return static_cast<T*>(this->entity); }T& operator* () const { return *get(); }template <class T2>bool operator== (const handle<T2>& theHandle) const { return get() == theHandle.get();}template <class T2>bool operator== (const T2 *thePtr) const { return get() == thePtr;}template <class T2>friend bool operator== (const T2 *left, const handle& right) {return left == right.get();}template <class T2>bool operator!= (const handle<T2>& theHandle) const {return get() != theHandle.get();}template <class T2>bool operator!= (const T2 *thePtr) const {return get() != thePtr;}template <class T2>friend bool operator!= (const T2 *left, const handle& right) {return left != right.get();}template <class T2>bool operator< (const handle<T2>& theHandle) const { return get() < theHandle.get();}/*作用:实现从handle<基类>到handle<派生类>的转换,通过dynamic_cast保证了转换的正确性。如果基类实际类型不是派生类或更具体类型,返回的handle<派生类>中指针为null。返回类型:使用 opencascade::std::enable_if 和 is_base_but_not_same 实现 SFINAE(Substitution Failure Is Not An Error),确保只有满足条件时才会编译此函数:is_base_but_not_same<T2, T>::value:检查 T2 是 T 的基类(但排除 T2 和 T 相同的情况)。若条件为真,返回 handle<T> 类型;否则忽略此函数(避免编译错误)*//*dynamic_cast<T*>:执行运行时类型检查(RTTI):若 theObject 实际指向的是 T 类型(或其派生类),返回正确的 T*。否则返回 nullptr(此时返回的 handle<T> 为空)。*/template <class T2>static typename opencascade::std::enable_if<is_base_but_not_same<T2, T>::value, handle>::typeDownCast (const handle<T2>& theObject) {return handle (dynamic_cast<T*>(const_cast<T2*>(theObject.get())));}template <class T2>static typename opencascade::std::enable_if<is_base_but_not_same<T2, T>::value, handle>::type DownCast (const T2* thePtr) {return handle (dynamic_cast<T*>(const_cast<T2*>(thePtr)));}explicit operator bool () const { return entity != nullptr;}template <class T2, typename = typename std::enable_if<is_base_but_not_same<T2, T>::value>::type>operator const handle<T2>& () const {return reinterpret_cast<const handle<T2>&>(*this);}/*作用:当T2是T的基类时,实现自动从handle<T>到handle<T2>的转换*/template <class T2, typename = typename std::enable_if<is_base_but_not_same<T2, T>::value>::type>operator handle<T2>& () {return reinterpret_cast<handle<T2>&>(*this);}template <class T2> friend class handle;};
}
结合上述代码和注释不难理解handle,主要针对T为Standard_Transient派生类型时,提供自动引用管理及对原生指针的封装。
3.Standard_Transient
class Standard_Transient {
public:/*所有派生类需重复声明 DEFINE_STANDARD_ALLOC 以保持内存管理一致性。*//*DEFINE_STANDARD_ALLOC 在 Standard_Transient 中的作用是:1.替换默认内存管理,提升性能与安全性;2.为 OCCT 的引用计数和类型系统提供基础设施;3.确保跨平台行为一致。这是 OCCT 实现高性能、稳定性的核心设计之一。*/DEFINE_STANDARD_ALLOC
public:Standard_Transient() : myRefCount_(0) {}Standard_Transient (const Standard_Transient&) : myRefCount_(0) {}Standard_Transient& operator= (const Standard_Transient&) { return *this; }virtual ~Standard_Transient() {}
public: // 作为动态类型层次的起点。其base_type需要特殊指定。// 非起点一般用DEFINE_STANDARD_RTTIEXT,IMPLEMENT_STANDARD_RTTIEXT指定typedef void base_type;static constexpr const char* get_type_name () { return "Standard_Transient"; }// Standard_Type是自定义RTTI机制的实现者。Standard_Type类字段包含了自定义RTTI所需的信息。// 对Standard_Transient用于获得自身的RTTI注册及注册后结果。Standard_EXPORT static const opencascade::handle<Standard_Type>& get_type_descriptor (){return opencascade::type_instance<Standard_Transient>::get();}// 向RTTI注册并取得注册结果。Standard_EXPORT virtual const opencascade::handle<Standard_Type>& DynamicType() const{return get_type_descriptor();}Standard_EXPORT Standard_Boolean IsInstance(const opencascade::handle<Standard_Type>& theType) const{return (AType == DynamicType());}Standard_EXPORT Standard_Boolean IsInstance(const Standard_CString theTypeName) const{return IsEqual ( DynamicType()->Name(), theTypeName );}// 当aType就是Standard_Transient,或是Standard_Transient的某个父类时返回trueStandard_EXPORT Standard_Boolean IsKind(const opencascade::handle<Standard_Type>& aType) const{return DynamicType()->SubType ( aType );}Standard_EXPORT Standard_Boolean IsKind(const Standard_CString theTypeName) const{return DynamicType()->SubType ( theTypeName );}// 安全的取得自身指针Standard_EXPORT Standard_Transient* This() const{if (GetRefCount() == 0)throw Standard_ProgramError("Attempt to create handle to object created in stack, not yet constructed, or destroyed");return const_cast<Standard_Transient*> (this);}
public:inline Standard_Integer GetRefCount() const noexcept { return myRefCount_; }inline void IncrementRefCounter() noexcept {myRefCount_.operator++();}inline Standard_Integer DecrementRefCounter() noexcept {return myRefCount_.operator--();}// 释放自身virtual void Delete() const {delete this;}
private:std::atomic_int myRefCount_;
};
其中:
# define DEFINE_STANDARD_ALLOC \void* operator new (size_t theSize) \{ \return Standard::Allocate (theSize); \} \void operator delete (void* theAddress) \{ \Standard::Free (theAddress); \} \DEFINE_STANDARD_ALLOC_ARRAY \DEFINE_STANDARD_ALLOC_PLACEMENT# define DEFINE_STANDARD_ALLOC_ARRAY \void* operator new[] (size_t theSize) \{ \return Standard::Allocate (theSize); \} \void operator delete[] (void* theAddress) \{ \Standard::Free (theAddress); \}/*
DEFINE_STANDARD_ALLOC_PLACEMENT 是 OCCT 为高效内存管理提供的底层工具宏,通过自定义 placement new/delete 实现:
零开销对象构造:在预分配内存上直接初始化。
异常安全:满足 C++ 对 placement new 的配套要求。
与 OCCT 内存体系集成:服务于 Standard_Allocator 等模块。
这种设计在需要严格控制内存分配的 CAD/CAM 内核中尤为重要。
*/
# define DEFINE_STANDARD_ALLOC_PLACEMENT \void* operator new (size_t, void* theAddress) \{ \return theAddress; \} \void operator delete (void*, void*) \{ \}
/*
实例:
char* buffer = (char*)Standard::Allocate(sizeof(Geom_Point));
// 1.此语句会先触发placement new的执行。
// 2.基于placement new的返回值作为基础执行构造。
// 这就允许placement new实际返回另一个地址并在其上执行构造。不过默认实现里,返回传入地址。
Geom_Point* point = new (buffer) Geom_Point(0, 0, 0); // 在 buffer 上构造对象
*/
Standard_Transient首先是OCCT中以引用计数管理自身的类层次起点,同时搭配OCCT中以Standard_Type为基础实现的自定义RTTI机制,提供相关服务。
由于类自定义了new/delete操作符,所以此类型实例的原始内存分配统一通过opencascade自定义方式进行。
4.Standard
class Standard {
public:DEFINE_STANDARD_ALLOCenum class AllocatorType {NATIVE = 0,OPT = 1,TBB = 2,JEMALLOC = 3};Standard_EXPORT static AllocatorType GetAllocatorType(){return allocatorTypeInstance();}/*以calloc为例:调用 C 标准库函数 calloc 分配一块大小为 theSize * sizeof(char) 的内存,并初始化为全零。使用实例:Standard_Address aPtr = calloc(1, sizeof(Geom_Point));Geom_Point* p = new (aPtr) Geom_Point(); // 在零初始化内存上构造对象*/Standard_EXPORT static Standard_Address Allocate (const Standard_Size theSize){#ifdef OCCT_MMGT_OPT_FLEXIBLEreturn Standard_MMgrFactory::GetMMgr()->Allocate(theSize);#elif defined OCCT_MMGT_OPT_JEMALLOCStandard_Address aPtr = je_calloc(theSize, sizeof(char));if (!aPtr)throw Standard_OutOfMemory("Standard_MMgrRaw::Allocate(): malloc failed");return aPtr;#elif defined OCCT_MMGT_OPT_TBBStandard_Address aPtr = scalable_calloc(theSize, sizeof(char));if (!aPtr)throw Standard_OutOfMemory("Standard_MMgrRaw::Allocate(): malloc failed");return aPtr;#elseStandard_Address aPtr = calloc(theSize, sizeof(char));if (!aPtr)throw Standard_OutOfMemory("Standard_MMgrRaw::Allocate(): malloc failed");return aPtr;#endif // OCCT_MMGT_OPT_FLEXIBLE}/*以malloc为例:优化体现在,相比calloc,malloc分配内存后无需初始化,有助于提升性能。*/Standard_EXPORT static Standard_Address AllocateOptimal (const Standard_Size theSize){#ifdef OCCT_MMGT_OPT_FLEXIBLEreturn Standard_MMgrFactory::GetMMgr()->Allocate(theSize);#elif defined OCCT_MMGT_OPT_JEMALLOCreturn je_malloc(theSize);#elif defined OCCT_MMGT_OPT_TBBreturn scalable_malloc(theSize);#elsereturn malloc(theSize);#endif}Standard_EXPORT static void Free (const Standard_Address thePtr){#ifdef OCCT_MMGT_OPT_FLEXIBLEStandard_MMgrFactory::GetMMgr()->Free(theStorage);#elif defined OCCT_MMGT_OPT_JEMALLOCje_free(theStorage);#elif defined OCCT_MMGT_OPT_TBBscalable_free(theStorage);#elsefree(theStorage);#endif}template <typename T>static inline void Free (T*& thePtr) { Free ((void*)thePtr);thePtr = 0;}Standard_EXPORT static Standard_Address Reallocate (const Standard_Address theStorage, const Standard_Size theNewSize){#ifdef OCCT_MMGT_OPT_FLEXIBLEreturn Standard_MMgrFactory::GetMMgr()->Reallocate(theStorage, theSize);#elif defined OCCT_MMGT_OPT_JEMALLOCStandard_Address aNewStorage = (Standard_Address)je_realloc(theStorage, theSize);if (!aNewStorage)throw Standard_OutOfMemory("Standard_MMgrRaw::Reallocate(): realloc failed");return aNewStorage;#elif defined OCCT_MMGT_OPT_TBBStandard_Address aNewStorage = (Standard_Address)scalable_realloc(theStorage, theSize);if (!aNewStorage)throw Standard_OutOfMemory("Standard_MMgrRaw::Reallocate(): realloc failed");return aNewStorage;#elseStandard_Address aNewStorage = (Standard_Address)realloc(theStorage, theSize);if (!aNewStorage)throw Standard_OutOfMemory("Standard_MMgrRaw::Reallocate(): realloc failed");return aNewStorage;#endif}Standard_EXPORT static Standard_Address AllocateAligned (const Standard_Size theSize, const Standard_Size theAlign){#ifdef OCCT_MMGT_OPT_JEMALLOCreturn je_aligned_alloc(theAlign, theSize);#elif defined OCCT_MMGT_OPT_TBBreturn scalable_aligned_malloc(theSize, theAlign);#else#if defined(_MSC_VER)return _aligned_malloc(theSize, theAlign);#elif defined(__ANDROID__) || defined(__QNX__)return memalign(theAlign, theSize);#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && (defined(__i386) || defined(__x86_64)))/*作用:分配一块大小为 theSize 的内存,并确保其起始地址按 theAlign 字节对齐。*//*与标准 malloc 的区别特性 _aligned_malloc 标准 malloc对齐保证 强制按 theAlign 对齐 通常仅 8/16 字节对齐释放方式 必须用 _aligned_free 释放 直接用 free 释放跨平台性 Windows 特有(Linux 用 posix_memalign) 跨平台通用*/return _mm_malloc(theSize, theAlign);#elsevoid* aPtr;if (posix_memalign(&aPtr, theAlign, theSize)) {return NULL;}return aPtr;#endif#endif}Standard_EXPORT static void FreeAligned (const Standard_Address thePtrAligned){#ifdef OCCT_MMGT_OPT_JEMALLOCreturn je_free(thePtrAligned);#elif defined OCCT_MMGT_OPT_TBBreturn scalable_aligned_free(thePtrAligned);#else#if defined(_MSC_VER)_aligned_free(thePtrAligned);#elif defined(__ANDROID__) || defined(__QNX__)free(thePtrAligned);#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && (defined(__i386) || defined(__x86_64)))_mm_free(thePtrAligned);#elsefree(thePtrAligned);#endif#endif}template <typename T>static inline void FreeAligned (T*& thePtrAligned) {FreeAligned ((void* )thePtrAligned);thePtrAligned = 0;}Standard_EXPORT static Standard_Integer Purge(){#ifdef OCCT_MMGT_OPT_FLEXIBLEreturn Standard_MMgrFactory::GetMMgr()->Purge();#elsereturn true;#endif }
};
其中分配类型:
namespace {static Standard::AllocatorType& allocatorTypeInstance() {static Standard::AllocatorType aType =
#ifdef OCCT_MMGT_OPT_FLEXIBLEStandard::AllocatorType::NATIVE;
#elif defined OCCT_MMGT_OPT_TBBStandard::AllocatorType::TBB;
#elif defined OCCT_MMGT_OPT_JEMALLOCStandard::AllocatorType::JEMALLOC;
#elseStandard::AllocatorType::NATIVE;
#endifreturn aType;}
}
受到宏定义控制。
从上述代码中,可以看出Standard通过提供静态方法对外部提供统一的原始内存空间分配和回收,内部可以在编译时选择多种工作模式。
5.type_instance
namespace opencascade {template <typename T>class type_instance {static Handle(Standard_Type) myInstance;public:static const Handle(Standard_Type)& get ();};template <>class type_instance<void> {public:static Handle(Standard_Type) get () { return 0; }};template <typename T>const Handle(Standard_Type)& type_instance<T>::get () {static Handle(Standard_Type) anInstance = Standard_Type::Register (typeid(T), T::get_type_name(), sizeof(T), type_instance<typename T::base_type>::get());return anInstance;}
}
提供接口用于向自定义RTTI进行注册和获得注册结果。支持自定义RTTI机制的类其基类也需支持自定义RTTI机制。Standard_Transient是opencascade源码中支持自定义RTTI最开始的类型。
6.Standard_Type
class Standard_Type : public Standard_Transient {
public:// 返回类型对象的系统名称Standard_CString SystemName() const { return myInfo.name(); }// 返回类型对象的自定义名称Standard_CString Name() const { return myName; }// 返回类型对象实例占据的内存尺寸Standard_Size Size() const { return mySize; }// 用于返回当前类型的父类型(基类)信息/*使用实例:Handle(Standard_Type) currentType = STANDARD_TYPE(Geom2d_TrimmedCurve);while (!currentType.IsNull()) {std::cout << "Type: " << currentType->Name() << std::endl;currentType = currentType->Parent(); // 获取父类类型}*/const Handle(Standard_Type)& Parent () const { return myParent; }// 当theOther就是自身或自身的某个父类时返回trueStandard_EXPORT Standard_Boolean SubType (const Handle(Standard_Type)& theOther) const{return ! theOther.IsNull() && (theOther == this || (! myParent.IsNull() && myParent->SubType (theOther)));}// 当theOther就是自身或自身的某个父类时返回trueStandard_EXPORT Standard_Boolean SubType (const Standard_CString theOther) const{return theName != 0 && (IsEqual (myName, theName) || (! myParent.IsNull() && myParent->SubType (theName)));}/*首次调用时会完成注册行为*/template <class T>static const Handle(Standard_Type)& Instance() {return opencascade::type_instance<T>::get();}Standard_EXPORT static Standard_Type* Register (const std::type_info& theInfo, const char* theName, Standard_Size theSize, const Handle(Standard_Type)& theParent){static Standard_Mutex theMutex;Standard_Mutex::Sentry aSentry (theMutex);registry_type& aRegistry = GetRegistry();Standard_Type* aType = 0;auto anIter = aRegistry.find(theInfo);if (anIter != aRegistry.end())return anIter->second;aType = new Standard_Type (theInfo, theName, theSize, theParent);aRegistry.emplace(theInfo, aType);return aType;}Standard_EXPORT ~Standard_Type (){registry_type& aRegistry = GetRegistry();Standard_ASSERT(aRegistry.erase(myInfo) > 0, "Standard_Type::~Standard_Type() cannot find itself in registry",);}DEFINE_STANDARD_RTTIEXT(Standard_Type,Standard_Transient)
private:Standard_Type (const std::type_info& theInfo, const char* theName, Standard_Size theSize, const Handle(Standard_Type)& theParent): myInfo(theInfo), myName(theName), mySize(theSize), myParent(theParent){}
private:std::type_index myInfo; //!< Object to store system name of the classStandard_CString myName; //!< Given name of the classStandard_Size mySize; //!< Size of the class instance, in bytesHandle(Standard_Type) myParent; //!< Type descriptor of parent class
};
其中:
namespace {typedef std::unordered_map<std::type_index, Standard_Type*> registry_type;registry_type& GetRegistry() {static registry_type theRegistry;return theRegistry;}
}
通过以上分析可知Standard_Type用于为向其注册的类型分配一个Standard_Type实例,用于实现此类型的自定义类型识别,通过注册方式为类型起名字,记录类型的父类信息。
7.DEFINE_STANDARD_RTTIEXT
#define DEFINE_STANDARD_RTTIEXT(Class,Base) \
public: \typedef Base base_type; \static const char* get_type_name () { return #Class; OCCT_CHECK_BASE_CLASS(Class,Base) } \Standard_EXPORT static const Handle(Standard_Type)& get_type_descriptor (); \Standard_EXPORT virtual const Handle(Standard_Type)& DynamicType() const Standard_OVERRIDE;#define IMPLEMENT_STANDARD_RTTIEXT(Class,Base) \const Handle(Standard_Type)& Class::get_type_descriptor () { return Standard_Type::Instance<Class>(); } \const Handle(Standard_Type)& Class::DynamicType() const { return STANDARD_TYPE(Class); }#define STANDARD_TYPE(theType) theType::get_type_descriptor()
自定义类型通过在声明时加入DEFINE_STANDARD_RTTIEXT,在实现源代码文件中加入IMPLEMENT_STANDARD_RTTIEXT,即可提供向自定义RTTI机制注册并获得注册结果的接口,从而为该类型获得自定义RTTI机制的支持。
#define STANDARD_TYPE(theType) theType::get_type_descriptor()
#define DEFINE_STANDARD_RTTI_INLINE(Class,Base) \
public: \typedef Base base_type; \static const char* get_type_name () { return #Class; OCCT_CHECK_BASE_CLASS(Class,Base) } \static const Handle(Standard_Type)& get_type_descriptor () { return Standard_Type::Instance<Class>(); } \virtual const Handle(Standard_Type)& DynamicType() const Standard_OVERRIDE { return get_type_descriptor (); }
DEFINE_STANDARD_RTTI_INLINE提供了无Standard_EXPORT的版本。STANDARD_TYPE用于快捷获得类型的Handle(Standard_Type),Standard_Type用于包含此类型的自定义RTTI信息。
8.DEFINE_STANDARD_ALLOC
# define DEFINE_STANDARD_ALLOC_ARRAY \void* operator new[] (size_t theSize) \{ \return Standard::Allocate (theSize); \} \void operator delete[] (void* theAddress) \{ \Standard::Free (theAddress); \}# define DEFINE_STANDARD_ALLOC_PLACEMENT \void* operator new (size_t, void* theAddress) \{ \return theAddress; \} \void operator delete (void*, void*) \{ \}# define DEFINE_STANDARD_ALLOC \void* operator new (size_t theSize) \{ \return Standard::Allocate (theSize); \} \void operator delete (void* theAddress) \{ \Standard::Free (theAddress); \} \DEFINE_STANDARD_ALLOC_ARRAY \DEFINE_STANDARD_ALLOC_PLACEMENT
DEFINE_STANDARD_ALLOC用于为自定义类型提供由opencascade提供的统一的内存分配机制。使得该类型的new/delete区别与c++中的默认行为。
1.Placement new 允许在已分配的内存地址上构造对象(不分配新内存,直接使用给定的指针 theAddress
)。
意义:
- 用于内存池、自定义内存管理或需要精确控制对象内存位置的场景(如硬件寄存器映射)。
- 通常与
new (address) ClassName()
语法配合使用。
2.placement delete
与 placement new 配对,用于在对象构造失败时释放资源(但实际极少使用)。
- 如果 placement new 后的构造函数抛出异常,编译器会自动调用此版本的
operator delete
来清理。 - 如果构造函数成功,此函数不会被调用(需手动调用析构函数,如
p->~ClassName()
)。
使用例子:
#include <stdio.h>
#include <iostream>
class A {
public:A() {printf("A()\n");}A(int ) {printf("A(int)\n");}~A() {printf("~A()\n");}void* operator new[] (size_t theSize) { printf("new[]\n");return malloc (theSize); } void operator delete[] (void* theAddress) { printf("delete[]\n");free (theAddress);}void* operator new (size_t, void* theAddress) { printf("placement new\n");return theAddress; } void operator delete (void*, void*) { printf("placement delete\n");}void* operator new (size_t theSize) {printf("new\n");return malloc (theSize);} void operator delete (void* theAddress) { printf("delete\n");free (theAddress); }};int main() {printf("hello world\n");A* lpA = new A();delete lpA;lpA = new A(10);delete lpA;char buffer[sizeof(A)]; A* p = new (buffer) A(); p->~A(); p = new (buffer) A(10); p->~A(); int n;scanf_s("%d", &n);return 0;
}
这个例子中placement new/delete没啥实际作用,可用于new (buffer) A(xxx); 语法下额外执行此函数用于记录日志和统计。
9.DEFINE_NCOLLECTION_ALLOC
# define DEFINE_NCOLLECTION_ALLOC \void* operator new (size_t theSize, \const Handle(NCollection_BaseAllocator)& theAllocator) \{ \return theAllocator->Allocate(theSize); \} \void operator delete (void* theAddress, \const Handle(NCollection_BaseAllocator)& theAllocator) \{ \theAllocator->Free(theAddress); \}