C++ STL标准库:std::vector 使用详解

文章目录

  1. 简介
  2. 使用示例
  3. 构造、析构、赋值
    3.1 std::vector::vector 构造函数
    3.2 std::vector::~vector 析构函数
    3.3 std::vector::operator= “=”符号
  4. Iterators 迭代器
    4.1 std::vector::begin
    4.2 std::vector::end
    4.3 std::vector::rbegin
    4.4 std::vector::rend
    4.5 std::vector::cbegin (C++11)
    4.6 std::vector::cend(C++11)
    4.7 std::vector::crbegin (C++11)
    4.8 std::vector::crend(C++11)
  5. Capacity 容量
    5.1 std::vector::size 查询大小
    5.2 std::vector::max_size
    5.3 std::vector::resize
    5.4 std::vector::capacity
    5.5 std::vector::empty
    5.6 std::vector::reserve
    5.7 std::vector::shrink_to_fit (C++11)
  6. Element access 元素访问
    6.1 std::vector::operator[]
    6.2 std::vector::at
    6.3 std::vector::front
    6.4 std::vector::back
    6.5 std::vector::data (C++11)
  7. Modifiers 内容修改
    7.1 std::vector::assign
    7.2 std::vector::push_back
    7.3 std::vector::pop_back
    7.4 std::vector::insert
    7.5 std::vector::erase
    7.6 std::vector::swap
    7.7 std::vector::clear
    7.8 std::vector::emplace(C++11)
    7.9 std::vector::emplace_back (C++11)
  8. 简介
    vector 是表示可以改变大小的数组的序列容器。

与arrays一样,vector 对元素使用连续的存储位置,这意味着也可以使用指向其元素的常规指针上的偏移量来访问它们的元素,并且与在数组中一样高效。但是与arrays不同,它们的大小可以动态变化,容器会自动处理它们的存储。

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

相反,vector 容器可以分配一些额外的存储空间以适应可能的增长,因此容器的实际容量可能大于严格需要的存储容量(即容器的大小)。库可以实现不同的增长策略,以平衡内存使用和重新分配,但在任何情况下,重新分配只应在大小的对数增长间隔进行,以便在向量末尾插入单个元素可以提供摊余的恒定时间复杂度(请参阅“推后”)。

因此,与arrays相比,vector 消耗更多的内存,以换取管理存储和以高效方式动态增长的能力。

与其他动态序列容器(deques、list和forward_list)相比,vectors可以非常高效地访问其元素(就像数组一样),并相对高效地从其末尾添加或删除元素。对于涉及在结尾以外的位置插入或删除元素的操作,它们的性能比其他操作差,迭代器和引用的一致性也不如列表和转发列表。

  1. 使用示例
#include <iostream>
#include <string>
#include <vector>

using namespace std;

void main()
{
    
    vector<string>myvt;     // 定义模板类对象
    myvt.reserve(4);        // 设置大小
    cout << "The size is 4." << endl;

    // 添加内容
    myvt.push_back("1. Beijing City.");
    myvt.push_back("2. Tianjin City.");
    myvt.push_back("3. Shanghai City.");
    myvt.push_back("4. Chongqing City.");

    // 打印内容
    vector<string>::iterator it;
    for(it=myvt.begin();it!=myvt.end();it++)
    {
        cout<<*it<<endl;
    }

    int m=myvt.size();          // 获取大小
    int n=myvt.capacity();      // 获取容量
    int m1=myvt.max_size();     // 获取最大大小
    cout<<"vector:myvt, size is "<<m<<endl;
    cout<<"vector:myvt, capacity is "<<n<<endl;
    cout<<"vector:myvt, maxsize is "<<m1<<endl;

    myvt.resize(10);    //重设大小
    cout<<"resize: 10."<<endl;
    int n1=myvt.capacity();
    int n2=myvt.size();
    cout<<"vector:myvt, capacity is "<<n1<<endl;
    cout<<"vector:myvt, size is "<<n2<<endl;

    // 如果为空值则打印 * 号
    for(it=myvt.begin();it!=myvt.end();it++)
    {
        if(*it=="")
            cout<<"******"<<endl;
        cout<<*it<<endl;
    }
    cin.get();
}
  1. 构造、析构、赋值

