使用带有rvalue的条件运算符时,采用const pmr :: vector <>&不传播分配器

拉蒙
#include <iostream>
#include <vector>
#include <memory_resource>

class SpecialMemoryResource : public std::pmr::memory_resource
{
public:
    void* do_allocate(std::size_t bytes, std::size_t alignment) override  { return nullptr; }
    void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) override {}

    bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override {
        return &other == this;
    }
};

static auto k_SpecialMemoryResource = SpecialMemoryResource{};

bool isUsingSpecialMemoryResource(const std::pmr::vector<int>& vec) {
    const bool usingSpecial{vec.get_allocator().resource() == &k_SpecialMemoryResource};
    std::cout << std::boolalpha << usingSpecial << std::endl;
    return usingSpecial;
}

void Func(const std::pmr::vector<int>& vec) {
    const bool LHS = true, RHS = false;
    const std::pmr::vector<int>& localLValRef{std::pmr::vector<int>{&k_SpecialMemoryResource}};

    isUsingSpecialMemoryResource(LHS? vec : localLValRef);
    isUsingSpecialMemoryResource(RHS? vec : localLValRef);
    isUsingSpecialMemoryResource(LHS? vec : std::pmr::vector<int>{&k_SpecialMemoryResource});
    isUsingSpecialMemoryResource(RHS? vec : std::pmr::vector<int>{&k_SpecialMemoryResource});
}

int main() {
    const auto specialVec = std::pmr::vector<int>{&k_SpecialMemoryResource};
    Func(specialVec);
}

运行上面的代码将导致:

true
true
false
true

为什么在第三种情况下不传播polymorphic_allocatormemory_resource我在这里的期望是,我只是绑定引用,而不构造/转换任何对象std::pmr::vector,因此我认为任何原因都不会改变。但是,我是否在条件运算符的类型推导中缺少某些内容,这些内容触发了不传播分配器std::pmr::vector 副本构造

  1. 复制构造函数。用other的内容的副本构造容器,就像通过调用获得分配器一样std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.get_allocator()).

或者是其他东西?我不确定发生了什么,并且发现条件运算符的类型推导文档难以解析。

我正在使用clang10进行编译-std=c++20

clang version 10.0.0-4ubuntu1 
Target: x86_64-pc-linux-gnu
Thread model: posix
伊戈尔·坦德尼克(Igor Tandetnik)

true ? vec : std::pmr::vector<int>{&k_SpecialMemoryResource}确实创建了一个临时对象,该对象是从复制初始化的vec

[expr.cond] / 2如果第二个或第三个操作数的类型为void... [不适用]
3否则,如果第二个和第三个操作数为glvalue位字段... [不适用]
4否则,如果第二和第三操作数具有不同的类型...或两者都是glvalues ... [不适用]
5如果第二和第三操作数是glvalues ... [不适用]

[expr.cond] / 6否则,结果为prvalue ...
[expr.cond] / 7 Lvalue -to-rvalue ...对第二个和第三个操作数执行标准转换。进行这些转换之后,应满足下列条件之一:
(7.1)—第二和第三操作数具有相同的类型;结果是该类型的结果,并且使用所选操作数初始化结果对象。

因此,对进行左值到右值转换vec

[conv.lval] / 3转换的结果是根据以下规则确定的:
(3.2)—否则,如果T具有类类型,则转换会从glvalue复制初始化结果对象。


现在,我们必须查看的副本构造函数的行为std::pmr::vector<T>,它是的别名std::vector<T, std::pmr::polymorphic_allocator<T>>事实证明,副本获得了一个默认构造的分配器。内存资源不传播。您观察到的是什么。

[container.requirements.general] / 8除非另有说明,否则本节中定义的所有容器都使用分配器获取内存...这些容器类型的复制构造函数通过调用allocator_traits<allocator_type>::select_on_container_copy_construction属于要复制的容器的分配器来获取分配器

[allocator.traits.members] / 8 static Alloc select_on_container_copy_construction(const Alloc& rhs);
返回: rhs.select_on_container_copy_construction()如果该表达式格式正确;则返回0否则,rhs

[mem.poly.allocator.mem] / 15 polymorphic_allocator select_on_container_copy_construction() const;
返回: polymorphic_allocator()
16 [注意:不传播内存资源。—尾注]

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

