C++ vector的使用

参考:http://www.cplusplus.com/reference/vector/vector/?kw=vector

std::vector (C++11)

template < class T, class Alloc = allocator<T> > class vector; // generic template

Vectors是一个序列容器,表示大小可变的数组

就像数组一样,vectors(向量)为其元素使用连续的存储位置,这意味着它们的元素也可以通过指向其元素的常规指针上的偏移量来访问,并且与数组一样有效。但与数组不同的是,它们的大小可以动态变化,容器会自动处理它们的存储。

在内部,向量使用动态分配的数组来存储它们的元素。这是因为为了在插入新元素时增大大小,可能需要重新分配这个数组,这意味着分配一个新数组并将所有元素移动到新数组中。就处理时间而言,这是一个相对昂贵的任务,因此,向量不会在每次向容器添加元素时重新分配。

相反,向量容器可能会分配一些额外的存储空间以适应可能的增长,因此容器的实际容量可能会大于存储元素所需的存储空间(即它的大小)。库可以实现不同的增长策略来平衡内存使用和重新分配,但在任何情况下,重新分配应该只发生在对数生长间隔的大小,以便插入单个元素的向量可以提供平摊常数时间复杂度(见push_back方法)。

因此,与数组相比,向量消耗更多的内存,以换取管理存储和有效地动态增长的能力。

与其他动态序列容器(deques、lists和forward_lists)相比,vector非常高效地访问它的元素(就像数组一样),并且相对高效地从它的末端添加或删除元素。对于涉及在非结尾位置插入或删除元素的操作,它们的性能比其他操作差,而且与lists和forward_lists相比,它们的迭代器和引用的一致性更差。

Container properties属性

Sequence序列

序列容器中的元素按严格的线性顺序排列。各个元素通过它们在这个序列中的位置来访问。

Dynamic array动态数组

允许直接访问序列中的任何元素,甚至是通过指针运算,并在序列末尾提供相对快速的元素添加/删除。

Allocator-aware

容器使用一个分配器对象来动态地处理它的存储需求。

Template parameters模版参数

  • T:元素类型。只有在T被保证在移动时不抛出异常时,实现才能优化移动元素,而不是在重新分配期间复制它们。别名为成员类型vector::value_type。
  • Alloc:用于定义存储分配模型的分配器对象的类型。默认情况下,使用的是分配器类模板,它定义了最简单的内存分配模型,并且是与值无关的。

别名为成员类型vector::allocator_type。

Member types成员类型

成员类型  定义  notes
value_type 第一个模版参数T  
allocator_type 第二个模版参数Alloc 默认为allocator<value_type>
reference value_type&,引用  
const_reference const value_type&  
pointer allocator_traits<allocator_type>::pointer 用于默认allocator:value_type*
const_pointer allocator_traits<allocator_type>::const_pointer 用于默认allocator:const value_type*
iterator 一个value_type的随机访问迭代器 可转换成const_iterator
const_iterator 一个const value_type的随机访问迭代器  
reverse_iterator reverse_iterator<iterator>  
const_reverse_iterator reverse_iterator<const_iterator>  
difference_type 一种有符号整数类型,等价于:iterator_traits<iterator>::difference_type 通常是ptrdiff_t
size_type 一个无符号整数类型,它可以表示任意一个非负的size_type类型的值 通常是size_t

Member functions成员函数

1)构造函数,有多态

default (1)    
explicit vector (const allocator_type& alloc = allocator_type());

fill (
2) explicit vector (size_type n); vector (size_type n, const value_type& val, const allocator_type& alloc = allocator_type());
range (
3) template <class InputIterator> vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type());
copy (
4) vector (const vector& x); vector (const vector& x, const allocator_type& alloc);
move (
5) vector (vector&& x); vector (vector&& x, const allocator_type& alloc);
initializer list (
6) vector (initializer_list<value_type> il, const allocator_type& alloc = allocator_type());

 构造一个vector向量,根据使用的构造器版本来初始化其内容

解释:

(1)empty container constructor (default constructor)空容器构造器,也是默认构造器

构造一个没有元素的空容器

(2) fill constructor

构造一个有着n个元素的容器。每个元素都是val(如果提供)的复制

(3) range constructor

用与range[first,last)相同的元素构造一个容器,每个元素都是由该范围中相应的元素按相同的顺序构造的。

(4) copy constructor (and copying with allocator)

构造一个获取x元素的容器。
如果指定了alloc,并且它与x的分配器不同,则移动元素。否则,不会构造任何元素(它们的所有权直接转移)。
x处于未指定但有效的状态。

(6) initializer list constructor
用il中每个元素的副本以相同的顺序构造一个容器。
容器保存一个alloc的内部副本,该副本用于为它的元素分配和释放存储,并构造和销毁它们(由它的allocator_traits指定)。如果没有alloc参数传递给构造函数,则使用默认构造的分配器,除了以下情况:
  • 复制构造函数(4,第一个签名,即第一种没alloc的方式)创建一个容器,该容器通过调用x的分配器上适当的selected_on_container_copy_construction trait来保存和使用分配器的副本。
  • move构造函数(5,第一个签名)获得x的分配器。

通过调用带有适当参数的allocator_traits::construct来复制、移动或以其他方式构造所有元素。

参数:

1) alloc:

分配器对象。
容器保存并使用这个分配器的内部副本。
成员类型allocator_type是容器使用的内部分配器类型,在vector中定义为其第二个模板参数(Alloc)的别名。
如果allocator_type是默认分配器的实例化(它没有状态),这就无关紧要了。

2) n:

初始容器大小(即,在构造时容器中的元素数)。
成员类型size_type是无符号整数类型。

3) val:

要填充容器的值。容器中的n个元素都将被初始化为该值的一个副本。
成员类型value_type是容器中元素的类型,在vector中定义为其第一个模板参数(T)的别名。

4) first, last:
将迭代器输入到范围的初始和最终位置。使用的范围是[first,last),它包括first和last之间的所有元素,包括first指向的元素,但不包括last指向的元素。
函数模板参数InputIterator应该是一个输入迭代器类型,它指向可以构造value_type对象的类型的元素。

5) x:

另一个相同类型的向量对象(具有相同的类模板参数T和Alloc),其内容要么被复制,要么被获取。

6) il:
一个initializer_list对象。
这些对象是由初始化器列表声明器自动构造的。
成员类型value_type是容器中元素的类型,在vector中定义为其第一个模板参数(T)的别名。
例子:
#include <iostream>
#include <vector>
using namespace std;