3.1 std::vector::vector 构造函数

(1) 空容器构造函数
(默认构造函数)构造一个没有元素的空容器。

(2) 填充构造函数
用n个元素构造一个容器。每个元素都是val的副本(如果提供)。

(3) 范围构造函数
构造一个包含与range[first,last]一样多的元素的容器,每个元素的emplace都是按照相同的顺序从该范围中的相应元素构造的。

(4) 复制构造函数(并使用分配器复制)
以相同的顺序构造一个容器,其中包含x中每个元素的副本。

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

(6) 初始化列表构造
以相同的顺序构造一个容器,其中包含il中每个元素的副本。

// 构造 vectors
#include <iostream>
#include <vector>

int main ()
{
  // 按上述顺序使用的构造函数:
  std::vector<int> first;                                // 整数的空向量
  std::vector<int> second (4,100);                       // 值为100的四个整数
  std::vector<int> third (second.begin(),second.end());  // 遍历构造
  std::vector<int> fourth (third);                       // 赋值构造

  // 迭代器构造函数也可用于从数组构造:
  int myints[] = {16,2,77,29};
  std::vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );

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

  return 0;
}

3.2 std::vector::~vector 析构函数

~vector();
Destroys the container object.

3.3 std::vector::operator= “=”符号

// vector assignment
#include <iostream>
#include <vector>

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

  bar = foo;                    // bar: 0 0 0
  foo = std::vector<int>();     // foo:

  std::cout << "Size of foo: " << int(foo.size()) << '\n';
  std::cout << "Size of bar: " << int(bar.size()) << '\n';
  return 0;
}
  1. Iterators 迭代器

4.1 std::vector::begin
返回指向容器中第一个元素的迭代器。

返回指向向量中第一个元素的迭代器。

注意,与member vector::front不同,member vector::front返回对第一个元素的引用,该函数返回指向该元素的随机访问迭代器。

如果容器为空,则返回的迭代器值不应被取消引用。

4.2 std::vector::end
返回指向容器最后一个元素所在位置后一个位置的迭代器,通常和 begin() 结合使用。

返回一个迭代器,该迭代器引用向量容器中过去的结束元素。

过去的结束元素是理论元素,它将跟随向量中的最后一个元素。它不指向任何元素,因此不应被取消引用。

由于标准库的函数使用的范围不包括其结束迭代器所指向的元素,因此此函数通常与vector::begin结合使用,以指定一个包含容器中所有元素的范围。

如果容器为空,此函数将返回与vector::begin相同的值。

// vector::begin/end
#include <iostream>
#include <vector>

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

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

  return 0;
}

4.3 std::vector::rbegin
返回指向最后一个元素的迭代器。

返回指向向量中最后一个元素的反向迭代器(即它的反向开始)。

反向迭代器向后迭代:增加它们会将它们移向容器的开头。

rbegin指向成员端将指向的元素之前的元素。

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

4.4 std::vector::rend
返回指向第一个元素所在位置前一个位置的迭代器。

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

// vector::rbegin/rend
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> myvector(5);  // 5个默认构造整数

    int i = 0;

    std::vector<int>::reverse_iterator rit = myvector.rbegin();
    for (; rit != myvector.rend(); ++rit)
        *rit = ++i;

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

    return 0;
}

4.5 std::vector::cbegin (C++11)
和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。

const_iterator cbegin() const noexcept;

返回指向容器中第一个元素的常量迭代器。

const_iterator是指向const内容的迭代器。这个迭代器可以增加和减少(除非它本身也是const),就像vector::begin返回的迭代器一样,但是它不能用来修改它指向的内容,即使vector对象本身不是const。

如果容器为空,则返回的迭代器值不应被取消引用。

4.6 std::vector::cend(C++11)
和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。

const_iterator cend() const noexcept;

返回一个指向容器中结束元素的常量迭代器。