分配器如何与std :: vector一起使用?

来自分类Dev

可以使用哪些方法在std :: vector和pmr :: vector容器之间创建接口?

来自分类Dev

在C ++ 20中,为什么有std :: vector运算符==不适用于具有不同分配器的向量?

来自分类Dev

具有自定义内存分配器的std :: vector的C ++模板

来自分类Dev

D不推荐使用的类分配器

来自分类Dev

带自定义类的范围循环(vector <string>的简单版本,使用分配器)

来自分类Dev

使用自定义的总体分配器来利用std :: vector末尾的内存

来自分类Dev

更改std :: vector的分配器时,为什么初始化器列表不可用?

来自分类Dev

复制有状态分配器:标准库分配器语义和内部内存

来自分类Dev

使用带有分配器的std :: unique_ptr

来自分类Dev

带有红黑树的免费列表分配器

来自分类Dev

视图分配器时如何删除导航子视图?

来自分类Dev

具有自定义分配器的std :: string

来自分类Dev

有关自定义分配器的问题

来自分类Dev

没有指针算法的自定义分配器

来自分类Dev

如何使用Box2D分配器?

来自分类Dev

在自定义容器类中使用分配器

来自分类Dev

我可以将变量分配器与if结合使用吗?

来自分类Dev

在分配器中使用boost :: lockfree :: spsc_queue

来自分类Dev

使用自定义分配器调整大小

来自分类Dev

在自定义容器类中使用分配器

来自分类Dev

当知道分配器的容器被复制/移动时,反弹分配器是否被复制/移动?

来自分类Dev

具有自定义分配器/本地分配器的std :: unordered_map无法编译

来自分类Dev

如果分配器提供了重新分配语义,std :: vector是否可以避免复制?

来自分类Dev

如果分配器提供了重新分配语义,std :: vector是否可以避免复制?

来自分类Dev

传播带有对象的运算符

来自分类Dev

从带有一个分配器的向量移动到带有另一个分配器的向量

来自分类Dev

是否有标准的memory_resource分配器适配器/包装器?

来自分类Dev

如果构造并销毁了许多vector <T>,那么自定义分配器会提高性能吗?

Related 相关文章

  1. 1

    分配器如何与std :: vector一起使用?

  2. 2

    可以使用哪些方法在std :: vector和pmr :: vector容器之间创建接口?

  3. 3

    在C ++ 20中,为什么有std :: vector运算符==不适用于具有不同分配器的向量?

  4. 4

    具有自定义内存分配器的std :: vector的C ++模板

  5. 5

    D不推荐使用的类分配器

  6. 6

    带自定义类的范围循环(vector <string>的简单版本,使用分配器)

  7. 7

    使用自定义的总体分配器来利用std :: vector末尾的内存

  8. 8

    更改std :: vector的分配器时,为什么初始化器列表不可用?

  9. 9

    复制有状态分配器:标准库分配器语义和内部内存

  10. 10

    使用带有分配器的std :: unique_ptr

  11. 11

    带有红黑树的免费列表分配器

  12. 12

    视图分配器时如何删除导航子视图?

  13. 13

    具有自定义分配器的std :: string

  14. 14

    有关自定义分配器的问题

  15. 15

    没有指针算法的自定义分配器

  16. 16

    如何使用Box2D分配器?

  17. 17

    在自定义容器类中使用分配器

  18. 18

    我可以将变量分配器与if结合使用吗?

  19. 19

    在分配器中使用boost :: lockfree :: spsc_queue

  20. 20

    使用自定义分配器调整大小

  21. 21

    在自定义容器类中使用分配器

  22. 22

    当知道分配器的容器被复制/移动时,反弹分配器是否被复制/移动?

  23. 23

    具有自定义分配器/本地分配器的std :: unordered_map无法编译

  24. 24

    如果分配器提供了重新分配语义,std :: vector是否可以避免复制?

  25. 25

    如果分配器提供了重新分配语义,std :: vector是否可以避免复制?

  26. 26

    传播带有对象的运算符

  27. 27

    从带有一个分配器的向量移动到带有另一个分配器的向量

  28. 28

    是否有标准的memory_resource分配器适配器/包装器?

  29. 29

    如果构造并销毁了许多vector <T>,那么自定义分配器会提高性能吗?

热门标签

归档