C++vector的使用总结及常用vector操作

本篇博客主要针对vector容器的使用事项做讨论,以如何在多线程中使用vector。

一、vector基础

1. C++vector的使用总结及常用vector操作

2. C++ 中vector的使用方法

二、vector使用注意事项

不能在后面还会改变vector容量的情况下(添加元素、删除元素),使用指针访问vector里面的元素。 这里原因是当元素的容量增加时,vector的数据存储区容量不够,就会重新申请更大的数据存储区,把原来的数据复制到新的数据存储区,然后释放掉旧的数据存储区,此时,如果有指针指向旧的数据区的数据,这些指针将指向不确定的内容(非法指针),访问这些指针时就会出错,而且这些错误非常值隐蔽,难以发现。

典型的场景就是就是多线程的应用中将vector作为容器。主线程不断地像vector中添加数据,多个子线程从vector得到指向某个数据的指针,以方便处理完这个数据之后通过指针更新数据。在这种情况下,由于主线程不断的向vector中添加数据,vector就会重新获取新的数据缓冲区,子线程中获取到的指针就指向不确定内容,程序运行就会出错。

有没有解决非法指针上述问题?当然有:


/**
 * Array是一个模板类,作用类似于一个vector,但是只实现了部分函数。
 * 最大的特点是在多线程环境下通过指针访问数组的元素的是安全的,不会
 * vector一样出现非法指针,详见博客:
 * https://blog.csdn.net/DumpDoctorWang/article/details/79966945
 * 设计思想是,每当向Array数组的末尾push一个元素时,不是直接将数
 * 据本身放进数据容器,而是new一块空间,把数据的值放进去,由于new
 * 的空间需要手动释放才会失效,因此通过指针访问数组的元素时,除非手
 * 动释放了空间,都不会出现异常。然后将新分配空间的指针存储在vector
 * 里,这样就可以通过指针访问数组元素。这部分详见push()的实现。
 */

#ifndef MY_ARRAY_H
#define MY_ARRAY_H

#include <vector>
#include <stdexcept>

template<typename T>
class Array {
public:
    virtual ~Array() {
        clear();
    }

    /**
     * 存入一个元素
     * @param elem 元素
     */
    void push(T &elem) {
        auto node = new T;  //分配空间
        (*node) = elem;     //赋值
        _pointer_vector.push_back(node);//存下指针
    }

    /**
     * 获取第index个元素的指针
     * @param index 索引
     * @return 指针
     */
    T* ptr(std::size_t index) {
        if (index < _pointer_vector.size()) {
            return _pointer_vector[index];
        } else {
            clear();//释放内存
            throw std::out_of_range("Array::ptr():index超出范围");
        }
    }

    /**
     * 重载[]操作符号,提供类似于普通数组通过[]访问元素的功能。
     * @param index  索引
     * @return index个元素的引用
     */
    T& operator[](std::size_t index){
        if (index < _pointer_vector.size()) {
            return *(_pointer_vector[index]);
        } else {
            clear();//释放内存
            throw std::out_of_range("Array::ptr():index超出范围");
        }
    }

    /**
     * 获取第index个元素
     * @param index 索引
     * @return 元素
     */
    T get(std::size_t index) {
        if (index < _pointer_vector.size()) {
            return *(_pointer_vector[index]);
        } else {
            clear();//释放内存
            throw std::out_of_range("Array::get():index超出范围");
        }
    }

    /**
     * elem更新第index个元素
     * @param index 索引
     * @param elem 元素
     */
    void set(std::size_t index, T elem) {
        if (index < _pointer_vector.size()) {
            *(_pointer_vector[index]) = elem;
        } else {
            clear();//释放内存
            throw std::out_of_range("Array::set():index超出范围");
        }
    }

    /**
     * 清空所有元素,并释放内存
     */
    void clear() {
        for (std::size_t i = 0; i < _pointer_vector.size(); i++) {
            delete _pointer_vector[i];
        }
        _pointer_vector.clear();
    }

    /**
     * 返回元素个数
     * @return 大于等于0的数
     */
    size_t size() {
        return _pointer_vector.size();
    }

private:
    std::vector<T *> _pointer_vector;
};

#endif //MY_ARRAY_H
 

Array类的使用非常简单,给出一段示例代码:


int main() {
    //初始化
    Array<int> int_arr;
    for(int i=0;i<10;i++){
        int_arr.push(i);//在数组末尾添加元素
    }
    //打印数组
    for(int i=0;i<int_arr.size();i++){
        std::cout<<int_arr[i]<<",";//访问元素
//        std::cout<<int_arr.get(i)<<",";//这样访问也ok
    }
    std::cout<<std::endl;

    //修改某个数据
    int_arr[0] = 23;
    int_arr.set(1,233);
    int *pInt = int_arr.ptr(2);
    *pInt = 2333;
    //打印数组
    for(int i=0;i<int_arr.size();i++){
        std::cout<<int_arr[i]<<",";//访问元素
    }
    return 0;
}




猜你喜欢

转载自blog.csdn.net/dumpdoctorwang/article/details/79966945