我正在使用英特尔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;
在scoped指针类中包装它的正确方法是什么,以便我不必担心重新分配?
我认为以下内容不安全,因为析构函数中对 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
答案 0 :(得分:0)
您可以使用boost::scoped_array
或std::vector
。
答案 1 :(得分:0)
你是对的:
boost::scoped_ptr<IppsSHA256State> ctx(
reinterpret_cast<IppsSHA256State *>(new uint8_t[byteSize])
);
这是一个坏主意,原因有两个:delete
将被调用而不是delete[]
,它将删除错误的类型。
boost::scoped_array
应该可以正常工作:
boost::scoped_array<uint8_t> temparray (new uint8_t[byteSize]);
IppsSHA256State * shaCtx = (IppsSHA256State *)(temparray.get());
但是这会给你两个局部变量,你必须记住在完成shaCtx
之后不要保持temparray
。因此,滚动自己的包装器是一个非常有吸引力的选择,因为它为您提供了安全性。
您当前的IppsScopedState
没问题,但我建议稍微调整一下,在内部使用boost :: scoped_array,添加operator->
访问器和const访问:
template <typename T>
class IppsScopedState
{
public:
explicit IppsScopedState(size_t byteSize)
: _ptr(new uint8_t[byteSize])
{}
const T* operator->() const { return get(); }
T* operator->() { return get(); }
const T* get() const { return reinterpret_cast<const T*> (_ptr.get()); }
T* get() { return reinterpret_cast<T*>(_ptr.get()); }
private:
boost::scoped_array<uint8_t> _ptr;
//NUKE_COPYASSIGN_CONSTRUCTORS
};
然后您可以轻松使用此包装器:
IppsScopedState<IppsSHA256State> shaCtx (byteSize);
shaCtx->member; // access any member of IppsSHA256State
some_function(shaCtx.get()); // pass the IppsSHA256State* to a method
根据您的需要,operator->
和const get()
可能过度且不必要。
所以,最后,我推荐你的自定义包装器,并使用reinterpret_cast而不是旧的c风格的转换语法。