int main(){
    //如上面所述的相同顺序来使用构造器
    vector<int> first; //ints的空vector
    vector<int> second (4, 100); //4个值为100的ints
    vector<int> third (second.begin(), second.end()); //迭代second
    vector<int> fourth (third); //third的副本

    int myints[] = {16, 2, 77, 29};
    //迭代器构造器也可以用来构造数组,即第三种构造器的另一种写法:
    vector<int> fifth(myints, myints + sizeof(myints) / sizeof(int));

    cout << "the contents of first are : ";
    for(auto x : first)
        cout << ' ' << x;
    cout << '\n';

    cout << "the contents of second are : ";
    for(auto x : second)
        cout << ' ' << x;
    cout << '\n';

    cout << "the contents of third are : ";
    for(auto x : third)
        cout << ' ' << x;
    cout << '\n';

    cout << "the contents of fourth are : ";
    for(auto x : fourth)
        cout << ' ' << x;
    cout << '\n';

    cout << "the contents of fourth are : ";
    for(vector<int>::iterator it = fourth.begin(); it!=fourth.end(); ++it)
        cout << ' ' << *it;
    cout << '\n';

    cout << "the contents of fifth are : ";
    for(vector<int>::iterator it = fifth.begin(); it!=fifth.end(); ++it)
        cout << ' ' << *it;
    cout << '\n';

    return 0;
}

返回:

/Users/user/CLionProjects/untitled/cmake-build-debug/untitled
the contents of first are : 
the contents of second are :  100 100 100 100
the contents of third are :  100 100 100 100
the contents of fourth are :  100 100 100 100
the contents of fourth are :  100 100 100 100
the contents of fifth are :  16 2 77 29

Process finished with exit code 0

Complexity复杂度

对于默认构造函数(1)和移动构造函数(5)来说容器复杂度是常量(除非alloc与x的分配器不同)。
对于所有其他情况,结果容器大小是线性的。
此外,如果range构造函数(3)中的InputIterator不是前向迭代器类别(即,它只是一个输入迭代器),则不能预先确定新的容量,而且构造在大小上将带来额外的对数复杂度(在增长时重新分配)。

Iterator validity迭代有效性

move constructors (5)中,如果元素被移动,那么与x相关的所有迭代器、指针和引用都将无效。

Data races

访问所有复制的元素。
移动构造函数(5)修改x。

Exception safety

强保证:在抛出异常时没有效果。
如果元素结构的适当参数不支持allocator_traits::construct,或者[first,last)指定的范围无效,它会导致未定义的行为。

2)析构函数

~vector();

销毁容器对象

这将对包含的每个元素调用allocator_traits::destroy,并使用它的分配器释放向量分配的所有存储容量。

Complexity复杂度

vector::size的线性

Iterator validity

所有的迭代器、指针和引用都无效。

Data races

修改容器及其所有元素。

Exception safety

No-throw guarantee: 从不抛出异常

3)赋值操作

copy (1)    
vector& operator= (const vector& x);
move (
2) vector& operator= (vector&& x);
initializer list (
3) vector& operator= (initializer_list<value_type> il);

将新内容分配给容器,替换其当前内容,并相应地修改其大小。

解释:

复制赋值(1)将x中的所有元素复制到容器中(x保留其内容)。

移动赋值(2)将x的元素移动到容器中(x处于未指定但有效的状态)。

初始化器列表赋值(3)将il的元素复制到容器中。

容器保留其当前分配器,除非allocator traits(分配器特征)表明x的分配器应该传播。如果发生了重新分配,则使用这个分配器(通过它的特性)来分配和释放存储,如果需要,则构造或销毁元素。

在调用之前容器中保存的任何元素要么被赋值,要么被销毁。

参数:

x:

一个相同类型的向量对象。(使用相同的模板参数,T和Alloc)。

il:

一个initializer_list对象。编译器将从初始化器列表声明器自动构造这些对象。
成员类型value_type是容器中元素的类型,在vector中定义为其第一个模板参数(T)的别名。

返回值:

*this

举例:

#include <iostream>
#include <vector>
using namespace std;

int main(){
    vector<int> foo (3,0);
    vector<int> bar (5,0);

    bar = foo;
    foo = vector<int>();

    cout << "size of foo : " << int(foo.size()) << endl;
    cout << "size of bar : " << int(bar.size()) << endl;
}

返回:

size of foo : 0
size of bar : 3

迭代器:

4)begin

      iterator begin() noexcept;
const_iterator begin() const noexcept;

返回迭代器开始
返回一个迭代器,该迭代器指向向量中的第一个元素。
注意,与成员vector::front返回对第一个元素的引用不同,这个函数返回一个指向它的随机访问迭代器。
如果容器为空,则不应取消对返回的迭代器值的引用。

参数:None

返回值:

序列容器开头的迭代器。
如果vector对象是const限定的,则该函数返回一个const_iterator。否则,它返回一个iterator。
成员类型iterator和const_iterator是随机访问迭代器类型(分别指向一个元素和一个const元素)。

5)end

      iterator end() noexcept;
const_iterator end() const noexcept;

返回迭代器结束
返回一个迭代器,该迭代器引用向量容器中的结束符元素。
后端元素是向量中最后一个元素之后的理论元素。它不指向任何元素,因此不应取消引用。
因为标准库函数使用的范围不包括它们的结束迭代器所指向的元素,所以这个函数常常与vector::begin结合使用,以指定一个范围,包括容器中的所有元素。
如果容器为空,则此函数返回与vector::begin相同的结果

参数:None

返回值:

一个迭代器,迭代到序列末尾之后的元素。
如果vector对象是const限定的,则该函数返回一个const_iterator。否则,它返回一个迭代器。
成员类型iterator和const_iterator是随机访问迭代器类型(分别指向一个元素和一个const元素)。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main(){
    vector<int> myvector;
    for(int i=1; i<=5; i++) myvector.push_back(i);
    cout << "myvector contains: ";

    for(vector<int>::iterator it = myvector.begin(); it!=myvector.end(); ++it)
        cout << ' ' << *it;
    cout << endl;
}

返回:

myvector contains:  1 2 3 4 5

6)rbegin

      reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;

返回反向迭代器以反向开始
返回一个反向迭代器,指向向量中的最后一个元素(它的开头正好相反)。
反向迭代器向后迭代:增加它们则是将它们移到容器的开头。
rbegin指向成员端将要指向的元素之前的元素。

注意,与成员vector::back返回对同一元素的引用不同,此函数返回一个反向随机访问迭代器。

参数:None

返回值:

序列容器的反向开头的反向迭代器。
如果vector对象是const限定的,则该函数返回一个const_reverse_iterator。否则,它将返回一个reverse_iterator。
成员类型reverse_iterator和const_reverse_iterator是反向随机访问迭代器类型(分别指向一个元素和一个const元素)。参见向量成员类型。

7)rend

      reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;

返回反向迭代器到反向结束
返回一个反向迭代器,指向向量中第一个元素之前的理论元素(被认为是它的反向端)。
vector::rbegin和vector::rend之间的范围包含向量的所有元素(按相反的顺序)。

参数:None

返回值:

