如何实现一个自定义的STL容器类,需要注意哪些方面

【QT】容器类 Qt 库提供了一组通用的基于模板的容器类。这些类可以用于存储指定类型的项目。例如,如果需要一个可调整大小的 QString 数组,可以使用 QVector。这些容器类设计得比 STL 容器更轻量、更安全且更易于使用。如果你不熟悉 STL,或者更喜欢“Qt 方式”的做法,可以使用这些类代替 STL 类。容器类是隐式共享的,它们是可重入的,并且经过优化以达到快速、低内存消耗和最小的内联代码扩展,从而生成更小的可执行文件。此外,在所有线程都将它们用作只读容器的情况下,它们是线程安全的。 阅读详情

一、实现时需要注意的关键方面

1. 模板与类型定义
模板类应该是一个类模板:template<typename T>
提供标准类型定义:value_type, iterator, const_iterator 等,用于与 STL 算法兼容。

2. 内存管理
使用 new / delete 或 allocator<T> 管理内存。
避免内存泄漏:确保所有内存都被正确释放(尤其是在异常处理时)。
实现 Rule of Five(拷贝构造、拷贝赋值、移动构造、移动赋值、析构)。

3. 异常安全性
所有操作(如 push_back)必须提供强异常保证或基本异常保证。
std::allocator 提供构造、销毁元素的方法,可用于安全构造对象。

4. 迭代器兼容性
提供 begin()、end() 返回迭代器。
迭代器应至少支持 STL 输入迭代器(可以直接用裸指针 T* 作为迭代器)。

5. 与 STL 算法兼容
类型别名如 value_type, reference, const_reference 可用于 STL 算法模板匹配。
重载操作符(如 operator[])与标准容器行为一致。

6. 性能优化
push_back 和 reallocate 时应该采用几何扩展策略(例如容量每次乘以 2)。
使用 std::move 移动元素,减少复制开销。

注:
value_type 表示“容器里元素的类型”。

std::vector<int> t;
std::vector<int>::value_type x = 42;
🔄 它的作用是?

主要是为 模板泛型算法 和 容器无关的编程 提供一种统一访问元素类型的方式。

例子:写一个函数模板接受任何容器
template<typename Container>
void printFirst(const Container& c) {
    typename Container::value_type val = *c.begin();
    std::cout << val << std::endl;
}


无论传入的是 std::vector<int> 还是 std::list<std::string>,value_type 都能正确推导出元素类型。

reference
reference 表示“容器中元素的引用类型”,通常是 T&,用于读写元素。

template <typename Container>
void setFirstElement(Container& c, const typename Container::value_type& newValue) {
    typename Container::reference ref = c.front();  // T& 类型
    ref = newValue;  // 修改第一个元素
}

二、实现代码:

template<typename T>
class MyVector {
public:
    // 类型定义
    using value_type = T;
    using iterator = T*;
    using const_iterator = const T*;

    // 构造函数、析构函数
    MyVector();
    MyVector(size_t size);
    ~MyVector();

    // 拷贝/移动 构造与赋值运算符
    MyVector(const MyVector& other);
    MyVector& operator=(const MyVector& other);
    MyVector(MyVector&& other) noexcept;
    MyVector& operator=(MyVector&& other) noexcept;

    // 容器接口
    void push_back(const T& value);
    void pop_back();
    T& operator[](size_t index);
    const T& operator[](size_t index) const;
    size_t size() const;
    bool empty() const;

    // 迭代器支持
    iterator begin();
    iterator end();
    const_iterator begin() const;
    const_iterator end() const;

private:
    T* data_;
    size_t size_;
    size_t capacity_;

    void reallocate(size_t new_capacity);
};

MyVector(const MyVector& other) 和MyVector(MyVector&& other) noexcept有什么区别,other不都是传进来的引用吗,都是不拷贝一份?

const MyVector& other只是不拷贝一份形参,但实现内容会深拷贝一份返回给新对象,且不能修改原值 MyVector&&
other 是可以修改原值的 因此它可以将原值修改为空,并且接管原值指向的内存

#include <cstddef>   // for size_t
#include <stdexcept> // for exceptions
#include <utility>   // for std::move
#include <algorithm> // for std::copy

template<typename T>
class MyVector {
public:
    using value_type = T;
    using iterator = T*;
    using const_iterator = const T*;

    // 默认构造函数
    MyVector()
            : data_(nullptr), size_(0), capacity_(0) {}

    // 有参数构造函数
    MyVector(size_t size)
            : data_(new T[size]), size_(size), capacity_(size) {}

