当前位置: 首页 > wzjs >正文

创建网站快捷方式到桌面文创产品设计分析

创建网站快捷方式到桌面,文创产品设计分析,云主机玩游戏,龙岩建设网引问:vector 的第二个模板是 allocator,它会调用一个什么bind 之类的东西,是个什么概念? 在 C 标准库里,std::vector 模板的第二个参数确实是分配器(Allocator),它负责管理容器内部元…

引问:vector 的第二个模板是 allocator,它会调用一个什么bind 之类的东西,是个什么概念?

在 C++ 标准库里,std::vector 模板的第二个参数确实是分配器(Allocator),它负责管理容器内部元素内存的分配和释放。为了让同一个分配器类型能够为不同类型的对象分配内存(比如 vector 内部可能要给 T 以外的临时对象分配空间),标准定义了一个“重绑定”(rebind)机制。


Allocator::rebind

  1. 概念
    Allocator 是一个模板类,它只能直接分配类型 T 的内存。但在操作容器内部结构时(比如分配节点、维护内存池、构造/销毁元素),可能需要分配其他类型的内存(例如内部节点、控制块、对齐缓冲区等)。rebind 就是告诉编译器 “嘿,如果我有一个为 T 服务的分配器类型,怎么把它‘转换’成一个为 U 服务的分配器类型?”

  2. 典型定义
    在一个自定义分配器里,你可能会看到类似:

template<typename U>
struct rebind {using other = MyAllocator<U>;
};

这就声明:
给定 MyAllocator,如果想要一个 MyAllocator<U>,就通过 MyAllocator<T>::rebind<U>::other 拿到。

  1. 标准适配:allocator_traits

从 C++11 开始,标准引入了 std::allocator_traits,来统一分配器的接口。allocator_traits 会检查你的分配器类型是否定义了 rebind 嵌套模板,如果没有,则提供一个默认实现:

template<typename Alloc, typename U>
using rebinder = typename Alloc::template rebind<U>::other;

当容器需要为其他类型(如内部节点类型)分配内存时,就使用:

using NodeAlloc = typename std::allocator_traits<Allocator>::template rebind_alloc<NodeType>;

这里的 rebind_alloc 就是通过 rebind::other 或内部默认实现得到的。


在 std::vector 中的作用
• 分配元素数组
最直接的用途是为 T[] 分配内存,构造和析构 T。这是最常见的:vector<T, Alloc> 内部会用到 Alloc::allocate(n) 分配 n * sizeof(T) 字节。
• 分配内部控制结构
比如在某些实现里,vector 可能会分配额外的控制块或对齐缓冲区(通常不是用在 vector 上,但对 list、map 之类的节点容器就很常见)。
• 容器之间的拷贝/移动
当你从一个使用分配器 A1 的容器,拷贝到另一个使用分配器 A2 的容器时,如果 A1 和 A2 不是同类型,需要把 A1 重绑定到目标元素类型以便做内存复制。


小结
• rebind:分配器模板里的一个内部模板,用来“重绑定”到其他类型。
• allocator_traits:C++11+ 统一接口,检测或提供默认的 rebind 实现。
• 用途:让同一个分配器类型能在容器内部为多种类型分配内存,不仅仅是容器元素本身。

这样,无论你在容器内部需要分配的是 T、Node、还是一些内部对齐缓冲,这个机制都能让分配器“通吃”各种类型。


下面是一个简单的自定义分配器 MyAllocator,它满足 C++11 的分配器要求,并且实现了 rebind 功能。你可以用它来替换 std::allocator,例如:std::vector<int, MyAllocator>。

#include <cstddef>      // for std::size_t, std::ptrdiff_t
#include <memory>       // for std::allocator_traits
#include <new>          // for ::operator new, ::operator deletetemplate <typename T>
class MyAllocator {
public:using value_type = T;using pointer = T*;using const_pointer = const T*;using reference = T&;using const_reference = const T&;using size_type = std::size_t;using difference_type = std::ptrdiff_t;// 重绑定模板,用于为其他类型 U 分配内存template <typename U>struct rebind {using other = MyAllocator<U>;};MyAllocator() noexcept = default;// 拷贝构造允许从不同类型的 MyAllocator 复制template <typename U>MyAllocator(const MyAllocator<U>&) noexcept {}~MyAllocator() = default;// 分配 n 个 T 对象的原始内存pointer allocate(size_type n) {if (n == 0) return nullptr;// 简单地使用全局 operator newvoid* ptr = ::operator new(n * sizeof(T));return static_cast<pointer>(ptr);}// 释放从 allocate 分配的内存void deallocate(pointer p, size_type) noexcept {::operator delete(p);}// 在已分配的内存上原地构造对象template <typename U, typename... Args>void construct(U* p, Args&&... args) {::new ((void*)p) U(std::forward<Args>(args)...);}// 显式调用析构template <typename U>void destroy(U* p) {p->~U();}// 最大可分配对象数量(理论上)size_type max_size() const noexcept {return size_type(-1) / sizeof(T);}
};// 比较运算符:不同类型的 MyAllocator 总是相等的
template <typename T, typename U>
bool operator==(const MyAllocator<T>&, const MyAllocator<U>&) noexcept {return true;
}template <typename T, typename U>
bool operator!=(const MyAllocator<T>& a, const MyAllocator<U>& b) noexcept {return !(a == b);
}