序列容器的反向末端的反向迭代器。
如果vector对象是const限定的,则该函数返回一个const_reverse_iterator。否则,它将返回一个reverse_iterator。
成员类型reverse_iterator和const_reverse_iterator是反向随机访问迭代器类型(分别指向一个元素和一个const元素)。参见向量成员类型vector member types.。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main(){
    vector<int> myvector(5); //5个0
    int i=0;

    cout << "myvector contains: ";
    for(vector<int>::iterator it = myvector.begin(); it!=myvector.end(); ++it)
        cout << ' ' << *it;
    cout << '\n';

    vector<int>::reverse_iterator rit = myvector.rbegin();
    for(;rit!=myvector.rend(); ++rit) //从后往前叠加
        *rit = ++i;

    cout << "myvector contains: ";
    for(vector<int>::iterator it = myvector.begin(); it!=myvector.end(); ++it)
        cout << ' ' << *it;
    cout << '\n';

    return 0;
}

返回:

myvector contains:  0 0 0 0 0
myvector contains:  5 4 3 2 1

8) cbegin-内容不能修改

const_iterator cbegin() const noexcept;

返回const_iterator开始
返回一个指向容器中第一个元素的const_iterator。

常量迭代器是指向const内容的迭代器。这个迭代器可以增加或减少(除非它本身也是const),就像vector::begin返回的迭代器一样,但是它不能用来修改它所指向的内容,即使vector对象本身不是const
如果容器为空,则不应取消对返回的迭代器值的引用。

参数:None

返回值:

序列开头的const_iterator。
成员类型const_iterator是指向const元素的随机访问迭代器类型。

9)cend

const_iterator cend() const noexcept;

返回const_iterator结束
返回一个指向容器中粘贴结束元素的const_iterator。
常量迭代器是指向const内容的迭代器。这个迭代器可以增加或减少(除非它本身也是const),就像vector::end返回的迭代器一样,但是它不能用来修改它所指向的内容,即使vector对象本身不是const。
如果容器为空,则此函数返回与vector::cbegin相同的结果。
返回的值不能取消引用。

参数:None

返回值:

序列末尾之后的元素的const_iterator。
成员类型const_iterator是指向const元素的随机访问迭代器类型。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main(){
    vector<int> myvector = {10,0,30,40,50};

    cout << "myvector contains: ";
    for(vector<int>::const_iterator it = myvector.cbegin(); it!=myvector.cend(); ++it)
        cout << ' ' << *it;
    cout << '\n';

    return 0;
}

返回:

myvector contains:  10 0 30 40 50

10)crbegin

const_reverse_iterator crbegin() const noexcept;

返回const_reverse_iterator到反转开始处
返回一个指向容器中最后一个元素的const_reverse_iterator(即,它的开头正好相反)。

参数:None

返回值:

序列开头相反的const_reverse_iterator。
成员类型const_reverse_iterator是指向const元素的反向随机访问迭代器类型(请参阅向量成员类型)。

11)crend

const_reverse_iterator crend() const noexcept;

将const_reverse_iterator返回到反向终端
返回一个指向容器中第一个元素之前的理论元素的const_reverse_iterator(它被认为是容器的反向端)。

参数:None

返回值:

序列末尾的const_reverse_iterator。
成员类型const_reverse_iterator是指向const元素的反向随机访问迭代器类型(请参阅向量成员类型)。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main(){
    vector<int> myvector = {10,20,30,40,50};

    cout << "myvector backwards: ";
    for(vector<int>::const_reverse_iterator it = myvector.crbegin(); it!=myvector.crend(); ++it)
        cout << ' ' << *it;
    cout << '\n';

    return 0;
}

返回:

myvector backwards:  50 40 30 20 10

Capacity:

12)size

size_type size() const noexcept;

返回的大小
返回向量中元素的数目。
这是向量中实际持有的对象的数量,不一定等于它的存储容量

参数:None

返回值:

容器中元素的数量。
成员类型size_type是无符号整数类型。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myints;
    cout << "0.size " << myints.size() << endl;

    //放入10个值
    for (int i = 0; i < 10; i++) myints.push_back(i);
    cout << "1.size " << myints.size() << endl;

    //插入10个值为100的ints
    myints.insert(myints.end(), 10, 100);
    cout << "2.size " << myints.size() << endl;

    myints.pop_back();
    cout << "3.size " << myints.size() << endl;

    for(auto x : myints)
        cout << x << ' ';
    cout <<endl;
    return 0;
}

返回:

0.size 0
1.size 10
2.size 20
3.size 19
0 1 2 3 4 5 6 7 8 9 100 100 100 100 100 100 100 100 100 

13)max_size

size_type max_size() const noexcept;

返回最大大小
返回向量可以容纳的元素的最大数目。
由于已知的系统或库实现的限制,这是容器能够达到的最大潜在大小,但是容器并不能保证能够达到这个大小:它仍然可能在达到这个大小之前的任何一点分配存储。

参数:None

返回值:

向量容器可以容纳的元素的最大数量。
成员类型size_type是无符号整数类型。

14)capacity

size_type capacity() const noexcept;

返回分配的存储容量大小
返回当前分配给向量的存储空间的大小,以元素的形式表示。
这个容量不一定等于向量的大小。它可以等于或更大,允许容纳增长的额外空间,而不需要在每次插入时重新分配。
请注意,此容量并不假设对向量的大小有限制。当这个容量用完并且需要更多容量时,容器会自动扩展它(重新分配它的存储空间)向量大小的理论极限由成员max_size给出

向量的容量可以通过调用成员vector::reserve来显式地改变。

参数:None

返回值:

向量中当前分配的存储容量的大小,以它可以容纳的元素的数量来度量。
成员类型size_type是无符号整数类型。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector;
    for(int i=0; i<100; i++) myvector.push_back(i);

    cout << "size : " << myvector.size() << endl;
    cout << "capacity : " << myvector.capacity() << endl;
    cout << "max_size : " << myvector.max_size() << endl;
    return 0;
}

返回:

size : 100
capacity : 128
max_size : 4611686018427387903

15)resize

void resize (size_type n);
void resize (size_type n, const value_type& val);

改变尺寸
调整容器的大小,使其包含n个元素。
如果n小于当前容器的大小,则将内容缩减为它的前n个元素,删除其他元素(并销毁它们)。
如果n大于当前容器的大小,则通过在末尾插入尽可能多的元素来扩展内容,以达到n的大小。如果指定了val,则将新元素初始化为val的副本,否则,它们将被初始化为0值。
如果n也大于当前容器容量,则会自动重新分配分配的存储空间。
注意,这个函数通过插入或删除容器中的元素来更改容器的实际内容。

参数:

n:

新的容器大小,用元素的数量表示。
成员类型size_type是无符号整数类型。

val:

如果n大于当前容器大小,则将该val对象的内容复制到添加的元素中。
如果未指定,则使用默认构造函数。
成员类型value_type是容器中元素的类型,在vector中定义为第一个模板参数(T)的别名。

返回值:none