const_iterator是指向const内容的迭代器。这个迭代器可以增加和减少(除非它本身也是const),就像vector::end返回的迭代器一样,但是它不能用来修改它指向的内容,即使vector对象本身不是const。

如果容器为空,此函数将返回与vector::cbegin相同的值。

返回的值不应被取消引用。

// vector::cbegin/cend
#include <iostream>
#include <vector>

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

  std::cout << "myvector contains:";

  for (auto it = myvector.cbegin(); it != myvector.cend(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

4.7 std::vector::crbegin (C++11)
和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。

const_reverse_iterator crbegin() const noexcept;

返回一个const_reverse_迭代器,指向容器中的最后一个元素(即它的反向开始)。

4.8 std::vector::crend(C++11)
和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。

const_reverse_iterator crend() const noexcept;

返回一个const_reverse_迭代器,该迭代器指向容器中第一个元素之前的理论元素(该元素被视为其反向端)。

// vector::crbegin/crend
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector = {1,2,3,4,5};

  std::cout << "myvector backwards:";
  for (auto rit = myvector.crbegin(); rit != myvector.crend(); ++rit)
    std::cout << ' ' << *rit;
  std::cout << '\n';

  return 0;
}
  1. Capacity 容量

5.1 std::vector::size 查询大小
返回实际元素个数。

size_type size() const noexcept;

返回矢量中的元素数。
这是向量中保存的实际对象的数量,它不一定等于它的存储容量。

// vector::size
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myints;
  std::cout << "0. size: " << myints.size() << '\n';

  for (int i=0; i<10; i++) myints.push_back(i);
  std::cout << "1. size: " << myints.size() << '\n';

  myints.insert (myints.end(),10,100);
  std::cout << "2. size: " << myints.size() << '\n';

  myints.pop_back();
  std::cout << "3. size: " << myints.size() << '\n';

  return 0;
}

5.2 std::vector::max_size
返回元素个数的最大值。这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。

size_type max_size() const noexcept;

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

// comparing size, capacity and max_size
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> myvector;

    // 向myvector中添加内容
    for (int i = 0; i < 100; i++) myvector.push_back(i);

    std::cout << "size: " << myvector.size() << "\n";
    std::cout << "capacity: " << myvector.capacity() << "\n";
    std::cout << "max_size: " << myvector.max_size() << "\n";
    return 0;
}

5.3 std::vector::resize
改变实际元素的个数。

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

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

// resizing vector
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> myvector;

    // 初始化内容
    for (int i = 1; i < 10; i++) myvector.push_back(i);

    myvector.resize(5);
    myvector.resize(8, 100);
    myvector.resize(12);

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

    return 0;
}

5.4 std::vector::capacity
返回当前容量。

size_type capacity() const noexcept;

返回当前为向量分配的存储空间的大小,以元素表示。
这个容量不一定等于向量大小。它可以相等或更大,额外的空间可以适应增长,而不需要在每次插入时重新分配。
请注意,此容量不假定对向量大小有限制。当这个容量耗尽并且需要更多容量时,容器会自动扩展它(重新分配它的存储空间)。向量大小的理论限制由成员max_size给出。
可以通过调用成员vector::reserve显式更改向量的容量。

// comparing size, capacity and max_size
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector;

  // set some content in the vector:
  for (int i=0; i<100; i++) myvector.push_back(i);

  std::cout << "size: " << (int) myvector.size() << '\n';
  std::cout << "capacity: " << (int) myvector.capacity() << '\n';
  std::cout << "max_size: " << (int) myvector.max_size() << '\n';
  return 0;
}

5.5 std::vector::empty
** 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。**

bool empty() const noexcept;

返回向量是否为空(即其大小是否为0)。
此函数不会以任何方式修改容器。若要清除向量的内容,请参见vector::clear。

// vector::empty
#include <iostream>
#include <vector>

int main ()
{
  std::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();
  }

  std::cout << "total: " << sum << '\n';

  return 0;
}

5.6 std::vector::reserve
增加容器的容量。

void reserve (size_type n);