说明:
1. value_type 等类型定义
标准要求分配器提供这些类型别名,以便 allocator_traits 能正确处理。
2. rebind 嵌套模板
用来将 MyAllocator<T> 变换为 MyAllocator<U>,容器内部需要为其他类型(如节点或缓冲区)分配时会用到。
3. allocate / deallocate
使用全局的 ::operator new 和 ::operator delete。在真实场景,你可以替换成自定义的内存池或对齐分配逻辑。
4. construct / destroy
在 C++17 及以前需要自定义,但从 C++20 起 allocator_traits 会使用 std::allocator_traits::construct,你可以省略这两个方法,让 allocator_traits 使用完美转发到 ::new。
5. 比较运算符
分配器之间相等意味着它们可以互换内存资源。在这里我们简单地认为所有 MyAllocator 实例都相等。

你可以像这样使用它:

#include <vector>
int main() {// 使用 MyAllocator 分配 vector 的内存std::vector<int, MyAllocator<int>> v;v.push_back(42);v.push_back(7);return 0;
}

这个示例展示了如何编写一个符合标准分配器接口、支持重绑定(rebind)的最简实现。


在 std::vector<T, Alloc> 的实现中,会通过 allocator_traits<Alloc>::rebind_alloc<U>(或直接用 Alloc::rebind<U>::other)来为不同用途分配内存。下面给出几个典型场景和简化示例,说明它们如何“引用”到 other:

  1. 分配元素数组

当你做 vector.reserve(n) 或第一次插入元素时,vector 需要为 n 个元素分配一片连续内存。它会这样写:

using AllocTraits = std::allocator_traits<Alloc>;
using TAlloc      = Alloc;                // 原始的元素分配器
using UAlloc      = AllocTraits::          // 重绑定到 Ttemplate rebind_alloc<T>;  // … 在成员函数里 …
UAlloc alloc = get_allocator();           // 拿到一个 T 分配器实例
pointer data = AllocTraits::allocate(     // 调用 allocate(n)alloc, static_cast<size_type>(n)
);

在 C++11 以前,等价于:

using UAlloc = typename Alloc::template rebind<T>::other;
UAlloc alloc = static_cast<const UAlloc&>(get_allocator());
pointer data = alloc.allocate(n);

这里的 rebind::other 就是 MyAllocator 或 std::allocator。


  1. 重新分配(grow)时的临时缓冲

当 vector 扩容(从旧容量 cap 增长到新容量 new_cap)时,会:

//	1.	先通过重绑定分配一块更大的内存:
UAlloc tmp_alloc = get_allocator();
T* new_buf = tmp_alloc.allocate(new_cap);
// 2.	将旧元素原地拷贝或移动到新缓冲区:
for (size_type i = 0; i < size(); ++i) {AllocTraits::construct(tmp_alloc, new_buf + i, std::move_if_noexcept(data_[i]));
}
// 3.	销毁、释放旧内存,切换指针:
for (size_type i = 0; i < size(); ++i)AllocTraits::destroy(alloc, data_[i]);
alloc.deallocate(data_, cap);
data_ = new_buf;
cap   = new_cap;

  1. 拷贝或移动构造另一个 vector

当你做 vector<int, MyAlloc> v2(v1); 时,如果 MyAlloc 支持跨类型拷贝:

template <class Alloc2>
vector(const vector<T,Alloc2>& other,const Alloc& alloc /* = Alloc()*/): alloc_(alloc), size_(other.size()), cap_(other.size())
{using UAlloc2 = typename Alloc2::template rebind<T>::other;UAlloc2 src_alloc(other.get_allocator());data_ = alloc_traits::allocate(alloc_, cap_);for (size_type i = 0; i < size_; ++i) {alloc_traits::construct(alloc_, data_ + i,other.data_[i]);}
}

这里,Alloc2::rebind::other 用来从 other 的分配器类型里拿到一个能分配 T 的实例。

  1. 插入时的异常安全缓冲