如果发生了重新分配,则使用容器的分配器分配存储,这可能会在失败时抛出异常(对于默认分配器,如果分配请求没有成功,则抛出bad_alloc)。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector;
    for(int i=1; i<10; i++) myvector.push_back(i);
    //从9截断为5
    myvector.resize(5);
    //从5扩为8,赋值为100
    myvector.resize(8,100);
    //从8扩为12,默认赋值为0
    myvector.resize(12);

    cout << "myvector contains:";
    for(int i=0; i<myvector.size(); i++)
        cout << ' ' << myvector[i];
    cout << '\n';
}

返回:

myvector contains: 1 2 3 4 5 100 100 100 0 0 0 0

16)empty

bool empty() const noexcept;

测试向量是否为空
返回该向量是否为空(即其大小是否为0)。

此函数不以任何方式修改容器。若要清除向量的内容,请参见vector::clear

参数:None

返回值:

如果容器大小为0,则为true,否则为false。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector;
    int sum{0};
    for(int i =1; i<=10; i++) myvector.push_back(i);
    while(!myvector.empty()){
        sum += myvector.back();
        myvector.pop_back();
    }

    cout << "total: " << sum << endl;
    return 0;
}

返回:

total: 55

该示例将向量的内容初始化为数字序列(从1到10)。然后,它逐个弹出元素,直到为空,然后计算它们的和。

17)reserve

void reserve (size_type n);

请求更改容量capacity
要求向量容量至少能够包含n个元素。
如果n大于当前向量容量,该函数将导致容器重新分配其存储,从而将其容量增加到n(或更大)。
在所有其他情况下,函数调用不会导致重新分配,向量容量也不会受到影响。
这个函数对向量大小没有影响,也不能改变它的元素

参数:

n:

向量的最小容量。
注意,得到的向量容量可能等于或大于n。
成员类型size_type是无符号整数类型。

返回值:

none

如果请求的大小大于最大大小(vector::max_size),则抛出一个length_error异常。

如果是重新分配,则使用容器的分配器分配存储,这可能会在失败时抛出异常(对于默认分配器,如果分配请求没有成功,则抛出bad_alloc)。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int>::size_type sz;
    vector<int> foo;
    sz = foo.capacity();
    cout << "making foo grow: \n";
    for(int i=0; i<100; i++){
        foo.push_back(i);
        if(sz!=foo.capacity()){
            sz = foo.capacity();
            cout << "capacity changed : " << sz << endl;
        }
    }

    vector<int> bar;
    sz = bar.capacity();
    cout << sz <<endl; //0
    bar.reserve(100);
    cout << "making bar grow: \n";
    for(int i=0; i<100; i++){
        bar.push_back(i);
        if(sz!=bar.capacity()){
            sz = bar.capacity(); //直接为100
            cout << "capacity changed: " << sz << endl;
        }
    }
    return 0;
}

返回:

making foo grow: 
capacity changed : 1
capacity changed : 2
capacity changed : 4
capacity changed : 8
capacity changed : 16
capacity changed : 32
capacity changed : 64
capacity changed : 128
0
making bar grow: 
capacity changed: 100

18)shrink_to_fit

void shrink_to_fit();

缩小以适应
请求容器减少容量以适应其大小。
该请求是非绑定的,容器实现可以自由地进行优化,使向量的容量大于其大小。

这可能会导致重新分配,但对向量大小没有影响,也不能改变其元素。

参数:

none

返回值:

none

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector(100);
    cout << "1.capacity of myvector: " << myvector.capacity() << endl;

    myvector.resize(10);
    cout << "2.capacity of myvector: " << myvector.capacity() << endl;

    myvector.shrink_to_fit();
    cout << "3.capacity of myvector: " << myvector.capacity() << endl;
    return 0;
}

返回:

1.capacity of myvector: 100
2.capacity of myvector: 100
3.capacity of myvector: 10

元素访问

19)operator[]-不检查是否出界

     reference operator[] (size_type n);
const_reference operator[] (size_type n) const;

访问元素
返回指向向量容器中位置为n的元素的引用。
类似的成员函数vector::at与这个操作符函数具有相同的行为,但vector::at是有界检查的,如果请求的位置超出范围,则通过抛出out_of_range异常发出信号。

可移植程序不应该使用超出范围的参数n来调用这个函数,因为这会导致未定义的行为。

参数:

n:

元素在容器中的位置。
注意,第一个元素的位置是0(不是1)。
成员类型size_type是无符号整数类型。

返回值:

在向量中指定位置的元素。
如果vector对象是const限定的,则该函数返回一个const_reference。否则,它返回一个引用。
成员类型reference和const_reference是容器元素的引用类型(请参阅向量成员类型)。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector(10);
    vector<int>::size_type sz = myvector.size();

    //赋值
    for(unsigned i = 0; i<sz; i++) myvector[i] = i;

    //调换顺序
    for(unsigned i = 0; i<sz/2; i++){
        int temp;
        temp = myvector[sz-1-i];
        myvector[sz-1-i] = myvector[i];
        myvector[i] = temp;
    }
    cout << "myvector contains: ";
    for(unsigned i=0; i<sz; i++)
        cout << ' ' << myvector[i];
    cout << endl;
    return 0;
}

返回:

myvector contains:  9 8 7 6 5 4 3 2 1 0

20)at - 检查是否出界

      reference at (size_type n);
const_reference at (size_type n) const;

访问元素
返回指向向量中位置为n的元素的引用。

该函数自动检查n是否在向量中有效元素的范围内,如果不是,则抛出out_of_range异常(即,如果n大于或等于它的大小)。这与成员操作符[]形成对比,后者不检查界限。

参数:

n:

元素在容器中的位置。
如果该值大于或等于向量大小,则抛出out_of_range类型的异常。
注意,第一个元素的位置是0(不是1)。
成员类型size_type是无符号整数类型。

返回值:

在容器中指定位置的元素。
如果vector对象是const限定的,则该函数返回一个const_reference。否则,它返回一个引用。
成员类型reference和const_reference是容器元素的引用类型(请参阅向量成员类型)。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector(10);

    //赋值
    for(unsigned i= 0; i<myvector.size(); i++)
        myvector.at(i) = i;
    
    cout << "myvector contains : ";
    for(unsigned i =0; i<myvector.size(); i++)
        cout << ' ' << myvector.at(i);
    cout << endl;
    return 0;
}

返回:

myvector contains :  0 1 2 3 4 5 6 7 8 9

21)front

      reference front();
const_reference front() const;

访问第一个元素
返回对向量中第一个元素的引用。
与成员vector::begin(它将迭代器返回到相同的元素)不同,此函数将返回一个直接引用

在空容器上调用此函数将导致未定义的行为。

参数:

none

返回值:

指向向量容器中的第一个元素的引用。
如果vector对象是const限定的,则该函数返回一个const_reference。否则,它返回一个引用。
成员类型reference和const_reference是容器元素的引用类型(请参阅向量成员类型)。

22)back

      reference back();
const_reference back() const;

访问的最后一个元素
返回对向量中最后一个元素的引用。
与成员vector::end返回的迭代器刚好经过这个元素不同,这个函数返回一个直接引用。
在空容器上调用此函数将导致未定义的行为。