要求向量容量至少足以包含n个元素。
如果n大于当前向量容量,函数将使容器重新分配其存储空间,将其容量增加到n(或更大)。
在所有其他情况下,函数调用不会导致重新分配,向量容量也不会受到影响。
此函数对向量大小没有影响,并且不能更改其元素。

// vector::reserve
#include <iostream>
#include <vector>

int main()
{
    std::vector<int>::size_type sz;

    std::vector<int> foo;
    sz = foo.capacity();
    std::cout << "making foo grow:\n";
    for (int i = 0; i < 100; ++i) {
        foo.push_back(i);
        if (sz != foo.capacity()) {
            sz = foo.capacity();
            std::cout << "容量已更改: " << sz << '\n';
        }
    }

    std::vector<int> bar;
    sz = bar.capacity();
    bar.reserve(100);   // 这是与上面的foo唯一的区别
    std::cout << "making bar grow:\n";
    for (int i = 0; i < 100; ++i) {
        bar.push_back(i);
        if (sz != bar.capacity()) {
            sz = bar.capacity();
            std::cout << "容量已更改: " << sz << '\n';
        }
    }
    return 0;
}

5.7 std::vector::shrink_to_fit (C++11)
将内存减少到等于当前元素实际所使用的大小。

void shrink_to_fit();

请求容器减小其容量以适合其大小。
请求是非绑定的,容器实现可以自由地进行优化,使向量的容量大于其大小。
这可能会导致重新分配,但对向量大小没有影响,并且无法更改其元素。

// vector::shrink_to_fit
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> myvector(100);
    std::cout << "1. myvector的容量: " << myvector.capacity() << '\n';

    myvector.resize(10);
    std::cout << "2. myvector的容量: " << myvector.capacity() << '\n';

    myvector.shrink_to_fit();
    std::cout << "3. myvector的容量: " << myvector.capacity() << '\n';

    return 0;
}
  1. Element access 元素访问

6.1 std::vector::operator[]
重载了 [ ] 运算符,可以向访问数组中元素那样,通过下标即可访问甚至修改 vector 容器中的元素。

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

返回对向量容器中位置n处元素的引用。
类似的成员函数vector :: at与该运算符具有相同的行为,不同之处在于vector :: at已进行边界检查,并通过引发out_of_range异常来发出信号,以指示请求的位置是否超出范围。
可移植程序永远不要使用参数n超出范围来调用此函数,因为这会导致未定义的行为。

// vector::operator[]
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> myvector(10);   // 10个零初始化元素

    std::vector<int>::size_type sz = myvector.size();

    // 分配一些值:
    for (unsigned i = 0; i < sz; i++) myvector[i] = i;

    // reverse vector using operator[]:
    for (unsigned i = 0; i < sz / 2; i++)
    {
        int temp;
        temp = myvector[sz - 1 - i];
        myvector[sz - 1 - i] = myvector[i];
        myvector[i] = temp;
    }

    std::cout << "myvector contains:";
    for (unsigned i = 0; i < sz; i++)
        std::cout << ' ' << myvector[i];
    std::cout << '\n';

    return 0;
}

6.2 std::vector::at
使用经过边界检查的索引访问元素。

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

返回对向量中位置n处元素的引用。
该函数自动检查n是否在向量中的有效元素的范围内,如果不是,则抛出out_of_range异常(即,如果n大于或等于其大小)。 这与成员operator []不同,后者不检查边界。

// vector::at
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> myvector(10);   // 10个零初始化的整数

    // 分配一些值:
    for (unsigned i = 0; i < myvector.size(); i++)
        myvector.at(i) = i;

    std::cout << "myvector contains:";
    for (unsigned i = 0; i < myvector.size(); i++)
        std::cout << ' ' << myvector.at(i);
    std::cout << '\n';

    return 0;
}

6.3 std::vector::front
返回第一个元素的引用。

      reference front();
const_reference front() const;

返回对向量中第一个元素的引用。
与成员vector :: begin返回一个迭代器到同一元素不同,此函数返回直接引用。
在空容器上调用此函数会导致未定义的行为。

