C++ 如何在作用域指针类中正确使用动态分配的不透明指针? 背景
我正在使用英特尔IPP加密库进行测试 它们定义了几个不透明结构,用于共享上下文,当然不能直接实例化哈希和加密等内容 要初始化其中一个不透明结构,需要查询字节大小,然后动态分配一些字节并强制转换到结构指针 他们的例子是这样的:C++ 如何在作用域指针类中正确使用动态分配的不透明指针? 背景,c++,casting,smart-pointers,opaque-pointers,C++,Casting,Smart Pointers,Opaque Pointers,我正在使用英特尔IPP加密库进行测试 它们定义了几个不透明结构,用于共享上下文,当然不能直接实例化哈希和加密等内容 要初始化其中一个不透明结构,需要查询字节大小,然后动态分配一些字节并强制转换到结构指针 他们的例子是这样的: int byteSize = 0; ippsSHA256GetSize(&byteSize); // IppsSHA256State shaCtx; // Error: incomplete type is not allowed IppsSHA256State
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;
IppsScopedState<IppsSHA256State> ctx(byteSize); // after querying for the byteSize, of course
问题: 用什么合适的方法将其包装在一个作用域指针类中,这样我就不必担心释放问题了?
我尝试过的事情 我认为以下操作不安全,因为析构函数中对delete的调用将在T类型上,而不是在实际分配的数组上调用delete[]:
boost::scoped_ptr<IppsSHA256State> ctx(
reinterpret_cast<IppsSHA256State *>(new uint8_t[byteSize])
);
boost::有范围的\u ptr ctx(
重新解释铸件(新的uint8[byteSize])
);
我考虑过的另一个(简化的)选项是我自己的一个简单的作用域指针类,但是这里的强制转换让我不确定这是否正确,尽管我对重新解释强制转换的理解是,当强制转换回原始类型时,不应该有任何歧义:
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
};
模板
IPPScopedState类
{
公众:
显式IPPScopedState(大小字节大小)
:_ptr(重新解释演员阵容(新单元8_t[byteSize]))
{}
T*get()常量{return\u ptr;}
~IPPScopedState(无效){
如果(_ptr)删除[]重新解释投射(_ptr);
}
私人:
T*_ptr;
//NUKE_COPYASSIGN_构造函数
};
最后,我考虑了上面的一点变化:
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
};
模板
IPPScopedState类
{
公众:
显式IPPScopedState(大小字节大小)
:\u ptr(新单元8\u t[byteSize])
{}
T*get()常量{return reinterpret_cast(_ptr);}
~IPPScopedState(无效){
如果(_ptr)删除[]_ptr;
}
私人:
uint8_t*_ptr;
//NUKE_COPYASSIGN_构造函数
};
在这两种情况下,用法如下:
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;
IppsScopedState<IppsSHA256State> ctx(byteSize); // after querying for the byteSize, of course
IPPScopedState ctx(字节大小);//当然,在查询byteSize之后
您可以使用boost::scoped_array
或只使用std::vector
您认为这是正确的:
boost::scoped_ptr<IppsSHA256State> ctx(
reinterpret_cast<IppsSHA256State *>(new uint8_t[byteSize])
);
但这会给您两个局部变量,您必须记住,在使用temparray
之后,不要保留shaCtx
。所以,滚动你自己的包装是一个非常吸引人的选择,因为它给了你安全感
您当前的ippscopedstate
很好,但我建议稍微调整一下,以便在内部使用boost::scoped_数组,添加操作符->
访问器和常量访问:
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
};
模板
IPPScopedState类
{
公众:
显式IPPScopedState(大小字节大小)
:\u ptr(新单元8\u t[byteSize])
{}
常量T*运算符->()常量{return get();}
T*运算符->(){return get();}
const T*get()const{return reinterpret_cast(_ptr.get());}
T*get(){return reinterpret_cast(_ptr.get());}
私人:
boost::作用域_数组_ptr;
//NUKE_COPYASSIGN_构造函数
};
然后,您可以轻松使用此包装:
IppsScopedState<IppsSHA256State> shaCtx (byteSize);
shaCtx->member; // access any member of IppsSHA256State
some_function(shaCtx.get()); // pass the IppsSHA256State* to a method
ippscopedstate shaCtx(字节大小);
shaCtx->member;//访问IppsSHA256State的任何成员
一些_函数(shaCtx.get());//将IppsSHA256State*传递给方法
根据您的需要,操作符->
和constget()
可能会过度使用,而且不必要
因此,最后,我建议您使用自定义包装器,并在旧的c样式转换语法上使用reinterpret_cast。感谢您在我的文章中提出这些要点。由于这些英特尔加密结构是不透明的,它们都没有任何可访问的成员,因此我不需要
运算符->
。因为这是我的第一个问题,所以我不能对你的答案投赞成票,但在做了一些简短的测试之后,我会接受它。