参数:

none

返回值:

指向向量中最后一个元素的引用。
如果vector对象是const限定的,则该函数返回一个const_reference。否则,它返回一个引用。
成员类型reference和const_reference是向量元素的引用类型(参见成员类型)。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector;

    myvector.push_back(78); //front的值
    myvector.push_back(16); //back的值

    cout << "myvector.front() is now " << myvector.front() << endl;
    cout << "myvector.back() is now " << myvector.back() << endl;
    myvector.front() -= myvector.back();

    cout << "myvector.front() is now " << myvector.front() << endl;
    cout << "myvector.back() is now " << myvector.back() << endl;

    return 0;
}

返回:

myvector.front() is now 78
myvector.back() is now 16
myvector.front() is now 62
myvector.back() is now 16

23)data

      value_type* data() noexcept;
const value_type* data() const noexcept;

访问数据
返回指向向量内部用于存储其拥有的元素的内存数组的直接指针。

由于保证向量中的元素以向量表示的相同顺序存储在连续的存储位置中,因此可以偏移检索到的指针以访问数组中的任何元素。

参数:

none

返回值:

指向向量内部使用的数组中的第一个元素的指针。
如果vector对象是const限定的,该函数将返回一个指向const value_type的指针。否则,它返回一个value_type指针。
成员类型value_type是容器中元素的类型,在vector中定义为第一个类模板参数(T)的别名。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector(5);

    int* p = myvector.data();
    *p = 10; //第一个元素赋值为10
    ++p;
    *p = 20; //第二个赋值为20
    //p[0]从myvector[1]开始
    cout << p[0] << '\t'<< p[1] << '\t'<< p[2] << '\t'<< p[3] << '\t'<< p[4] << endl;
    p[2] = 100;
    cout << "myvector contains:";
    for(unsigned i=0; i<myvector.size(); ++i)
        cout << ' ' << myvector[i];
    cout << endl;
    return 0;
}

返回:

20    0    0    0    32644
myvector contains: 10 20 0 100 0

修改:

24)assign

range (1)    
template <class InputIterator>
  void assign (InputIterator first, InputIterator last);

fill (
2) void assign (size_type n, const value_type& val);
initializer list (
3) void assign (initializer_list<value_type> il);

分配向量内容
将新内容分配给向量,替换其当前内容,并相应地修改其大小。

解释:

在range版本(1)中,新内容是由first和last之间的每个元素按照相同的顺序构造的元素。
在fill版本(2)中,新内容是n个元素,每个元素初始化为val的一个副本。
在初始化列表版本(3)中,新内容是作为初始化列表传递的值的副本,顺序相同。
如果发生了重新分配,则使用内部分配器(通过其特性)来分配和释放存储。它也被用来破坏所有现有的元素,并构建新的元素。

在调用之前容器中保存的任何元素都将被销毁,并由新构造的元素替换(不进行元素分配)。
当且仅当新向量大小超过当前向量容量时,这将导致分配的存储空间的自动重新分配。

参数:

first, last:

将迭代器输入到范围的初始和最终位置。使用的范围是[first,last),它包括first和last之间的所有元素,包括first指向的元素,但不包括last指向的元素。
函数模板参数InputIterator应该是一个输入迭代器类型,它指向可以构造value_type对象的类型的元素。

n:

初始容器大小(即,在构造时容器中的元素数)。
成员类型size_type是无符号整数类型。

val:

要填充容器的值。容器中的n个元素都将被初始化为该值的一个副本。
成员类型value_type是容器中元素的类型,在vector中定义为其第一个模板参数(T)的别名。

 il:

一个initializer_list对象。
这些对象是由初始化器列表声明器自动构造的。
成员类型value_type是容器中元素的类型,在vector中定义为其第一个模板参数(T)的别名。

返回值:

none

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> first;
    vector<int> second;
    vector<int> third;

    first.assign(7,100); //7个值为100
    vector<int>::iterator it;
    it = first.begin()+1;

    second.assign(it, first.end()-1); //first[1:6]的5个值

    int myints[] = {1776, 7, 4};
    third.assign(myints, myints+3); //从数组中赋值
    cout << "size of first : " << int(first.size()) << endl;
    cout << "size of second : " << int(second.size()) << endl;
    cout << "size of third : " << int(third.size()) << endl;
    return 0;
}

返回:

size of first : 7
size of second : 5
size of third : 3

25)push_back

void push_back (const value_type& val);
void push_back (value_type&& val);

在末尾添加元素
在向量的最后一个元素之后添加一个新元素。val的内容被复制(或移动)到新元素。
这有效地将容器大小增加了1,当且仅当新向量大小超过当前向量容量时,就会自动重新分配分配的存储空间。

参数:

val:

要复制(或移动)到新元素的值。
成员类型value_type是容器中元素的类型,在vector中定义为其第一个模板参数(T)的别名。

返回值

none

如果发生了重新分配,则使用容器的分配器分配存储,这可能会在失败时抛出异常(对于默认分配器,如果分配请求没有成功,则抛出bad_alloc)。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector;
    int myint;

    cout << "Please enter some integers (enter 0 to end): \n";
    do{
        cin >> myint;
        myvector.push_back(myint);
    }while(myint);
    cout << "myvector stores " << int(myvector.size()) << " numbers.\n";
    return 0;
}

返回:

Please enter some integers (enter 0 to end): 
3
5
2
0
myvector stores 4 numbers.

该示例使用push_back在每次读取新整数时向向量添加新元素。

26)pop_back

void pop_back();

删除最后一个元素
删除向量中的最后一个元素,有效地将容器大小减少了1。
这将破坏删除的元素。

参数:

none

返回值:

none

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector;
    int sum(0);
    myvector.push_back(100);
    myvector.push_back(200);
    myvector.push_back(300);
    while(!myvector.empty()){
        sum += myvector.back();
        myvector.pop_back();
    }
    cout << "the elements of myvector add up to " << sum << endl;
    return 0;
}

返回:

the elements of myvector add up to 600

27)insert

single element (1)    
iterator insert (const_iterator position, const value_type& val);

fill (
2) iterator insert (const_iterator position, size_type n, const value_type& val);
range (
3) template <class InputIterator> iterator insert (const_iterator position, InputIterator first, InputIterator last);
move (
4) iterator insert (const_iterator position, value_type&& val);
initializer list (
5) iterator insert (const_iterator position, initializer_list<value_type> il);

插入元素
通过在元素之前插入指定位置的新元素来扩展向量,从而有效地通过插入的元素数量增加容器的大小。
当且仅当新向量大小超过当前向量容量时,这将导致分配的存储空间的自动重新分配。

因为向量使用数组作为它们的底层存储,所以将元素插入到向量末端以外的位置会导致容器将所有在position之后的元素重新定位到它们的新位置。与其他类型的序列容器(如list或forward_list)对同一操作执行的操作相比,这通常是一个低效的操作。

