C++:allocator类(动态数组续)
1.为什么需要 allocator?
在 C++ 中,动态内存管理通常通过 new
和 delete
完成:
int* p = new int; // 分配内存 + 构造对象
delete p; // 析构对象 + 释放内存
但 new
和 delete
有两个问题:
-
耦合性:将内存分配和对象构造合并为一个操作。
-
灵活性不足:无法适配不同的内存管理策略(如内存池、共享内存等)。
allocator
类的核心目标就是解耦内存分配和对象构造,提供更灵活的内存管理。
2.allocator 的核心作用
std::allocator
是标准库容器(如 vector
, list
, map
等)默认使用的内存分配器。它主要有以下作用:
1. 分离内存分配和对象构造
-
分配内存:先分配原始内存块,但不构造对象。
-
构造对象:在已分配的内存上手动构造对象。
-
析构对象:手动析构对象,但不释放内存。
-
释放内存:最终释放原始内存块。
#include <memory>std::allocator<int> alloc;// 1. 分配内存(未初始化)
int* p = alloc.allocate(5); // 分配 5 个 int 的空间// 2. 构造对象
for (int i = 0; i < 5; ++i) {alloc.construct(p + i, i); // 在 p[i] 处构造 int 对象,值为 i
}// 3. 析构对象
for (int i = 0; i < 5; ++i) {alloc.destroy(p + i); // 析构 p[i] 处的对象
}// 4. 释放内存
alloc.deallocate(p, 5);
2. 支持自定义内存管理策略
通过自定义 allocator
,可以实现:
-
内存池:预分配大块内存,减少碎片。
-
共享内存:在进程间共享内存区域。
-
性能优化:针对特定场景优化内存分配速度。
3.allocator 的典型使用场景
场景 1:标准库容器
所有标准库容器(如 std::vector
)默认使用 std::allocator
:
template <class T, class Allocator = std::allocator<T>>
class vector {
private:T* data_ = nullptr; // 指向动态数组的指针size_t size_ = 0; // 当前元素数量size_t capacity_ = 0; // 当前分配的内存容量Allocator allocator_; // 内存分配器对象public:// ... 保留已有构造函数 ...// 赋值运算符(拷贝并交换 idiom)vector& operator=(const vector& other) {if (this != &other) {vector temp(other); // 利用拷贝构造函数swap(*this, temp); // 交换资源}return *this;}// 移动赋值运算符vector& operator=(vector&& other) noexcept {if (this != &other) {clear();allocator_.deallocate(data_, capacity_);data_ = other.data_;size_ = other.size_;capacity_ = other.capacity_;allocator_ = std::move(other.allocator_);other.data_ = nullptr;other.size_ = other.capacity_ = 0;}return *this;}// 交换两个vector(noexcept保证)friend void swap(vector& a, vector& b) noexcept {using std::swap;swap(a.data_, b.data_);swap(a.size_, b.size_);swap(a.capacity_, b.capacity_);swap(a.allocator_, b.allocator_);}// 添加emplace_back支持template <class... Args>void emplace_back(Args&&... args) {if (size_ >= capacity_) {reserve(capacity_ ? capacity_ * 2 : 1);}allocator_.construct(data_ + size_++, std::forward<Args>(args)...);}// 完善reserve的异常安全void reserve(size_t new_cap) {if (new_cap <= capacity_) return;T* new_data = allocator_.allocate(new_cap);size_t i = 0;try {for (; i < size_; ++i) {allocator_.construct(new_data + i, std::move_if_noexcept(data_[i]));allocator_.destroy(data_ + i);}} catch (...) {// 回滚已构造元素for (size_t j = 0; j < i; ++j) {allocator_.destroy(new_data + j);}allocator_.deallocate(new_data, new_cap);throw;}allocator_.deallocate(data_, capacity_);data_ = new_data;capacity_ = new_cap;}// ... 保留其他已有方法 ...
};
要点说明:
1. 使用分配器进行内存管理(allocate/deallocate)
2. 实现RAII原则,在析构函数中释放资源
3. 支持基础操作:push_back/pop_back/clear
4. 包含移动语义优化性能
5. 实现迭代器访问功能
6. 包含简单的扩容策略(容量翻倍)
这个只是简单模仿vector容器的核心机制,实际标准库实现会更复杂(包含异常安全、优化策略等很多东西)
场景 2:自定义内存分配策略
例如,实现一个简单的内存池:
template <typename T>
class MemoryPoolAllocator {
public:// 必需的类型定义(C++标准要求)using value_type = T; // 分配的元素类型using pointer = T*; // 指针类型using const_pointer = const T*; // 常指针类型using size_type = std::size_t; // 大小类型using difference_type = std::ptrdiff_t; // 指针差异类型// 分配器传播特性(影响容器拷贝行为)using propagate_on_container_copy_assignment = std::true_type;using propagate_on_container_move_assignment = std::true_type;using propagate_on_container_swap = std::true_type;/*** @brief 默认构造函数(必须支持)* @note 需要保证同类型的不同allocator实例可以互相释放内存*/MemoryPoolAllocator() noexcept = default;/*** @brief 模板拷贝构造函数(必须支持)* @tparam U 模板参数类型* @note 允许从其他模板实例化的allocator进行构造*/template <typename U>MemoryPoolAllocator(const MemoryPoolAllocator<U>&) noexcept {}/*** @brief 内存分配函数(核心接口)* @param n 需要分配的元素数量* @return 指向分配内存的指针* @exception 可能抛出std::bad_alloc或派生异常*/T* allocate(size_t n) {// TODO: 实现内存池分配逻辑// 建议方案:// 1. 计算总字节数 bytes = n * sizeof(T)// 2. 从内存池获取对齐的内存块// 3. 返回转换后的指针return static_cast<T*>(::operator new(n * sizeof(T)));}/*** @brief 内存释放函数(核心接口)* @param p 需要释放的内存指针* @param n 释放的元素数量* @note 必须保证p是通过allocate(n)分配的指针*/void deallocate(T* p, size_t n) noexcept {// TODO: 实现内存池回收逻辑// 建议方案:// 1. 将内存块标记为空闲// 2. 返回内存池供后续重用::operator delete(p);}/*** @brief 分配器比较函数(必须支持)* @note 不同实例是否应该被视为相等,需根据内存池实现决定*/bool operator==(const MemoryPoolAllocator&) const noexcept { return true; // 假设所有实例使用同一内存池}bool operator!=(const MemoryPoolAllocator&) const noexcept {return false;}/*** @brief 可选:对象构造函数(C++20前需要)* @tparam Args 构造参数类型*/template <typename... Args>void construct(T* p, Args&&... args) {::new(static_cast<void*>(p)) T(std::forward<Args>(args)...);}/*** @brief 可选:对象析构函数(C++20前需要)*/void destroy(T* p) {p->~T();}
};
场景 3:避免默认初始化
默认的 new
会调用构造函数,而 allocator
可以先分配内存,再按需构造对象:
std::allocator<std::string> alloc;
std::string* p = alloc.allocate(3); // 仅分配内存,不构造对象// 按需构造
alloc.construct(p, "hello"); // 构造第一个 string
alloc.construct(p + 1, "world"); // 构造第二个 string
4.allocator 的关键接口
以下是 std::allocator
的核心方法:
方法 | 作用 |
---|---|
allocate(n) | 分配 n 个对象的原始内存(未初始化) |
deallocate(p, n) | 释放内存(需先析构所有对象) |
construct(p, args) | 在位置 p 构造对象,参数为 args |
destroy(p) | 析构 p 处的对象 |
5.自定义 allocator 的要点
5.1. 必须提供的类型别名
自定义 allocator
需要定义以下类型:
template <typename T>
class CustomAllocator {
public:using value_type = T; // 必须定义// 其他必要类型...
};
5.2. 实现必要接口
至少需要实现 allocate
和 deallocate
方法:
T* allocate(size_t n) {return static_cast<T*>(::operator new(n * sizeof(T)));
}void deallocate(T* p, size_t n) {::operator delete(p);
}
5.3. 支持 rebind 机制
容器可能需要分配其他类型的对象(如链表节点的分配器):
template <typename U>
struct rebind {using other = CustomAllocator<U>;
};
6.C++17 后的改进
C++17 引入了 std::allocator_traits
,简化了自定义 allocator
的实现。即使自定义分配器未实现某些接口,allocator_traits
会提供默认实现:
template <typename Alloc>
using allocator_traits = std::allocator_traits<Alloc>;// 使用示例
auto p = allocator_traits<Alloc>::allocate(alloc, n);
7.总结
-
核心作用:解耦内存分配与对象构造,提供更灵活的内存管理。
-
默认行为:标准库容器使用
std::allocator
。 -
自定义场景:内存池、性能优化、特殊内存区域(如共享内存)。
-
关键接口:
allocate
、deallocate
、construct
、destroy
。
相关文章:
C++:allocator类(动态数组续)
1.为什么需要 allocator? 在 C 中,动态内存管理通常通过 new 和 delete 完成: int* p new int; // 分配内存 构造对象 delete p; // 析构对象 释放内存 但 new 和 delete 有两个问题: 耦合性:将内…...
Go语言手动内存对齐的四大场景与实践指南
Go语言手动内存对齐的四大场景与实践指南 引言:Go的内存对齐机制 Go语言通过编译器自动处理内存对齐问题,开发者通常无需关心底层细节。然而,在特定场景下,手动干预内存对齐是避免程序崩溃或数据错乱的必要操作。本文将深入探讨G…...
libva基础
Libva(Lib Video Acceleration)是一个开源的库,实现了 **VA-API**(Video Acceleration API),旨在为视频处理提供跨平台的硬件加速支持。 1、核心功能与作用 硬件加速抽象层:Libva 作为中间层&…...
如何在 AI 搜索引擎(GEO)霸屏曝光,快速提升知名度?
虽然大多数人仍然使用 Google 来寻找答案,但正在发生快速转变。ChatGPT、Copilot、Perplexity 和 DeepSeek 等 LLM 已成为主流。这主要是因为每个都有自己的免费和公共版本,并且总是有重大的质量改进。 许多人每天都使用这些工具来提问和搜索互联网&…...
Java入门知识总结——章节(二)
ps:本章主要讲数组、二维数组、变量 一、数组 数组是一个数据容器,可用来存储一批同类型的数据 🔑:注意 类也可以是一个类的数组 public class Main {public static class Student {String name;int age; // 移除 unsignedint…...
Python 序列构成的数组(元组不仅仅是不可变的列表)
元组不仅仅是不可变的列表 有些 Python 入门教程把元组称为“不可变列表”,然而这并没有完全概括 元组的特点。除了用作不可变的列表,它还可以用于没有字段名的记 录。鉴于后者常常被忽略,我们先来看看元组作为记录的功用。 元组和记录 元…...
OJ题:移动零
双指针法 c 语言实现 void moveZeroes(int* nums, int numsSize) {int dest,cur; //创建临时指针和目标指针destcur0;//出初始化while(cur<numsSize)//遍历{if(nums[cur]!0){swap(&nums[cur],&nums[dest]);cur;dest;}else{cur;}}} 思路是建立两个指针࿰…...
wait函数等待多个子进程
父进程等待多个子进程时可以使用 wait() 函数,但有一些要点需要注意,下面为你详细介绍相关内容。 可以使用 wait() 函数等待多个子进程的原理 wait() 函数会让调用它的父进程暂停执行,直到它的某个子进程结束,然后返回结束子进程…...
数据湖的数据存储与管理策略:构建高效的数据管理框架
数据湖的数据存储与管理策略:构建高效的数据管理框架 在大数据时代,数据湖作为存储和管理海量数据的关键技术,已经成为众多企业数字化转型的重要组成部分。数据湖的核心优势在于其能够支持结构化、半结构化和非结构化数据的存储,然而,随着数据量的增加和复杂度的提升,如…...
Linux进程管理之进程的概念、进程列表和详细的查看、进程各状态的含义
进程的概念 进程是程序执行的实例,在Linux中,每个进程都有一个唯一的PID(进程ID)。 查看当前系统中有哪些进程 在Linux系统中,查看当前运行的进程可以使用几个常用命令: ps - 显示当前进程的快照。常用选…...
3万字长文详解Android AIDL 接口设计
目录 第一章:AIDL 概述 1.1 什么是 AIDL?定义与核心作用 1.2 AIDL 的典型使用场景 第二章:AIDL 语法规则 2.1 支持的数据类型:从基础到高级 2.2 接口声明:写好通信的 “剧本” 2.3 方向标记:数据流向的 “交通灯” 第三章:AIDL 文件编写 3.1 创建 AIDL 文件:从…...
HFSS 使用入门
资源 下载资源: https://download.csdn.net/download/wangjun_huster/90547193 下载破解: https://download.csdn.net/download/wangjun_huster/90547551 安装 https://www.bilibili.com/list/ml3403866295?oid925751664&bvidBV1CT4y1u7LB 入门…...
精心整理-2024最新网络安全-信息安全全套资料(学习路线、教程笔记、工具软件、面试文档).zip
2024最新网络安全-信息安全全套资料(学习路线、教程笔记、工具软件、面试文档),视频教程文档资料共55GB。 一、网络安全-信息安全学习路线 0、网络安全-信息安全思维导图.jpg 1、网络安全大师课 V2024.pdf 2、网络安全行业白皮书.pdf 3、网络…...
RAG基建之PDF解析的“流水线”魔法之旅
将PDF文件和扫描图像等非结构化文档转换为结构化或半结构化格式是人工智能的关键部分。然而,由于PDF的复杂性和PDF解析任务的复杂性,这一过程显得神秘莫测。 在RAG(Retrieval-Augmented Generation)基建之PDF解析的“魔法”与“陷阱”中,我们介绍了PDF解析的主要任务,对现…...
leetcode刷题日记——跳跃游戏
[ 题目描述 ]: [ 思路 ]: 题目要求在给出的每次可移动最大步数中选择一个移动步数,如果有一种选择能达到终点就返回true,如果没有一种选择能够达到终点就返回false因为每次给出的最大步数不同,步数越大,…...
Scala 数组
Scala 数组 引言 Scala 作为一门多范式编程语言,融合了面向对象和函数式编程的特点。数组是编程语言中非常基础和常见的数据结构,在 Scala 中也不例外。本文将详细介绍 Scala 中的数组,包括其定义、操作以及在实际开发中的应用。 Scala 数…...
基于华为设备技术的端口类型详解
以下是基于华为设备技术网页的端口类型详解(截至2025年3月): 一、Access端口 定义:仅允许单个VLAN通过,用于连接终端设备(如PC、打印机) 处理流程: 接收帧:未带标签…...
使用 Go 和 Gin 实现高可用负载均衡代理服务器
前言 在现代分布式系统中,负载均衡是保障服务高可用性和性能的核心技术。本文将基于 Go 语言和 Gin 框架实现一个支持动态路由、健康检查、会话保持等特性的企业级负载均衡代理服务器,并提供完整的压力测试方案和优化建议。 通过本方案实现的负载均衡代理具备以下优势: 单…...
零基础驯服GitHub Pages
各位互联网流浪汉、赛博吉普赛人、以及不小心点进来的产品经理们!今天我们要用程序员的方式搞点大事情——不写代码、不买服务器、不氪金,免费拥有一个能吹牛的个人网站!准备好你的键盘和表情包收藏夹,我们的奇幻漂流开始了&#…...
OpenBMC:BmcWeb 生效路由5 优化trie
OpenBMC:BmcWeb 生效路由4 将路由添加到Trie中-CSDN博客 在url被添加到trie中后,validate的最后一步是优化trie void validate() {for (std::unique_ptr<BaseRule>& rule : allRules){if (rule){std::unique_ptr<BaseRule> upgraded = rule->upgrade();if…...
买卖股票的最佳时机(121)
121. 买卖股票的最佳时机 - 力扣(LeetCode) 解法: class Solution { public:int maxProfit(vector<int>& prices) {int cur_min prices[0];int max_profit 0;for (int i 1; i < prices.size(); i) {if (prices[i] > cur…...
强大的AI网站推荐(第四集)—— Gamma
网站:Gamma 号称:展示创意的新媒介 博主评价:快速展示创意,重点是展示,在几秒钟内快速生成幻灯片、网站、文档等内容 推荐指数:🌟🌟🌟🌟🌟&#x…...
Business Trip and Business Travel
Business Trip and Business Travel References Background I would like to introduce the background. Dave is going on a business trip, but he’s very busy, so he needs Leo’s help to buy the plane ticket. Panda is an agent of China Eastern /ˈiːstərn/ Airl…...
为pip设置国内镜像源
pip设置国内镜像源 在Python中使用pip安装软件包时,通常我们会遇到网络问题,尤其是在中国大陆地区。为了解决这个问题我们可以使用一些国内提供的镜像源。下面以清华大学的镜像源为例进行使用说明。 方法一:临时使用 在命令行中࿰…...
MySQL查询成本计算
对于如上SQL,只是因为查询字段不同,最终执行时选择的索引就不同,那么MySQL是如何决定选择使用哪个索引呢? 答案是MySQL会进行成本计算,对于各个场景查询进行成本预估,最终选择最优。 我们可以使用trace工具…...
使用 rsync 进行服务器文件同步与优化
使用 Rsync 工具在两台 Linux 服务器之间同步文件 Rsync 是一种高效的文件同步工具,它可以在本地或远程服务器之间同步文件和目录。Rsync 通过仅传输文件的变化部分来减少数据传输量,因此特别适合用于定期备份或同步大量数据。本文将详细介绍如何将 A 服…...
java面向对象从入门到入土
面向对象进阶 (写程序的套路) 面向:拿,找 对象:能干活的东西 面向对象编程:拿东西过来做对应的事情 (写程序的套路) 面向:拿,找 对象:能干活的东西 面向对象编程:拿东西过来做对应的事情 重点学习:学习已有对象并使用,学习如何自己设计对象并使用 设计对…...
Redis设计与实现-哨兵
哨兵模式 1、启动并初始化sentinel1.1 初始化服务器1.2 使用Sentinel代码1.3 初始化sentinel状态1.4 初始化sentinel状态的master属性1.5 创建连向主服务器的网络连接 2、获取主服务器信息3、获取从服务器的信息4、向主从服务器发送信息5、接受主从服务器的频道信息6、检测主观…...
vscode 打开工程 看不到文件目录
vscode 打开工程 看不到文件目录 View->Explorer 快捷键:CtrlShiftE...
[c++项目]基于微服务的聊天室服务端测试
项目概述 本测试报告针对基于C实现的微服务架构聊天室服务端进行全面测试。系统主要包含以下微服务: 用户认证服务(Auth Service)消息处理服务(Message Service)在线状态服务(Presence Service࿰…...
Java面试黄金宝典16
1. 各种排序算法的时间复杂度和空间复杂度 冒泡排序 定义: 冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,…...
pytorch中dataloader自定义数据集
前言 在深度学习中我们需要使用自己的数据集做训练,因此需要将自定义的数据和标签加载到pytorch里面的dataloader里,也就是自实现一个dataloader。 数据集处理 以花卉识别项目为例,我们分别做出图片的训练集和测试集,训练集的标…...
LabVIEW 燃气轮机气路故障诊断
在船用燃气轮机气路故障诊断领域,LabVIEW 软件以其独特的功能和优势,成为构建高效、精准诊断系统的关键技术支撑。它全面覆盖硬件在环仿真平台的各个环节,从硬件连接、数据交互到系统功能实现,都发挥着不可替代的作用,…...
[项目]基于FreeRTOS的STM32四轴飞行器: 十六.激光测距定高功能
基于FreeRTOS的STM32四轴飞行器: 十六.激光测距定高功能 一.芯片介绍二.配置CubeMX三.激光测距芯片驱动编写四.定高PID的计算五.定高PID作用到电机上 一.芯片介绍 激光测高芯片在飞控板下侧: 原理图如下: 型号为:VL53LX1,为国产…...
HTML跑酷
先看效果 再上代码 <!DOCTYPE html> <html> <head><title>火柴人跑酷</title><style>body {margin: 0;overflow: hidden;background: #87CEEB;}#gameCanvas {background: linear-gradient(to bottom, #87CEEB 0%, #87CEEB 50%, #228B22 …...
C++Primer学习(14.1 基本概念)
当运算符作用于类类型的运算对象时,可以通过运算符重载重新定义该运算符的含义。明智地使用运算符重载能令我们的程序更易于编写和阅读。举个例子,因为在Sales_item类中定义了输入、输出和加法运算符,所以可以通过下述形式输出两个Sales_item…...
【Goalng】第九弹-----文件操作、JSON处理
🎁个人主页:星云爱编程 🔍所属专栏:【Go】 🎉欢迎大家点赞👍评论📝收藏⭐文章 长风破浪会有时,直挂云帆济沧海 目录 1.文件操作 1.1文件介绍 1.2.文件流 1.3.打开和关闭文件 1…...
锐评|希捷NVMe闪存+磁盘混合存储阵列
近日,希捷在英伟达GTC 2025会议上展示了NVMe混合闪存/磁盘阵列技术。这个混合存储阵列确实在当前AI数据存储困境中撕开了一道新口子,但远称不上完美,优缺点都极为鲜明。 从优点来看,希捷切中了大多数企业的痛点。AI领域数据量呈爆…...
如何缩短研发周期,降低研发成本?全星APQP软件为您提供解决方案
如何缩短研发周期,降低研发成本?全星APQP软件为您提供解决方案 一、 系统概述 全星研发管理APQP软件系统是一款专为产品研发和质量管控打造的智能化平台,旨在帮助企业高效推进APQP(先期产品质量策划)流程,…...
Centos7安装cat美化工具lolcat
Centos7安装cat美化工具lolcat Centos7安装lolcat使用ruby安装lolcat配置cat系统别名 结果验证 Centos7安装lolcat lolcat :一个在Linux 终端中输出彩虹特效的命令行工具 使用ruby安装lolcat # 安装ruby和zip yum install -y ruby# 查看ruby版本 ruby --version# …...
bluecode-20240913_1_数据解码
时间限制:C/C 1000MS,其他语言 2000MS 内存限制:C/C 256MB,其他语言 512MB 难度:困难 数据解码 指定有一段经过编码的二进制数据,数据由0个或多个"编码单元"组成。"编码单元"的编码方式…...
【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的缓存技术:使用 Redis 提升性能
<前文回顾> 点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、开篇整…...
典范硬币系统(Canonical Coin System)→ 贪心算法
【典范硬币系统】 ● 典范硬币系统(Canonical Coin System)是指使用贪心算法总能得到最少硬币数量解的货币面值组合。 ● 给定一个硬币系统 ,若使其为典范硬币系统,则要求其各相邻面值比例 ,及各开区间 内各金额…...
hbuilderx打包iOS上传苹果商店的最简流程
无需Mac电脑,无需安装xcode和transporter,其实使用hbuilderx开发的ios软件,也可以上架到苹果的app store商店的。 只需要有苹果开发者中心的苹果开发者账号就行了。 假如你还在了解上架阶段,还没打包,也还没有创建任…...
DeepSeek详解:探索下一代语言模型
文章目录 前言一、什么是DeepSeek二、DeepSeek核心技术2.1 Transformer架构2.1.1 自注意力机制 (Self-Attention Mechanism)(a) 核心思想(b) 计算过程(c) 代码实现 2.1.2 多头注意力 (Multi-Head Attention)(a) 核心思想(b) 工作原理(c) 数学描述(d) 代码实现 2.1.3 位置编码 (…...
python的内存管理
目录 1. 引用计数 2. 垃圾收集(GC) python的内存管理主要是引用计数和垃圾回收器来进行内存管理 1. 引用计数 每个 Python 对象都有一个引用计数,当引用计数为零时,对象的内存会被释放。 import sysa [] # 创建一个空列表对…...
【STL】list
l i s t list list 是 C C C 标准模板库( S T L STL STL)中的一个序列容器( S e q u e n c e C o n t a i n e r Sequence\ Container Sequence Container),它允许在容器的任意位置快速插入和删除元素,是一…...
证券公司主要业务分析及当前佣金最低免五情况探讨
我是StockMasterX,今日想分析证券公司主要业务,并探讨当前佣金最低且免五的证券公司情况,此议题具有一定研究价值,我从事股票交易多年,与证券公司互动频繁,前日晚间饮茶之际,浏览手机时对此深思…...
C++ 变量的声明与定义分离式编译与静态类型(十六)
1. 声明与定义的区别 声明(declaration):向编译器表明某个变量(或其他实体)的类型与名字,使它在后续的编译过程中可见或可用。定义(definition):除了声明变量的名字和类…...
黑盒测试的等价类划分法(输入数据划分为有效的等价类和无效的等价类)
重点: 有效等价和单个无效等价各取1个即可 1、正向用例:一条尽可能覆盖多条2、逆向用例:每一条数据,都是一条单独用例。 步骤: 1、明确需求 2、确定有效和无效等价 3、根据有效和无效造数据编写用例 3、适用场景 针对:需要有大量数据测试输入, …...