【问题标题】:Custom std::allocator for classes with replaced operator new具有替换运算符 new 的类的自定义 std::allocator
【发布时间】:2014-11-13 04:22:22
【问题描述】:

我最近用使用 SSE 的类替换了一些 Vector/Matrix 类,现在正在确保内存正确对齐。

按照this question 的回答中的建议,我已将 operator new/delete 替换为需要它的类,并开始使用自定义分配器与 STL 容器一起使用 - 但是,似乎存在一些冲突两者之间:

首先,我只是从here 复制并粘贴了示例分配器类,当我将它与相关类型的 std::vector 一起使用时,它编译得很好,而没有我的自定义 new/delete,但是当我替换了这些函数,我从construct()函数中得到一个错误“没有匹配函数调用'operator new'”,

void    construct(pointer p, const T& t)    { new(p) T(t); }

我猜我已经替换了“通常的”新的事实以某种方式掩盖了新的位置?但是,鉴于我无法编写自己的新位置来获取它,我不确定该怎么做......我是整个自定义内存分配的新手(NPI),所以任何建议都会不胜感激!

我正在使用 Clang v3.4(或 gcc 4.1.2)在 Linux 上进行编译;不使用 C++11。

非常感谢。

【问题讨论】:

    标签: c++ stl new-operator allocator placement-new


    【解决方案1】:

    规范的allocator::construct 调用::new((void *)p) T(val)

    通过省略::,您让名称查找从T 的类范围开始,它找到了您的类范围operator new 并且没有继续进行(name lookup 在第一个停止找到任何匹配名称的范围,即使某个封闭范围中存在更好的候选者)

    (强制转换为 void 是为了防止用户潜入全局几乎放置的新重载,该重载采用非 void 指针参数)

    PS:正如 cmets 中正确指出的那样,“鉴于我无法编写自己的新位置”是错误的假设。你不能替换一个全局的placement-new,但是你当然可以写一个类特定的placement new,然后它会被class-scope lookup 拾取。查看cppreference 了解分配函数的摘要。

    【讨论】:

    • 要解决此问题,::new为您的班级实施覆盖的布置new
    • 啊,是的,这很有道理...谢谢!出于某种原因,我完全错过了关于 ccpreference 的注释指出这一点:“即使不能替换放置新(重载 5 和 6),也可以在类范围内定义具有相同签名的函数,如上所述”......哎呀.
    【解决方案2】:

    我建议使用 Boost 的 aligned_allocator:

    #include <boost/align/aligned_allocator.hpp>
    #include <immintrin.h>
    #include <vector>
    
    struct m128i {
        // FIXME: ctors/opers with intrinsics would be nice (required?)
        __m128i data;
    }
    
    int main()
    {
        std::vector<m128i, boost::alignment::aligned_allocator<m128i, 16> > v;
        v.emplace_back();
    }
    

    注意:我已对此进行了更新,以使用包装内在成员的结构。有很多图书馆可以做到这一点。这样做的原因很简单:vector_size 属性是 __m128i 与 __m256i 和 __m512i 的区别,模板忽略类型属性,所以我相信它们最终都会使用相同的扩展,即“long long”(或 float/double在非 i 和 d 类型的情况下)。

    【讨论】:

      【解决方案3】:

      我将使用我的起点作为此处给出的分配器:http://en.cppreference.com/w/cpp/concept/Allocator。这实际上是一个最小的分配器。特别是,您根本不需要写constructallocator_traits,如果它没有发现你的分配器有一个construct 方法,它将简单地为你调用placement new,正确地使用::(如Cubbi 注释)来确定调用的范围,所以你没有这个问题:@ 987654322@.

      我可能根本不会编写自定义的新建/删除。只需编写一个自定义分配器就足够了,并让您的 Vector/Matrix 类使用您的自定义分配器通过 std::vector 管理它们的数据。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-11
        • 1970-01-01
        • 2017-02-18
        • 1970-01-01
        • 2011-03-31
        • 1970-01-01
        • 1970-01-01
        • 2023-03-04
        相关资源
        最近更新 更多