// vector::front
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> myvector;

    myvector.push_back(78);
    myvector.push_back(16);

    // 现在前排等于78,后排等于16

    myvector.front() -= myvector.back();

    std::cout << "myvector.front() is now " << myvector.front() << '\n';

    return 0;
}

6.4 std::vector::back
返回最后一个元素的引用。

      reference back();
const_reference back() const;

返回对向量中最后一个元素的引用。
与成员向量::: end返回仅在此元素之后的迭代器不同,该函数返回直接引用。
在空容器上调用此函数会导致未定义的行为。

// vector::back
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector;

  myvector.push_back(10);

  while (myvector.back() != 0)
  {
    myvector.push_back ( myvector.back() -1 );
  }

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

  return 0;
}

6.5 std::vector::data (C++11)
返回指向容器中第一个元素的指针。

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

返回指向向量内部用于存储其拥有的元素的内存数组的直接指针。
由于保证向量中的元素以与向量表示相同的顺序存储在连续的存储位置中,因此检索到的指针可以偏移以访问数组中的任何元素。

// vector::data
#include <iostream>
#include <vector>

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

  int* p = myvector.data();

  *p = 10;
  ++p;
  *p = 20;
  p[2] = 100;

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

  return 0;
}
  1. Modifiers 内容修改

7.1 std::vector::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);

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

在范围版本(1)中,新内容是从第一个到最后一个范围内的每个元素以相同顺序构造的元素。
在填充版本(2)中,新内容是n个元素,每个元素都初始化为val的副本。
在初始化程序列表版本(3)中,新内容是作为初始化程序列表传递的值的副本,顺序相同。
如果发生重新分配,则使用内部分配器(通过其特征)分配和取消分配存储。 它还可用于销毁所有现有元素,并构造新元素。

// vector assign
#include <iostream>
#include <vector>

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

    first.assign(7, 100);             // 7个整数,值为100

    std::vector<int>::iterator it;
    it = first.begin() + 1;

    second.assign(it, first.end() - 1); // 从第2个值到到数第1个值

    int myints[] = { 1776,7,4 };
    third.assign(myints, myints + 3);   // 从数组分配

    std::cout << "Size of first: " << int(first.size()) << '\n';
    std::cout << "Size of second: " << int(second.size()) << '\n';
    std::cout << "Size of third: " << int(third.size()) << '\n';
    return 0;
}

7.2 std::vector::push_back
在序列的尾部添加一个元素。

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

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

// vector::push_back
#include <iostream>
#include <vector>

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

    std::cout << "请输入一些整数 (输入0结束):\n";

    do {
        std::cin >> myint;
        myvector.push_back(myint);
    } while (myint);

    std::cout << "myvector stores " << int(myvector.size()) << " numbers.\n";

    return 0;
}

7.3 std::vector::pop_back
移出序列尾部的元素。

void pop_back();

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

// vector::pop_back
#include <iostream>
#include <vector>

int main()
{
    std::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();
    }

    std::cout << "myvector的元素总计为: " << sum << '\n';

    return 0;
}

7.4 std::vector::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);

通过在元素前面的指定位置插入新元素来扩展向量,有效地通过插入元素的数量增加容器的大小。
这将导致当且仅当新矢量大小超过当前矢量容量时自动重新分配分配的存储空间。
因为向量使用数组作为其底层存储,所以在向量结尾以外的位置插入元素会导致容器将位置之后的所有元素重新定位到新位置。与其他类型的序列容器(如list或forward_list)对同一操作执行的操作相比,这通常是一种低效的操作。
参数决定插入多少个元素以及它们被初始化到哪些值:

// inserting into a vector
#include <iostream>
#include <vector>

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

    it = myvector.begin();
    it = myvector.insert(it, 200);

    myvector.insert(it, 2, 300);

    // "it" 不再有效,请换一个新的:
    it = myvector.begin();

    std::vector<int> anothervector(2, 400);
    myvector.insert(it + 2, anothervector.begin(), anothervector.end());

    int myarray[] = { 501,502,503 };
    myvector.insert(myvector.begin(), myarray, myarray + 3);

    std::cout << "myvector contains:";
    for (it = myvector.begin(); it < myvector.end(); it++)
        std::cout << ' ' << *it;
    std::cout << '\n';

    return 0;
}

