对齐动态数组和智能指针

时间:2015-04-02 09:57:12

标签: c++ c++11 unique-ptr memory-alignment

我经常需要将动态数组的开头与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);
    }
};

我想做这样的事情

std::unique_ptr<float[]> data(allocate_aligned<float>(alignment, length));

但我无法弄清楚如何让unique_ptr使用正确的Deleter而无需用户指定它(这可能是导致错误的原因)。我找到的替代方法是使用模板别名

template<class T>
using aligned_unique_ptr = std::unique_ptr<T[], DeleteAligned<T>>;

然后我们可以使用

aligned_unique_ptr<float> data(allocate_aligned<float>(alignment, length));

剩下的问题是没有任何东西阻止用户将原始指针放入std::unique_ptr

除此之外,你觉得这有什么问题吗?是否存在一种不易出错的替代方案,但在完成分配后对用户完全透明?

1 个答案:

答案 0 :(得分: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};
}

这样,没有客户端可以将原始指针放入不合适的智能指针中,因为它们从不首先得到原始指针。并且你可以防止内存泄漏意外地将原始指针放在一个聪明的指针中。

正如@KonradRudolph指出的那样,标准本身就是这样 - 在C ++ 14中,std::make_unique正是普通new的包装。

相关问题