这些参数决定了插入了多少个元素,并将它们初始化为哪些值:

参数:

position:

在向量中插入新元素的位置。
iterator是一个成员类型,定义为一个指向元素的随机访问迭代器类型。

first, last:

将迭代器输入到范围的初始和最终位置。使用的范围是[first,last),它包括first和last之间的所有元素,包括first指向的元素,但不包括last指向的元素。
函数模板参数InputIterator应该是一个输入迭代器类型,它指向可以构造value_type对象的类型的元素。

n:

初始容器大小(即,在构造时容器中的元素数)。
成员类型size_type是无符号整数类型。

val:

要填充容器的值。容器中的n个元素都将被初始化为该值的一个副本。
成员类型value_type是容器中元素的类型,在vector中定义为其第一个模板参数(T)的别名。

 il:

一个initializer_list对象。
这些对象是由初始化器列表声明器自动构造的。
成员类型value_type是容器中元素的类型,在vector中定义为其第一个模板参数(T)的别名。

返回值:

指向第一个新插入元素的迭代器。
成员类型迭代器是指向元素的随机访问迭代器类型。
如果发生重新分配,则使用容器的分配器分配存储,这可能会在失败时抛出异常(对于默认分配器,如果分配请求没有成功,则抛出bad_alloc)。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector(3,100);
    vector<int>::iterator it;

    it = myvector.begin();
    it = myvector.insert(it, 200); //前面加个200,此时it在200前面
    myvector.insert(it,2,300); //前面加2个300
    cout << "myvector contains : ";
    for(it = myvector.begin(); it<myvector.end(); it++)
        cout << ' ' << *it;
    cout << endl;

    //it不再有效,重新获得
    it = myvector.begin();//此时it在300前面
    vector<int> anothervector(2, 400);
    //在300和200见加2个400
    myvector.insert(it+2, anothervector.begin(), anothervector.end());
    cout << "myvector contains : ";
    for(it = myvector.begin(); it<myvector.end(); it++)
        cout << ' ' << *it;
    cout << endl;
    
    int myarray[] = {501,502,503};
    myvector.insert(myvector.begin(), myarray, myarray+3);

    cout << "myvector contains : ";
    for(it = myvector.begin(); it<myvector.end(); it++)
        cout << ' ' << *it;
    cout << endl;
    return 0;
}

返回:

myvector contains :  300 300 200 100 100 100
myvector contains :  300 300 400 400 200 100 100 100
myvector contains :  501 502 503 300 300 400 400 200 100 100 100

28)erase

iterator erase (const_iterator position);
iterator erase (const_iterator first, const_iterator last);

删除元素
从向量中删除单个元素(位置)或元素范围([first,last])。

这有效地减少了容器的大小,减少了被删除的元素的数量。
因为向量使用一个数组作为它们的底层存储,擦除向量端以外位置的元素会导致容器在擦除段之后将所有元素重新定位到它们的新位置。与其他类型的序列容器(如list或forward_list)对同一操作执行的操作相比,这通常是一个低效的操作。

参数:

position:

在向量中插入新元素的位置。
iterator是一个成员类型,定义为一个指向元素的随机访问迭代器类型。

first, last:

将迭代器输入到范围的初始和最终位置。使用的范围是[first,last),它包括first和last之间的所有元素,包括first指向的元素,但不包括last指向的元素。
函数模板参数InputIterator应该是一个输入迭代器类型,它指向可以构造value_type对象的类型的元素。
返回值:
一个迭代器,指向函数调用 擦除的最后一个元素之后的元素的新位置。如果操作擦除序列中的最后一个元素,则返回容器端。
成员类型迭代器是指向元素的随机访问迭代器类型。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector;
    //赋值
    for(int i=1; i<=10; i++) myvector.push_back(i);

    //擦除第6个元素
    myvector.erase(myvector.begin()+5);
    cout << "myvector contains : " ;
    for(unsigned i = 0; i<myvector.size(); ++i)
        cout << ' ' << myvector[i];
    cout << endl;
    
    //擦除前3个
    myvector.erase(myvector.begin(), myvector.begin()+3);

    cout << "myvector contains : " ;
    for(unsigned i = 0; i<myvector.size(); ++i)
        cout << ' ' << myvector[i];
    cout << endl;
    return 0;
}

返回:

myvector contains :  1 2 3 4 5 7 8 9 10
myvector contains :  4 5 7 8 9 10

29)swap

void swap (vector& x);

交换内容
通过x的内容交换容器的内容,x是另一个相同类型的向量对象。大小可能不同。
在调用这个成员函数之后,这个容器中的元素是调用之前x中的元素,x中的元素是调用之前x中的元素。所有迭代器、引用和指针对交换后的对象仍然有效。
请注意,存在一个具有相同名称的非成员函数,交换,用类似于这个成员函数的优化来重载该算法。

 容器分配器是否也交换没有定义,除非在这种情况下,适当的allocator traits(分配器特性)明确地指示它们应该传播。

vector的bool为这个函数提供了额外的重载(参见vector<bool>::swap)。

参数:

x:

另一个相同类型的向量容器(即,用相同的模板参数T和Alloc实例化),其内容与此容器的内容交换。

返回值:

none

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> foo(3,100);
    vector<int> bar(5,200);
    cout << "foo contains: ";
    for(unsigned i=0; i<foo.size(); i++)
        cout << ' ' << foo[i];
    cout << endl;
    
    cout << "bar contains: ";
    for(unsigned i=0; i<bar.size(); i++)
        cout << ' ' << bar[i];
    cout << endl;

    foo.swap(bar);
    cout << "after swap foo contains: ";
    for(unsigned i=0; i<foo.size(); i++)
        cout << ' ' << foo[i];
    cout << endl;

    cout << "after swap bar contains: ";
    for(unsigned i=0; i<bar.size(); i++)
        cout << ' ' << bar[i];
    cout << endl;
    return 0;
}

返回:

foo contains:  100 100 100
bar contains:  200 200 200 200 200
after swap foo contains:  200 200 200 200 200
after swap bar contains:  100 100 100

30)clear

void clear() noexcept;

清除内容
删除向量中的所有元素(已销毁的元素),使容器的大小为0。

不能保证会发生重新分配,也不能保证由于调用此函数而改变向量容量。强制重新分配的典型替代方案是使用swap:

vector<T>().swap(x);   // clear x reallocating 

参数:

none

返回值:

none

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector;
    myvector.push_back(100);
    myvector.push_back(200);
    myvector.push_back(300);

    cout << "myvector contains : ";
    for(unsigned i =0; i<myvector.size(); i++)
        cout << ' ' << myvector[i];
    cout << endl;

    myvector.clear(); //清空
    myvector.push_back(1101);
    myvector.push_back(2202);

    cout << "myvector contains : ";
    for(unsigned i =0; i<myvector.size(); i++)
        cout << ' ' << myvector[i];
    cout << endl;
    return 0;
}

返回:

