Sim*_*mon 12 c++ memory-alignment unique-ptr c++11
我经常需要将动态数组的开头与用于矢量化的16,32或64字节边界对齐,例如,对于SSE,AVX,AVX-512.我正在寻找一种透明和安全的方式,特别是与智能指针一起使用它std::unique_ptr.
比如分配和释放例程的实现
template<class T>
T * allocate_aligned(int alignment, int length)
{
// omitted: check minimum alignment, check error
T * raw = 0;
// using posix_memalign as an example, could be made platform dependent...
int error = posix_memalign((void **)&raw, alignment, sizeof(T)*length);
return raw;
}
template<class T>
struct DeleteAligned
{
void operator()(T * data) const
{
free(data);
}
};
Run Code Online (Sandbox Code Playgroud)
我想做这样的事情
std::unique_ptr<float[]> data(allocate_aligned<float>(alignment, length));
Run Code Online (Sandbox Code Playgroud)
但我无法弄清楚如何unique_ptr使用正确Deleter而无需用户指定它(这是导致错误的潜在原因).我找到的替代方法是使用模板别名
template<class T>
using aligned_unique_ptr = std::unique_ptr<T[], DeleteAligned<T>>;
Run Code Online (Sandbox Code Playgroud)
然后我们可以使用
aligned_unique_ptr<float> data(allocate_aligned<float>(alignment, length));
Run Code Online (Sandbox Code Playgroud)
剩下的问题是没有任何东西阻止用户将原始指针放入std::unique_ptr.
除此之外,你觉得这有什么问题吗?是否存在一种不易出错的替代方案,但在完成分配后对用户完全透明?
Rei*_*ica 10
你永远不应该返回拥有原始指针.allocate_aligned违反了这一点.更改它以返回相应的智能指针:
template<class T>
std::unique_ptr<T[], DeleteAligned<T>> allocate_aligned(int alignment, int length)
{
// omitted: check minimum alignment, check error
T * raw = 0;
// using posix_memalign as an example, could be made platform dependent...
int error = posix_memalign((void **)&raw, alignment, sizeof(T)*length);
return std::unique_ptr<T[], DeleteAligned<T>>{raw};
}
Run Code Online (Sandbox Code Playgroud)
这样,没有客户端可以将原始指针放入不合适的智能指针中,因为它们从不首先获得原始指针.并且您可以防止内存泄漏意外地将原始指针放在智能指针中.
正如@KonradRudolph指出的那样,标准本身就是这样 - 在C++ 14中,std::make_unique正是这样的普通包装new.