背景
我正在使用英特尔 IPP 加密库进行测试。
他们定义了几个用于共享上下文的不透明结构,例如散列和加密,当然,这些结构不能直接实例化。
要初始化这些不透明结构之一,您查询字节大小,然后动态分配一些字节并转换为结构指针。
他们的例子是这样的:
int byteSize = 0;
ippsSHA256GetSize(&byteSize);
// IppsSHA256State shaCtx; // Error: incomplete type is not allowed
IppsSHA256State * shaCtx = (IppsSHA256State *)(new uint8_t[byteSize]);
// use shaCtx
delete [] (uint8_t *)shaCtx;
问题
将它包装在作用域指针类中的正确方法是什么,这样我就不必担心释放了?
我尝试过的事情
我认为以下内容不安全,因为在析构函数中对delete的调用将在 T 类型上,而不是在实际分配的数组上的delete [] :
boost::scoped_ptr<IppsSHA256State> ctx(
reinterpret_cast<IppsSHA256State *>(new uint8_t[byteSize])
);
我考虑过的另一个(简化的)选项是我自己的一个简单的作用域指针类,但是那里的转换让我不确定这是否正确,尽管我对reinterpret_cast的理解是,当转换回原始类型时,不应该有任何歧义:
template <typename T>
class IppsScopedState
{
public:
explicit IppsScopedState(size_t byteSize)
: _ptr(reinterpret_cast<T *>(new uint8_t[byteSize]))
{}
T * get() const { return _ptr; }
~IppsScopedState(void) {
if (_ptr) delete [] reinterpret_cast<uint8_t *>(_ptr);
}
private:
T * _ptr;
//NUKE_COPYASSIGN_CONSTRUCTORS
};
最后,我考虑了上述内容的轻微变化:
template <typename T>
class IppsScopedState
{
public:
explicit IppsScopedState(size_t byteSize)
: _ptr(new uint8_t[byteSize])
{}
T * get() const { return reinterpret_cast<T *>(_ptr); }
~IppsScopedState(void) {
if (_ptr) delete [] _ptr;
}
private:
uint8_t * _ptr;
//NUKE_COPYASSIGN_CONSTRUCTORS
};
在任何一种情况下,用法都是这样的:
IppsScopedState<IppsSHA256State> ctx(byteSize); // after querying for the byteSize, of course