    // 析构函数
    ~MyVector() {
        delete[] data_;
    }

    // 拷贝构造函数(深拷贝)
    MyVector(const MyVector& other)
            : data_(new T[other.capacity_]), size_(other.size_), capacity_(other.capacity_) {
        std::copy(other.data_, other.data_ + other.size_, data_);
    }

    // 拷贝赋值运算符(深拷贝)
    MyVector& operator=(const MyVector& other) {
        if (this != &other) {
            delete[] data_;
            data_ = new T[other.capacity_];
            size_ = other.size_;
            capacity_ = other.capacity_;
            std::copy(other.data_, other.data_ + other.size_, data_);
        }
        return *this;
    }

    // 移动构造函数
    MyVector(MyVector&& other) noexcept
            : data_(other.data_), size_(other.size_), capacity_(other.capacity_) {
        other.data_ = nullptr;
        other.size_ = 0;
        other.capacity_ = 0;
    }

    // 移动赋值运算符
    MyVector& operator=(MyVector&& other) noexcept {
        if (this != &other) {
            delete[] data_;
            data_ = other.data_;
            size_ = other.size_;
            capacity_ = other.capacity_;
            other.data_ = nullptr;
            other.size_ = 0;
            other.capacity_ = 0;
        }
        return *this;
    }

    // 添加元素
    void push_back(const T& value) {
        if (size_ >= capacity_) {
            reallocate(capacity_ == 0 ? 1 : capacity_ * 2);
        }

        try {
            data_[size_] = value;
            ++size_;
        } catch (...) {
            // 如果赋值失败,size_ 不增加
            throw;
        }
    }


    // 删除最后一个元素
    void pop_back() {
        if (size_ == 0) throw std::out_of_range("Vector is empty");
        --size_;
    }

    // 下标访问
    T& operator[](size_t index) {
        if (index >= size_) throw std::out_of_range("Index out of range");
        return data_[index];
    }

    const T& operator[](size_t index) const {
        if (index >= size_) throw std::out_of_range("Index out of range");
        return data_[index];
    }

    // 当前元素数量
    size_t size() const {
        return size_;
    }

    // 是否为空
    bool empty() const {
        return size_ == 0;
    }

    // 迭代器
    iterator begin() { return data_; }
    iterator end() { return data_ + size_; }

    const_iterator begin() const { return data_; }
    const_iterator end() const { return data_ + size_; }

private:
    T* data_;
    size_t size_;
    size_t capacity_;

    // 内部扩容函数
    void reallocate(size_t new_capacity) {
        // 先分配新内存
        T* new_data = new T[new_capacity];

        size_t i = 0;
        try {
            // 尝试移动构造所有已有元素
            for (; i < size_; ++i) {
                new_data[i] = std::move(data_[i]);
            }
        } catch (...) {
            // 如果中途抛异常,需要销毁已构造对象并释放内存
            delete[] new_data;
            throw;  // 重新抛出异常
        }

        // 一切安全完成后再替换旧数据
        delete[] data_;
        data_ = new_data;
        capacity_ = new_capacity;
    }

};

Qt容器类使用总结—QList、QVector等类 Qt库提供了一套通用的基于模板的容器类,可以用这些类存储指定类型的项。比如,你需要一个大小可变的QString的数组,则使用QVector。这些容器类比STL(C++标准模板库)容器设计得更轻量、更安全并且更易于使用。如果对STL不熟悉,或者倾向于用“Qt的方式”,那么你可以使用这些类,而不去使用STL的类。你可以用两种方式遍历容器内存储的项:Java风格的迭代器和STL风格的迭代器。Java风格的迭代器更易于使用,并且提供了更高级的功能; 阅读详情

相关推荐

Qt容器类及其遍历(Java风格和STL风格迭代器)

1、Qt提供了一组通用的基于模板的容器类。Qt的容器类对比C++的标准准模板库中的容器类,更轻量、更安全、更容易使用;此外,Qt的容器类还在速度、内存消耗和内联(inline)代码等方面进行了优化。2、存储在Qt容器类中的数据必须是可赋值的数据类型,即,这种数据类型必须提供一个默认的构造函数(不需参数的构造函数)、一个复制构造函数和一个赋值操作运算符。3、这些数据类型包含通常使用的大多数数据类型,包

zyx_0604的博客 2363

【QT学习五】Qt 的容器类QList,QVector,QSet,QMap等