myvector contains :  100 200 300
myvector contains :  1101 2202

31) emplace - 一次插入一个

template <class... Args>
iterator emplace (const_iterator position, Args&&... args);

构造和插入元素
通过在位置插入新元素来扩展容器。这个新元素是使用args作为构造参数在适当的地方构造的。

这有效地将容器大小增加了1
当且仅当新向量大小超过当前向量容量时,将自动重新分配分配的存储空间。

因为向量使用数组作为它们的底层存储,所以将元素插入到向量末端以外的位置会导致容器将所有在position之后的元素移动到它们的新位置。与其他类型的序列容器(如list或forward_list)执行的操作相比,这通常是一个低效的操作。请参阅emplace_back,了解在末尾直接扩展容器的成员函数。

元素是通过调用allocator_traits::construct和args转发来就地构造的。
存在一个类似的成员函数insert,它复制或将现有对象移动到容器中。

参数:

position:

在向量中插入新元素的位置。
iterator是一个成员类型,定义为一个指向元素的随机访问迭代器类型。

args:

用于构造新元素的参数。

返回值:

指向新放置元素的迭代器。
成员类型迭代器是指向元素的随机访问迭代器类型。
如果发生了重新分配,则使用容器的分配器分配存储,这可能会在失败时抛出异常(对于默认分配器,如果分配请求没有成功,则抛出bad_alloc)。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector = {10,20,30};
    auto it = myvector.emplace(myvector.begin()+1, 100);
    myvector.emplace(it, 200);
    myvector.emplace(myvector.end(), 300);

    cout << "myvector contains : ";
    for(auto& x : myvector)
        cout << ' ' << x;
    cout << endl;
    return 0;
}

返回:

myvector contains :  10 200 100 20 30 300

32)emplace_back - 在尾巴插入

template <class... Args>
  void emplace_back (Args&&... args);

构造并在末尾插入元素
在向量的末尾插入一个新元素,正好在它当前的最后一个元素之后。这个新元素是使用args作为其构造函数的参数在适当的地方构造的。

这有效地将容器大小增加了1,当且仅当新向量大小超过当前向量容量时,就会自动重新分配分配的存储空间。
元素是通过调用allocator_traits::construct和args转发来就地构造的。
存在一个类似的成员函数push_back,它复制或将现有对象移动到容器中。

参数:

args:

用于构造新元素的参数。

返回值:

none

如果发生了重新分配,则使用容器的分配器分配存储,这可能会在失败时抛出异常(对于默认分配器,如果分配请求没有成功,则抛出bad_alloc)。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector = {10,20,30};
    myvector.emplace_back(100);
    myvector.emplace_back(200);

    cout << "myvector contains : ";
    for(auto& x : myvector)
        cout << ' ' << x;
    cout << endl;
    return 0;
}

返回:

myvector contains :  10 20 30 100 200

Allocator分配器:

33)get_allocator

allocator_type get_allocator() const noexcept;

得到分配器
返回与向量关联的分配器对象的副本。

参数:

none

返回值:

分配器

成员类型allocator_type是容器使用的分配器的类型,在vector中定义为其第二个模板参数(Alloc)的别名。

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> myvector ;
    int* p;
    unsigned int i;

    //使用vector的分配器分配一个有着5个元素空间的数组
    p = myvector.get_allocator().allocate(5);

    //在数组中构建适当的值:
    for(i=0; i<5; i++) myvector.get_allocator().construct(&p[i], i);

    cout << "the allocated array contains :";
    for(i=0; i<5; i++) cout << ' ' << p[i];
    cout << endl;

    //销毁和去分配
    for(i=0; i<5; i++) myvector.get_allocator().destroy(&p[i]);
    myvector.get_allocator().deallocate(p,5);
    return 0;
}

返回:

the allocated array contains : 0 1 2 3 4

至此都是public member function

下面是非成员函数重载:

34)relational operators (vector)

(1)    
template <class T, class Alloc>
  bool operator== (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);

(2)    
template <class T, class Alloc>
  bool operator!= (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);

(3)    
template <class T, class Alloc>
  bool operator<  (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);

(4)    
template <class T, class Alloc>
  bool operator<= (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);

(5)    
template <class T, class Alloc>
  bool operator>  (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);

(6)    
template <class T, class Alloc>
  bool operator>= (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);

向量的操作符
在向量容器lhs和rhs之间执行适当的比较操作。

相等比较(运算符==)是通过首先比较大小来执行的,如果大小匹配,则使用运算符==对元素进行顺序比较,在第一次不匹配时停止(就像使用算法equal一样)。

less-than比较(操作符<)的行为类似于使用lexicographical_compare算法,该算法以互惠的方式使用操作符<(即,检查a<b和b<a),并在第一次出现时停止。

其他操作也在内部使用操作符==和<来比较元素,其行为类似于执行以下等价操作:

 这些操作符在头文件<vector>中被重载

参数:

lhs, rhs:
向量容器(分别位于操作符的左侧和右侧),具有相同的模板参数(T和Alloc)。
返回值:
如果条件满足则返回true,否则为false
举例:
#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> foo(3,100) ;
    vector<int> bar(2,200);

    if(foo == bar) cout << "foo and bar are equal\n";
    if(foo != bar)cout << "foo and bar are not equal\n";
    if(foo < bar) cout << "foo is less than bar\n";
    if(foo > bar) cout << "foo is greater than bar\n";
    if(foo <= bar) cout << "foo is less than or equal to bar\n";
    if(foo >= bar) cout << "foo is greater than or equal to bar\n";

    return 0;
}

返回:

foo and bar are not equal
foo is less than bar
foo is less than or equal to bar

35)swap

template <class T, class Alloc>
  void swap (vector<T,Alloc>& x, vector<T,Alloc>& y);

交换向量内容
容器x的内容与容器y的内容交换。两个容器对象必须具有相同的类型(相同的模板参数),尽管大小可能不同

调用这个成员函数后,x中的元素是调用之前在y中的元素,y中的元素是在x中的元素。所有迭代器、引用和指针对交换后的对象仍然有效。

这是泛型算法交换的一个重载,它通过将资产的所有权相互转移到另一个容器来提高性能(例如,,容器交换对其数据的引用,而不实际执行任何元素复制或移动):它的行为就像调用了x.swap(y)

参数:

x,y:

相同类型的向量容器(即,具有相同的模板参数T和Alloc)。

返回值:

none

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    unsigned int i;
    std::vector<int> foo (3,100);   // three ints with a value of 100
    std::vector<int> bar (5,200);   // five ints with a value of 200
    std::cout << "foo contains:";
    for (std::vector<int>::iterator it = foo.begin(); it!=foo.end(); ++it)
        std::cout << ' ' << *it;
    std::cout << '\n';

    std::cout << "bar contains:";
    for (std::vector<int>::iterator it = bar.begin(); it!=bar.end(); ++it)
        std::cout << ' ' << *it;
    std::cout << '\n';

    swap(foo, bar);

    std::cout << "after swap foo contains:";
    for (std::vector<int>::iterator it = foo.begin(); it!=foo.end(); ++it)
        std::cout << ' ' << *it;
    std::cout << '\n';

    std::cout << "after swap bar contains:";
    for (std::vector<int>::iterator it = bar.begin(); it!=bar.end(); ++it)
        std::cout << ' ' << *it;
    std::cout << '\n';
    return 0;
}