7.5 std::vector::erase
移出一个元素或一段元素。

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

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

// erasing from vector
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> myvector;

    // set some values (from 1 to 10)
    for (int i = 1; i <= 10; i++) myvector.push_back(i);

    // erase the 6th element
    myvector.erase(myvector.begin() + 5);

    // erase the first 3 elements:
    myvector.erase(myvector.begin(), myvector.begin() + 3);

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

    return 0;
}

7.6 std::vector::swap
交换两个容器的所有元素。

void swap (vector& x);

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

// swap vectors
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> foo(3, 100);   // 100 100 100
    std::vector<int> bar(5, 200);   // 200 200 200 200 200

    foo.swap(bar);

    std::cout << "foo contains:";
    for (unsigned i = 0; i < foo.size(); i++)
        std::cout << ' ' << foo[i];
    std::cout << '\n';

    std::cout << "bar contains:";
    for (unsigned i = 0; i < bar.size(); i++)
        std::cout << ' ' << bar[i];
    std::cout << '\n';

    return 0;
}

7.7 std::vector::clear

移出所有的元素,容器大小变为 0。

void clear() noexcept;

从向量中移除所有元素(已销毁),使容器的大小为0。
不能保证会发生重新分配,也不能保证由于调用此函数而改变向量容量。强制重新分配的典型替代方法是使用swap:

// clearing vectors
#include <iostream>
#include <vector>

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

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

  myvector.clear();
  myvector.push_back (1101);
  myvector.push_back (2202);

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

  return 0;
}

7.8 std::vector::emplace(C++11)
在指定的位置直接生成一个元素。
emplace() 每次只能插入一个元素,而不是多个。 emplace() 在插入元素时,是在容器的指定位置直接构造元素,而不是先单独生成,再将其复制(或移动)到容器中。因此,在实际使用中,推荐大家优先使用 emplace()。

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

通过在位置插入新元素来扩展容器。 这个新元素是使用args作为其构造参数构建的。
这有效地将容器尺寸增加了一个。
当且仅当新向量大小超过当前向量容量时,才会自动重新分配已分配的存储空间。
由于向量使用数组作为其基础存储,因此在向量末端以外的位置插入元素会导致容器将位置后的所有元素都移动一个到其新位置。 与其他类型的序列容器(例如list或forward_list)执行的操作相比,这通常是一种低效的操作。 请参阅emplace_back以获取直接在末尾扩展容器的成员函数。
通过转发带有args的allocator_traits :: construct来就地构建元素。
存在一个类似的成员函数,插入,该成员函数将现有对象复制或移动到容器中。

// vector::emplace
#include <iostream>
#include <vector>

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

  auto it = myvector.emplace ( myvector.begin()+1, 100 );
  myvector.emplace ( it, 200 );
  myvector.emplace ( myvector.end(), 300 );

  std::cout << "myvector contains:";
  for (auto& x: myvector)
    std::cout << ' ' << x;
  std::cout << '\n';

  return 0;
}

7.9 std::vector::emplace_back (C++11)
在序列尾部生成一个元素。
emplace_back() 的执行效率比 push_back() 高。因此,在实际使用时,建议大家优先选用 emplace_back()。

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

在最后构造并插入元素在向量的最后一个元素之后,在向量的末尾插入一个新元素。 使用args作为其构造函数的参数在适当的位置构造此新元素。
这有效地将容器大小增加了一个,这会导致分配的存储空间自动重新分配,前提是(且仅当)新向量大小超过当前向量容量时。
通过转发带有args的allocator_traits :: construct来就地构建元素。
存在类似的成员函数push_back,该函数将现有对象复制或移动到容器中。

// vector::emplace_back
#include <iostream>
#include <vector>

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

  myvector.emplace_back (100);
  myvector.emplace_back (200);

  std::cout << "myvector contains:";
  for (auto& x: myvector)
    std::cout << ' ' << x;
  std::cout << '\n';

  return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容