对于强异常安全保证,vector 插入可能在临时缓冲区中先做完整构造,然后才切换到正式内存。依然用同一个 rebind::other:

// 简化伪码
UAlloc temp_alloc = get_allocator();
pointer temp_buf = temp_alloc.allocate(cap_ + 1);try {// 构造 [0, pos) 旧元素for (...) construct(temp_buf + i, data_[i]);// 构造新元素construct(temp_buf + idx, value);// 构造剩余旧元素for (...) construct(temp_buf + j, data_[j-1]);
}
catch(...) {// 析构已经构造的元素for(...) destroy(temp_buf + k);temp_alloc.deallocate(temp_buf, cap_ + 1);throw;
}// 到此无异常,切换到 temp_buf ...

小结
• Alloc::rebind<U>::other 或 allocator_traits<Alloc>::rebind_alloc<U>
• 场景:初次分配元素数组、扩容重分配、跨分配器拷贝构造、异常安全插入等。
• 作用都是:把一个“只能分配 T”的分配器,变成“能分配 U”的分配器,供 vector 各种内部机制使用。

通过这些例子,可以看到 other 是如何被 std::vector 在内存管理各环节中反复引用的。


文章转载自:

http://mOWTslj9.ywpcs.cn
http://1koVKe3u.ywpcs.cn
http://nEkLzb0P.ywpcs.cn
http://I5C7atXH.ywpcs.cn
http://71Np78Ca.ywpcs.cn
http://POPDlmK4.ywpcs.cn
http://wH4umgiJ.ywpcs.cn
http://djCm57wV.ywpcs.cn
http://9uk0FXUs.ywpcs.cn
http://UftVgwwz.ywpcs.cn
http://GCCfZRPF.ywpcs.cn
http://pRJnEJoM.ywpcs.cn
http://FE2VFIRC.ywpcs.cn
http://nfoQ5XA6.ywpcs.cn
http://IUtt3kcg.ywpcs.cn
http://t62zV4ps.ywpcs.cn
http://21DfOSpC.ywpcs.cn
http://eg4z063O.ywpcs.cn
http://0ziLY0wb.ywpcs.cn
http://CBuEtaq6.ywpcs.cn
http://M59KBrio.ywpcs.cn
http://TK5md0mZ.ywpcs.cn
http://b99r1hdU.ywpcs.cn
http://NB4cwwVW.ywpcs.cn
http://n8hJq48v.ywpcs.cn
http://z7V8oXxp.ywpcs.cn
http://bHo3InjT.ywpcs.cn
http://BikfnphQ.ywpcs.cn
http://so4YroTL.ywpcs.cn
http://xbQ7dW1v.ywpcs.cn
http://www.dtcms.com/wzjs/738854.html

相关文章:

  • 深圳福田最大网站公司网站套餐可以分摊吗吗
  • 网站seo在线诊断网站快照前显示中文怎么做的
  • 网站首页二级下拉框怎么做百度联盟怎么做自己的网站
  • 欧派全屋定制联系电话seo比较好的优化
  • 网站导航作用无锡网站建设专注千客云网络
  • 零用贷网站如何做wordpress添加新的模板
  • 辽宁网站建设招标自己如何建立网站
  • 企业网站登录入口官网wordpress memcache插件
  • 南宁网站建设索q.479185700国内优秀企业网站设计欣赏
  • 网站淘宝客怎么做个人网页设计作品下载
  • 山西省建设招聘信息网站设计公司网页制作
  • 清华大学学生工作做网站政务服务网站建设整改报告
  • 慈溪高端网站设计wordpress php7不兼容
  • 维护网站的一般方法google浏览器网页版
  • 网站不被收录了网站后台软件可以自己做吗
  • 免费的源代码分享有哪些网站dede分类信息网站
  • 蚌埠网站制作公司费用建筑模型网站
  • 济南做网站哪里好win7怎么重新安装wordpress
  • 四合一网站建设源码软件开发周期
  • 学院网站建设的现状分析东莞网站优化哪家好
  • 怎么做后台网站一键更新晋城推广型网站建设
  • 广西网站建设与规划胶州经济技术开发区 建设局 网站
  • 凡科建站官网页更换视频做阀门网站电话
  • 大港做网站刹车片图纸网站建设
  • 网站运营管理的内容有哪些什么是网站运营推广
  • 网站平台建设呈现全新亮点棋盘网站开发
  • 西安有哪些做网站建设的公司广东东莞建设网
  • 国外网页游戏网站合肥建站企业
  • 护肤品网站建设方案电商网站制作流程图
  • 网站设计简单吗汕头中小企业网站制作