它可以存储任何类型的对象,并提供了许多实用的函数来方便地访问和操作列表中的元素。QSet是一个集合,它存储不同的值,并提供了许多函数来方便地访问和操作集合中的元素。注意:存储在Qt容器中的数据必须是可赋值的数据类型,Qt的Object类以及其子类是不能够存储在容器中的,但可以存储其指针。优点:支持高效的随机访问,可以快速插入和删除元素,可以保持元素的顺序。优点:支持高效的随机访问,可以快速插入和删除元素,可以保持元素的顺序。优点:支持高效的查找,插入和删除元素,可以保持元素的唯一性。

从此不归路 2805

wxWidgets:容器类

wxWidgets:容器类wxWidgets:容器类Legacy类STL 构建 wxWidgets:容器类 由于历史原因,wxWidgets 在内部使用自定义容器类。 不幸的是,这在很长一段时间内是不可避免的,当时标准库没有广泛使用,即使现在出于兼容性原因也不能轻易更改。如果您正在构建自己的库版本,并且不关心兼容性或使用 STL 类造成的轻微(小于 5%)大小损失,您可以选择使用 wxWidgets 的“STL”构建,其中这些自定义类被替换为它们的标准对应类,只需阅读STL Build部分解释如何做到这一点

希望我的博客,能帮上你解决学习中工作中所遇到的问题 680

STL的容器类和迭代器

1.STL的容器类介绍 1.1、何为容器 (1)顾名思义,容器就是盛放东西的东西,这里被盛放的一般是数据对象,用来盛放的是容器类 (2)计算机中一切皆是数据,数据存储只能在内存中,而容器类是用做容器的内存的管理方法 (3)容器类的内核就是:数据结构 + 算法 (4)C语言语法内置的数组和结构体,就是语言源生支持的容器 (5)C++容器通过类库方式提供,容器类库被模板技术泛化后,就是STL容器了 1.2、STL有哪些容器类 (1)序列容器。元素在容器中的位置同元素的值无关,即容器不是排序的(类似于C数组)。包

weixin_44705391的博客 467

学习QT之容器类

学习QT之容器类 Qt提供了一组通用的基于模板的容器类。对比C++的标准模板库中的容器类,Qt的这些容器更轻量、更安全并且更容易使用。此外,Qt的容器类在速度、内存消耗和内联(inline)代码等方面进行了优化(较少的内联代码将说件可执行程序的大小)。 存储在Qt容器中的数据必须是可赋值的数据类型,也就是说,这种数据类型必须提供一个默认的构造函数、一个复制构造函数和一个赋值操作运算符。 这样的数...

贝勒里恩的博客 1731

掌握STL与Qt容器类:排序、映射与字符串处理

本文深入探讨了C++ STL和Qt框架中的容器类,如向量、列表、映射和字符串处理方法。通过实际案例,阐述了如何对向量进行排序、在列表中高效插入与删除,以及如何使用映射存储和检索数据。同时,介绍了QString类如何处理Unicode字符串,以及QMemArray<T>及其子类的特性与陷阱。

weixin_36299472的博客 327

Qt学习笔记1.3.1 Qt Core-容器类

Qt库提供基于模板的通用容器类,相比STL容器类更轻量化、安全和易用。容器类是隐式共享的、可重入的并且针对速度、低内存开销和最小内内联代码拓展进行了优化,这样实现了更小的可执行文件。此外。在某些情况下被用作只读容器时是线程安全的.为了访问容器内的项目,可以使用两种类型的迭代器:java风格迭代器和STL风格迭代器。java风格迭代器更易用而且提供高级功能。STL风格稍微更高效而且可以和QT和STL的泛型算法一起使用。QT还提供foreach关键字更方便地遍历容器。

qq_18466391的博客 1487

C#实战:5分钟搞定Modbus RTU通讯(基于NModbus4库)

本文详细介绍了如何使用C#和NModbus4库快速实现Modbus RTU通讯,包括环境配置、核心功能实现、性能优化及常见问题排查。通过代码示例和实用技巧,帮助开发者高效完成工业自动化设备的数据采集与控制任务。

weixin_30689307的博客 467

Qt容器类

文章目录一、顺序容器QVectorQListQLinkedListQStackQQueue二、关联容器类QMapQMultiMapQHashQMultiHashQSetQCache与QContiguousCache三、容器的嵌套四、Object及其子类不能直接作为容器类的itemC++容器类和Qt容器类的对比 Qt中的容器类比STL(C++标准模版库)更轻量、更安全、更容易使用。 一、顺序容器 顺序容器中的数据项(item)在逻辑上是一个接一个线性存储的; Qt顺序容器都支持面向对象的泛型操作。 QVect