返回:

foo contains: 100 100 100
bar contains: 200 200 200 200 200
after swap foo contains: 200 200 200 200 200
after swap bar contains: 100 100 100

Template specializations模版特殊化

36)vector<bool>

template < class T, class Alloc = allocator<T> > class vector; // generic template
template <class Alloc> class vector<bool,Alloc>;               // bool specialization

bool矢量
这是vector的一个特殊版本,用于bool类型的元素并对空间进行优化。

它的行为就像矢量的非特殊化版本,有以下变化:

  • 存储不一定是bool值的数组,但是库实现可以优化存储,使每个值都存储在单个bit位中。
  • 元素不是使用分配器对象构造的,但是它们的值直接设置在内部存储的适当位上。
  • 成员函数翻转flip和用于成员交换swap的新签名。
  • 一个特殊的成员类型,引用,一个类,它使用一个模拟bool引用的接口来访问容器内部存储中的各个位。相反,成员类型const_reference是普通的bool。
  • 容器使用的指针和迭代器类型不一定既不是指针也不是符合条件的迭代器,尽管它们应该模拟大多数预期的行为。

这些变化为这种特殊化提供了一个古怪的接口,并且更倾向于内存优化而不是处理(这可能适合也可能不适合您的需要)。在任何情况下,都不可能直接为bool实例化vector的未特殊化模板。避免使用不同类型(char、unsigned char)或容器(如deque)来使用包装器类型或进一步特殊化特定的分配器类型,从而避免这种情况。
bitset是一个为固定大小的位数组提供类似功能的类。

模版参数:

Alloc:

用于定义存储分配模型的分配器对象的类型。默认情况下,使用的是allocate<bool>,它定义了最简单的内存分配模型,并且是与值无关的。
别名为成员类型vector<bool>::allocator_type。

成员类型

跟特殊的差不多:

成员类型  定义  notes
value_type 第一个模版参数boool  
allocator_type 第二个模版参数Alloc 默认为allocator<bool>
reference 一个特殊成员类  
const_reference bool  
pointer 模拟指向行为的指针的类型 可转换成const_pointer
const_pointer 模拟指向const行为的指针的类型  
iterator 模拟随机访问迭代器迭代行为的类型 可转换成const_iterator
const_iterator 模拟随机访问迭代器迭代到const行为的类型  
reverse_iterator reverse_iterator<iterator>  
const_reverse_iterator reverse_iterator<const_iterator>  
difference_type 一种有符号整数类型 通常是ptrdiff_t
size_type   通常是size_t

成员类:

1》 vector<bool>::reference

class reference;

引用类型
这个嵌入的类是由非常量vector<bool>的成员在直接访问它的元素时返回的类型。它使用一个模拟对bool引用的接口来访问各个位。

其原型为:

class vector<bool>::reference {
  friend class vector;
  reference() noexcept;                                 // no public constructor
public:
  ~reference();
  operator bool () const noexcept;                      // convert to bool
  reference& operator= (const bool x) noexcept;         // assign from bool
  reference& operator= (const reference& x) noexcept;   // assign from bit
  void flip();                                          // flip bit value.
};

成员函数:

特殊化具有与非特殊化向量相同的成员函数,但data、emplace和emplace_back函数不在此特殊化中。

同时还添加了下面的两个函数:

1》flip

void flip() noexcept;

翻转位
将容器中的所有值翻转:所有true实例变为false,所有false实例变为true。

参数:

none

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<bool> mask;
    mask.push_back(true);
    mask.push_back(false);
    mask.push_back(false);
    mask.push_back(true);

    mask.flip();

    cout << boolalpha; //让返回值是true/false形式,而不是0/1
    cout << "mask contains : ";
    for(unsigned i=0; i<mask.size(); i++)
        cout << ' ' << mask.at(i);
    cout << endl;
    return 0;
}

返回:

mask contains :  false true true false

2》swap

swap containers (1)    
void swap (vector& x);
swap elements (
2) static void swap (reference ref1, reference ref2) noexcept;

交换容器或元素
第一个签名与vector::swap中描述的相同(更多信息请参见vector::swap)。
在vector<bool>上添加一个用于交换单个元素(位)的静态签名

参数:

x:

另一个vector<bool>容器。大小可能不同

ref1,ref2:

对元素的引用。
reference是一种成员类型,它访问各个元素,同时提供一个模拟bool引用的接口(有关更多信息,请参阅reference)。

返回值:

none

举例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<bool> foo;
    vector<bool> bar;

    foo.push_back(false);
    foo.push_back(true);
    foo.push_back(false);

    bar.push_back(true);
    bar.push_back(false);

    //交换元素
    foo.swap(foo[0], foo[1]);
    bar.swap(bar.front(), bar.back());
    
    cout << boolalpha; //让返回值是true/false形式,而不是0/1
    cout << "foo contains : ";
    for(unsigned i=0; i<foo.size(); i++)
        cout << ' ' << foo.at(i);
    cout << endl;
    cout << "bar contains : ";
    for(unsigned i=0; i<bar.size(); i++)
        cout << ' ' << bar.at(i);
    cout << endl;

    //交换容器
    foo.swap(bar);

    cout << boolalpha; //让返回值是true/false形式,而不是0/1
    cout << "foo contains : ";
    for(unsigned i=0; i<foo.size(); i++)
        cout << ' ' << foo.at(i);
    cout << endl;
    cout << "bar contains : ";
    for(unsigned i=0; i<bar.size(); i++)
        cout << ' ' << bar.at(i);
    cout << endl;

    return 0;
}

返回:

foo contains :  true false false
bar contains :  false true
foo contains :  false true
bar contains :  true false false

Non-member class specializations

1》hash<vector<bool>>

template <class T> struct hash;                             // unspecialized
template <class Alloc> struct hash <vector<bool,Alloc>>;    // vector<bool>

向量的散列向量
一元函数对象类,它定义了vector<bool>的hash特殊化。

函数调用返回一个基于整个向量的散列值:散列值是一个仅依赖于其参数的值,对于相同的参数(对于给定的程序执行)总是返回相同的值。返回的值与另一个参数返回的值有很小的可能相同(碰撞的几率接近1/numeric_limits<size_t>::max)。
这允许使用vector<bool>对象作为无序容器(如unordered_set或unordered_map)的键

有关其他信息,请参见散列 hash

成员函数:

operator()

返回其参数的散列值,作为类型size_t的值。
size_t是一个无符号整数类型。

猜你喜欢

转载自www.cnblogs.com/wanghui-garcia/p/11679969.html