STL 容器 vector

1.1 什么是STL?
STL(Standard Template Library),即标准模板库,是一个具有工业强度的,高效的C++程序库。它被容纳于C++标准程序库(C++ Standard Library)中,是ANSI/ISO C++标准中最新的也是极具革命性的一部分。该库包含了诸多在计算机科学领域里所常用的基本数据结构和基本算法。为广大C++程序员们提供了一个可扩展的应用框架,高度体现了软件的可复用性。
STL的一个重要特点是数据结构和算法的分离。尽管这是个简单的概念,但这种分离确实使得STL变得非常通用。例如,由于STL的sort()函数是完全通用的,你可以用它来操作几乎任何数据集合,包括链表,容器和数组;
STL另一个重要特性是它不是面向对象的。为了具有足够通用性,STL主要依赖于模板而不是封装,继承和虚函数(多态性)——OOP的三个要素。你在STL中找不到任何明显的类继承关系。这好像是一种倒退,但这正好是使得STL的组件具有广泛通用性的底层特征。另外,由于STL是基于模板,内联函数的使用使得生成的代码短小高效;
从逻辑层次来看,在STL中体现了泛型化程序设计的思想,引入了诸多新的名词,比如像需求(requirements),概念(concept),模型(model),容器(container),算法(algorithmn),迭代器(iterator)等。与OOP(object-oriented programming)中的多态(polymorphism)一样,泛型也是一种软件的复用技术;从实现层次看,整个STL是以一种类型参数化的方式实现的,这种方式基于一个在早先C++标准中没有出现的语言特性--模板(template)。

1.2 STL内容介绍
STL中六大组件:
1)容器(Container),是一种数据结构,如list,vector,和deques ,以模板类的方法提供。为了访问容器中的数据,可以使用由容器类输出的迭代器;
2)迭代器(Iterator),提供了访问容器中对象的方法。例如,可以使用一对迭代器指定list或vector中的一定范围的对象。迭代器就如同一个指针。事实上,C++的指针也是一种迭代器。但是,迭代器也可以是那些定义了operator*()以及其他类似于指针的操作符地方法的类对象;
3)算法(Algorithm),是用来操作容器中的数据的模板函数。例如,STL用sort()来对一个vector中的数据进行排序,用find()来搜索一个list中的对象,函数本身与他们操作的数据的结构和类型无关,因此他们可以在从简单数组到高度复杂容器的任何数据结构上使用;
4)仿函数(Function object)
5)迭代适配器(Adaptor)
6)空间配制器(allocator)

vector 容器

1. vector容器 简介
(1)vector容器和数组非常相似,也称为单端数组。
(2)vector与普通数组区别:不同之处在于数组是静态空间,而vector可以动态扩展。 动态扩展并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间。
(3)vector容器的迭代器是支持随机访问的迭代器。

vector常用的操作函数

1. vector<T> v; //T表示数据的类型,可以是int类型,也可以是string对象。
2. vector(v.begin(), v,end());  //将v[begin().end())区间(前闭后开)中的元素拷贝给本身。
3. vector(n, elem);  //构造函数将n个elem拷贝给本身。
4. vector(const vector &vec);  //拷贝构造函数。
5. vector& operator=(const vector &vec);  //重载等号操作符。
6. assign(begin,end);  //将[begin,end)区间中的数据拷贝赋值给本身。
7. assign(n,elem);  //将n个elem拷贝赋值给本身。
8. empy(); //判断容器是否为空。
9. capacity(); //容器的容量。
10. size();  //返回容器中元素的个数。
11. resize(int num);  //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
                               //如果容器变短,则末尾超出容器长度的元素被删除。
12. resize(int num, elem); //重新指定容器的长度为num,若容器变成,则以elem值填充新位置。
                                       //如果容器变短,则末尾超出容器长度的元素被删除。
13. push_back(ele);  //尾部插入元素ele。
14. pop_back();  //删除最后一个元素。
15. insert(const_iterator pos, ele); //迭代器指向位置pos插入元素ele。
16. insert(const_iterator pos, int count ele); //迭代器指向位置pos插入count个元素。
17. erase(const_iterator pos); //删除迭代器指向的元素。
18. erase(cons_titerator start, const_iterator end);  //删除迭代器从start到end之间的元素。