weixin_43956958的博客 1273

Minitab实战:用Weibull分布预测产品寿命的5个关键参数(附真实案例)

本文通过一个真实的电容器老化测试案例,详细介绍了如何运用Minitab软件进行Weibull分布分析,以预测产品寿命。文章深入解读了形状参数β、尺度参数η等五个关键参数的工程意义与商业价值,指导工程师从失效数据中提取洞察,并将其应用于可靠性评估、保修策略制定及成本预估等实际业务决策。

weixin_29231263的博客 520

AI量化交易工作台Vibe-Trading:用自然语言驱动策略回测与多智能体研究

量化交易通过数学模型和计算机程序执行投资决策,其核心在于将市场规律转化为可验证的策略。传统量化开发涉及数据获取、策略编写、回测验证等复杂工程,对非编程背景的从业者构成较高门槛。随着大语言模型技术的发展,自然语言交互正成为降低技术使用难度的关键。Vibe-Trading项目正是这一趋势的实践,它将金融工程任务封装为可调用的工具与技能,允许用户通过自然语言指令直接驱动策略回测、因子研究和投资组合分析。其技术价值在于构建了一个模块化的AI Agent框架,通过ReAct推理框架协调多个专项技能,并创新性地引入多智

weixin_28695161的博客 1565

标准C++中的STL容器类简介

标准C++中的STL容器类简介 标准C++中的STL容器类简介 - sabolasi - ITeye技术网站标准C++中的STL容器类简介 SGI -- Silicon Graphics[Computer System] Inc.硅图[计算机系统]公司.STL ...

114

红外热成像仪原理及应用

目录什么是红外热成像背景介绍热成像技术原理热成像分类红外热成像和夜视仪之间的区别红外热像仪夜视仪红外照明相机对比红外热像仪都能看透什么如何选择制冷型和非制冷型红外热像仪制冷型红外热像仪非制冷型红外热像仪实例对比成像速度空间分辨率灵敏度光谱滤波同步何如选择合适的红外热像仪像素测温范围和被测物温度分辨率空间分辨率温度稳定性热像仪的距离系数比常见热成像仪关键参数量程视场角 (FOV)红外分辨率热灵敏度(NETD)焦距光谱范围精度内置优化分析NTED(热灵敏度)什么是NETD如何测量NETD?NETD如何影响测量?

zhy295006359的博客 2万+

C++ STL 容器类总结

零. 背景介绍 为什么要讲容器,因为容器是STL中最不可或缺的一部分: STL可分为容器(containers)、迭代器(iterators)、空间配置器(allocator)、配接器(adapters)、算法(algorithms)、仿函数(functors)六个部分。 对于常用的一些容器和容器适配器(可以看作由其它容器实现的容器),可以通过下表总结一下它们和相应头文件

ChenLI's blog 1186

解析vCard 3.0:提取电子名片中的姓名

N:LastName;FirstName;;;END:VCARD和END:VCARD标记数据块的开始和结束。N字段存储结构化姓名(分号分隔)。FN字段为直接可读的显示名称。其他字段如TELEMAIL等保存联系信息。

qq_45797625的博客 2777

使用R语言实现循环神经网络RNN进行文本生成

首先,让我们回顾一下循环神经网络(Recurrent Neural Networks,RNN)的基本概念。RNN是一种深度学习技术,特别适合处理序列数据,如时间序列和文本数据。RNN的关键特性是它的隐藏状态,这个状态可以捕捉到当前输入之前的信息。这使得RNN能够利用前面的信息来影响后续的输出,从而对序列数据进行有效的处理。

斌擎科技 724

模版和STL

string是标准库中的一个类,它位于头文件中。这个类提供了很多方便的功能来处理字符串,比如字符串的拼接、查找、替换等操作。这里作为string的前置讲解,还是比较重要的,需要客观的了解一下,一个是函数的模版,一个是STL核心概念参数化类型泛型编程的核心是使用参数化类型,也称为模板。这些参数可以在编译时被实例化为具体的类型,使得代码可以适应不同的数据类型需求。例如,在 C++ 中,可以定义一个模板函数来实现对不同类型数组的排序:函数模版应用场景容器类。

Jason_from_China的博客 1218

基于 SoC 的卷积神经网络车牌识别系统设计(1)引言

