如何使用 placement new 确定对象是否已放置
How to determine if object has been placed using placement new
使用 placement new 语法,我应该可以做这样的事情:
char *buffer = new char[sizeof(MyClass)]; //pre-allocated buffer
MyClass *my_class = new (buffer) MyClass; //put da class there
现在假设我只做第一行,而不做第二行。有没有一种方法可以在代码中确定是否已正确分配缓冲区,但那里尚未实例化 MyClass 类型的对象?
该语言没有提供任何内置机制来提供该信息,至少 none 据我所知是这样。您必须添加自己的簿记代码来跟踪此类信息。
您可以维护一个 static
table 的 this
指针值,您可以在构造函数和析构函数中将其变异为 MyClass
。然后在需要时根据 buffer
的特定值检查它。
不要忘记考虑移动语义的影响。做对会很棘手。
出于调试目的,您可以将特殊成员 signature
添加到 MyClass
并将其值设置为常量
class MyClass {
public:
MyClass() : signature(762347562374) {}
bool isValidSignature() const { return signature==762347562374; }
private:
unsigned long long signature;
<other members>
};
然后,检查如下:
char *buffer = new char[sizeof(MyClass)]; //pre-allocated buffer
MyClass *my_class = new (buffer) MyClass; //put da class there
if (my_class->isValidSignature())
<this means that the object has been allocated correctly, with a high probability>
}
您可以将与签名相关的所有内容放在适当的 #ifdef
中,这样它只会在调试模式下运行。
不是没有自己跟踪它。
一个解决方案是围绕 std::allocator 创建一个包装器。
template<class T>
class MyAllocator
{
public:
T* allocate(std::size_t count = 1)
{
return allocator_.allocate(count);
}
template<class... Args>
void construct(T* ptr, Args&&... args)
{
allocator_.construct(ptr, std::forward<Args>(args)...);
allocated_ = true;
}
bool IsAllocated() const
{
return allocated_;
}
private:
std::allocator<T> allocator_;
bool allocated_;
};
原代码:
char *buffer = new char[sizeof(MyClass)]; //pre-allocated buffer
MyClass *my_class = new (buffer) MyClass; //put da class there
要动态地确定 放置new
是否已执行,有关它的信息必须存储在某处。该语言不提供该服务。所以你必须自己做,主要有两种可能的方式之一:
- 正在缓冲区中存储信息。
对于这种情况,缓冲区必须在分配时初始化。例如。只需在 new
表达式的末尾添加 ()
即可。否则无法保证缓冲区内容看起来不像一个对象。两个子案例:
- 通过在缓冲区中为标志添加空间。
- 通过将标志作为对象的成员。
在多态 class 的情况下,实际上会有一个非零 vtable 指针,可以用作标志。
- 在外部存储信息。
对于这种情况,缓冲区不需要在分配时初始化。有无数种可能性,包括
- 一个简单的
bool
变量。
- 指向所有此类对象的指针集合。
- 向黑猩猩发出的声音信号,稍后会对其进行查询。
使用 placement new 语法,我应该可以做这样的事情:
char *buffer = new char[sizeof(MyClass)]; //pre-allocated buffer
MyClass *my_class = new (buffer) MyClass; //put da class there
现在假设我只做第一行,而不做第二行。有没有一种方法可以在代码中确定是否已正确分配缓冲区,但那里尚未实例化 MyClass 类型的对象?
该语言没有提供任何内置机制来提供该信息,至少 none 据我所知是这样。您必须添加自己的簿记代码来跟踪此类信息。
您可以维护一个 static
table 的 this
指针值,您可以在构造函数和析构函数中将其变异为 MyClass
。然后在需要时根据 buffer
的特定值检查它。
不要忘记考虑移动语义的影响。做对会很棘手。
出于调试目的,您可以将特殊成员 signature
添加到 MyClass
并将其值设置为常量
class MyClass {
public:
MyClass() : signature(762347562374) {}
bool isValidSignature() const { return signature==762347562374; }
private:
unsigned long long signature;
<other members>
};
然后,检查如下:
char *buffer = new char[sizeof(MyClass)]; //pre-allocated buffer
MyClass *my_class = new (buffer) MyClass; //put da class there
if (my_class->isValidSignature())
<this means that the object has been allocated correctly, with a high probability>
}
您可以将与签名相关的所有内容放在适当的 #ifdef
中,这样它只会在调试模式下运行。
不是没有自己跟踪它。
一个解决方案是围绕 std::allocator 创建一个包装器。
template<class T>
class MyAllocator
{
public:
T* allocate(std::size_t count = 1)
{
return allocator_.allocate(count);
}
template<class... Args>
void construct(T* ptr, Args&&... args)
{
allocator_.construct(ptr, std::forward<Args>(args)...);
allocated_ = true;
}
bool IsAllocated() const
{
return allocated_;
}
private:
std::allocator<T> allocator_;
bool allocated_;
};
原代码:
char *buffer = new char[sizeof(MyClass)]; //pre-allocated buffer
MyClass *my_class = new (buffer) MyClass; //put da class there
要动态地确定 放置new
是否已执行,有关它的信息必须存储在某处。该语言不提供该服务。所以你必须自己做,主要有两种可能的方式之一:
- 正在缓冲区中存储信息。
对于这种情况,缓冲区必须在分配时初始化。例如。只需在new
表达式的末尾添加()
即可。否则无法保证缓冲区内容看起来不像一个对象。两个子案例:- 通过在缓冲区中为标志添加空间。
- 通过将标志作为对象的成员。
在多态 class 的情况下,实际上会有一个非零 vtable 指针,可以用作标志。
- 在外部存储信息。
对于这种情况,缓冲区不需要在分配时初始化。有无数种可能性,包括- 一个简单的
bool
变量。 - 指向所有此类对象的指针集合。
- 向黑猩猩发出的声音信号,稍后会对其进行查询。
- 一个简单的