注意 : std::remove 是一个算法,它将所有与指定值匹配的元素移动到容器的末尾,
并返回一个迭代器指向新逻辑结尾。它不实际删除元素,只是将它们移动到容器的末尾

19. clear();  //删除容器中所有元素。   
20. at(int idx);   ///返回索引为idx所指的数据。
21. operator[];  //返回索引idx所指的数据。
22. front();  //返回容器中第一个数据元素。
23. back();   //返回容器中最后一个数据元素。
24. swap(vec);  //将vec与本身的元素互换。
25. reserve(int len); //容器预留len个元素长度,预留位置不初始化,元素不可访问。

构造函数

(1)功能描述:创建vector容器
(2) 函数原型:

1. vector<T> v; //T表示数据的类型,可以是int类型,也可以是string对象
2. vector(v.begin(), v,end());  //将v[begin().end())区间(前闭后开)中的元素拷贝给本身。
3. vector(n, elem);  //构造函数将n个elem拷贝给本身
4. vector(const vector &vec);  //拷贝构造函数
#include <iostream>
#include<vector> 

using namespace std;

void printVector(vector<int>&v)   //各种容器的接口,v1容器传进去,就打印v1容器
{
    for (vector<int>::iterator it = v.begin(); it != v.end();it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

//vector容器构造
void test01()
{
    vector<int> v1; //默认构造  无参构造

    for (int i = 0; i < 10; i++)
    {
        v1.push_back(i);
    }

    printVector(v1);

    //通过区间方式进行构造
    vector<int> v2(v1.begin(), v1.end()); //把v1.begin()-v1.end()区间内数给v2

    printVector(v2);

    //n个elem方式构造

    vector<int> v3(10, 100); //这是10个100,不是100个10

    printVector(v3);

    //拷贝构造
    vector<int>v4(v3);

    printVector(v4);
}

int main()
{
    test01();
    
    return 0;
}

 赋值操作

(1)功能描述:给vector容器进行赋值。
(2) 函数原型:

1. vector& operator=(const vector &vec);  //重载等号操作符。
2. assign(begin,end);  //将[begin,end)区间中的数据拷贝赋值给本身。
3. assign(n,elem);  //将n个elem拷贝赋值给本身。

(3)vector赋值方式比较简单,使用operator=,或者assign都可以。

        

#include <iostream>
#include<vector> 

using namespace std;

//vector赋值

void printVector(vector<int>& v)
{
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test02()
{
    vector<int>v1;
    for (int i = 0; i < 10; i++)
    {
        v1.push_back(i);
    }
    printVector(v1);

    //赋值 operator=
    vector<int> v2;
    v2 = v1;
    printVector(v2);

    //assign
    vector<int> v3;
    v3.assign(v1.begin(), v1.end());  //提供两个迭代器,两个迭代器区间中的元素都赋值给vector容器,区间为前闭后开
    printVector(v3);

    //n个elem方式赋值
    vector<int> v4;
    v4.assign(10, 100);
    printVector(v4);
}


int main()
{
    test02();

    return 0;
}

容量和大小

(1)功能描述:对vector容器的容量和大小操作。
(2)函数原型:

1. empy(); //判断容器是否为空
2. capacity(); //容器的容量
3. size();  //返回容器中元素的个数
4. resize(int num);  //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
                               //如果容器变短,则末尾超出容器长度的元素被删除。
5. resize(int num, elem); //重新指定容器的长度为num,若容器变成,则以elem值填充新位置。
                                       //如果容器变短,则末尾超出容器长度的元素被删除。

(3) vector 容器的容量(用 capacity 表示),指的是在不分配更多内存的情况下,容器可以保存的最多元素个数;而 vector 容器的大小(用 size 表示),指的是它实际所包含的元素个数。
(4) vector 容器的大小不能超出它的容量,在大小等于容量的基础上,只要增加一个元素,就必须分配更多的内存。注意,这里的“更多”并不是 1 个。换句话说,当 vector 容器的大小和容量相等时,如果再向其添加(或者插入)一个元素,vector 往往会申请多个存储空间,而不仅仅只申请 1 个。
(5)一旦 vector 容器的内存被重新分配,则和 vector 容器中元素相关的所有引用、指针以及迭代器,都可能会失效,最稳妥的方法就是重新生成。

 #include <iostream>
 #include<vector> 

using namespace std;

//vector容器的容量和大小操作

void printVector(vector<int>&v)
{
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test03()
{
    vector<int> v1;
    for (int i = 0; i < 10; i++)
    {
        v1.push_back(i);
    }
    printVector(v1);

    if (v1.empty()) //为真 代表容器为空
    {
        cout << "v1为空" << endl;
    }
    else
    {
        cout << "v1不为空:" << endl;
        cout << "capacity容量:" << v1.capacity() <<endl;
        cout << "v1的大小为:" << v1.size() << endl;

        //重新指定大小
        v1.resize(15);  //如果重新指定的比原来长了,默认用0填充新的位置
        printVector(v1);

        v1.resize(20,100);  //利用重载版本,参数2可以指定默认填充值
        printVector(v1);

        v1.resize(5);  //如果重新指定的比原来短了,超出的部分会删除掉
        printVector(v1);
    }
}

int main()
{
    test03();

    return 0;
}

插入和删除

(1)功能描述:对vector容器进行插入、删除操作。
(2)函数原型:

1.1 push_back(ele);  //尾部插入元素ele 需要一个已经构造好的对象,并且会复制或移动这个对象的副本        
                     到容器中
1.2 emplace_back(ele) // 尾插,接受构造函数的参数,在容器末尾直接构造新的对象,避免了复制或移动 
                     的开销。
2. pop_back();  //删除最后一个元素
3. insert(const_iterator pos, ele); //迭代器指向位置pos插入元素ele
4. insert(const_iterator pos, int count ele); //迭代器指向位置pos插入count个元素
5. erase(const_iterator pos); //删除迭代器指向的元素
6. erase(cons_titerator start, const_iterator end);  //删除迭代器从start到end之间的元素
7. clear();  //删除容器中所有元素

(3)push_back 和 emplace_bcak 的区别:

  push_back

push_back 是向容器尾部添加一个拷贝(或者移动)构造的对象副本。具体来说:

  • 如果你调用 push_back,你需要传递一个已经构造好的对象,容器将会创建这个对象的一个副本,然后将副本放入容器。

示例:

std::vector<int> vec;
int x = 10;
vec.push_back(x);  // 将 x 的副本添加到 vec 的末尾

emplace_back

emplace_back 则是在容器的末尾直接构造一个新对象,而不是拷贝或者移动一个已经存在的对象。具体来说:

  • 如果你调用 emplace_back,你需要传递构造函数的参数,这些参数将被用来在容器的末尾直接构造一个新对象。

示例:

std::vector<std::string> vec;
vec.emplace_back("hello");  // 在 vec 的末尾直接构造一个 std::string 对象

总结 : 

push_back 需要进行对象的复制或移动操作,而 emplace_back 则是直接在容器的内存空间上构造对象,因此通常更高效

push_back 适用于已经构造好的对象,而 emplace_back 更适合直接通过构造函数参数来构造对象

示例使用 push_back

#include <iostream>
#include <vector>
#include <string>

struct MyObject {
    int data;
    MyObject(int d) : data(d) {
        std::cout << "Constructing MyObject with data " << data << std::endl;
    }
    MyObject(const MyObject& other) : data(other.data) {
        std::cout << "Copying MyObject with data " << data << std::endl;
    }
};

int main() {
    std::vector<MyObject> vec;

    MyObject obj1(1);
    vec.push_back(obj1);  // 使用 push_back 添加 obj1 的副本

    std::cout << "Adding another object..." << std::endl;

    MyObject obj2(2);
    vec.push_back(obj2);  // 使用 push_back 添加 obj2 的副本

    return 0;
}


// 输出
Constructing MyObject with data 1
Copying MyObject with data 1
Adding another object...
Constructing MyObject with data 2
Copying MyObject with data 2

示例使用 emplace_back

#include <iostream>
#include <vector>
#include <string>

struct MyObject {
    int data;
    MyObject(int d) : data(d) {
        std::cout << "Constructing MyObject with data " << data << std::endl;
    }
};

int main() {
    std::vector<MyObject> vec;

    vec.emplace_back(1);  // 使用 emplace_back 在容器中直接构造对象

    std::cout << "Adding another object..." << std::endl;

    vec.emplace_back(2);  // 使用 emplace_back 在容器中直接构造对象

    return 0;
}

//输出
Constructing MyObject with data 1
Adding another object...
Constructing MyObject with data 2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值