通过 CPU 软核 IP 在纯 FPGA 平台上构建一个 AI SoC 卷积神经网络车牌识别系统,其中,缩放、填充层、卷积层、ReLU、池化层、全连接层 IP 都是 Verilog 设计的,同时集成了各种高性能的 IP。这是最具挑战性的 AI SoC 芯片设计项目,集成了 Python 卷积神经网络代码、Verilog 卷积神经网络硬件设计、ARM SoC 设计、ARM 与 FPGA 的交叉编译流程等等。这不仅是科研学习、集创竞赛、秋招求职的一个极具优势的精彩项目,也是目前最火热的芯片行业之中的一个...

新芯设计的博客 3778

c++ 容器类

【转】C++容器类 C++容器类 C++中的容器类包括“顺序存储结构”和“关联存储结构”,前者包括vector,list,deque等;后者包括set,map,multiset,multimap等。 若需要存储的元素数在编译器间就可以确定,可以使用数组来存储,否则,就需要用到容器类了。  1、vector 连续存储结构,每个元素是在内存上是连续的; 支持高效的随机访问和

lcjwxd的专栏 1956

【信息系统项目管理师】第18章:项目绩效域详解

(3)度量绩效域与规划绩效域、项目工作绩效域和交付绩效域的相互作用:1规划构成了 交付和规划比较的基础;项目绩效域共同构成了一个统一的整体,作为一个完整系统,在项目生命周期过程中运行,系统内的每个绩效域相互作用、相互关联和相互依赖,并协调一致、共同运作,支撑项目目标和价值 的实现。(5)开发方法和生命周期绩效域与其他绩效域的相互作用:开发方法和生命周期绩效域与干系人绩效域、规划绩效域、不确定性绩效域、交付绩效域、项目工作绩效域和团队绩效域相互作用。(2)项目工作绩效域的绩效要点包括:项目过程;

数据知道的博客 7800

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

C++的STL容器类(Vector)----第一篇

1、Vector是什么1、Vector是什么Vector。

Jinyizhi2233的博客 6532

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

C++ STL list 容器详解:使用与模拟实现

本文详细介绍了C++ STL中的list容器及其模拟实现。list是带头结点的双向循环链表,支持O(1)时间复杂度的插入删除操作,但不支持随机访问。文章从list的基本使用入手,讲解了构造、迭代器、容量操作等接口,重点分析了迭代器失效问题。在模拟实现部分,详细展示了节点类、迭代器类的设计,以及list容器类的核心实现,包括类型定义、迭代器转换机制、构造函数和插入操作等关键功能。通过模板参数实现了const和非const迭代器的统一,支持前后遍历和箭头操作符访问成员。

凤年徐的博客 2170

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

标准模板库STL简介

题   目:Introduction to the Standard Template Library 原作者:SGI 翻   译:btwsmile 标准模板库(STL)是一个有关容器类、算法和迭代器的C++程序组件库,它提供了计算机科学领域内基础的算法和数据结构。STL是一个泛型库,这意味着它的组件被广泛的参数化,几乎每一个组件都用模板来实现。在使用STL之前,你必须首

btwsmile's blog 1305

STL容器类的继承

 STL容器类的继承     即时创建一个元素序列的能力是惊人的,它实现了你过去可能会花费(或者更确切的是浪费)多少时间才能解决这个特定的问题。例如,许多实用程序都涉及将文件读到内存,修改文件然后将它写会磁盘。你也可以抽取StringVector.cpp文件中的功能封装成一个以后可重用类。     现在问题是:创建一个vector类型成员的成员对象还是继承一个呢?一般的准则是使用组件(成员

只谈技术 4412

Qt容器类介绍

简介: Qt提供了多个基于模板的容器类,这些容器类可用于支持指定的数据类型,和STL容器相比,它们更加轻巧,安全,使用方便。这些容器类在很多方面进行了优化,例如优化速度,降低内存消耗,减少代码膨胀。它们都是隐式共享,写时复制并且它们支持线程可重入,在只读情况下,多线程访问同一对象是线程安全的。 在访问容器中的数据项时,可以使用两种风格的迭代器:Java风格迭代器和STL风格迭代。Qt还提供了for...

急支糖浆的博客 747

初阶C++——STL——string类、vector类和list类(使用方法+模拟实现+测试+思路分析)

从今天开始,我们正式进入STL的学习。 我们今天会重点讲解三个类——string vector 和 list 在介绍之前,我们可以先来了解一下,何为STL?以及它的优势和缺陷。

jxwd的博客 4989
上一篇: 异常安全性
下一篇: 多态相关知识
C++_girl
博客等级 码龄7年 32粉丝 60原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值