C++ STL標準庫std::vector的使用詳解

1. 簡介

vector 是表示可以改變大小的數組的序列容器。

與arrays一樣,vector 對元素使用連續的存儲位置,這意味著也可以使用指向其元素的常規指針上的偏移量來訪問它們的元素,並且與在數組中一樣高效。但是與arrays不同,它們的大小可以動態變化,容器會自動處理它們的存儲。

在內部,vector 使用一個動態分配的數組來存儲它們的元素。這個數組可能需要重新分配,以便在插入新元素時增大大小,這意味著分配一個新數組並將所有元素移動到其中。就處理時間而言,這是一項相對昂貴的任務,因此,vector 不會在每次向容器添加元素時重新分配。

相反,vector 容器可以分配一些額外的存儲空間以適應可能的增長,因此容器的實際容量可能大於嚴格需要的存儲容量(即容器的大小)。庫可以實現不同的增長策略,以平衡內存使用和重新分配,但在任何情況下,重新分配隻應在大小的對數增長間隔進行,以便在向量末尾插入單個元素可以提供攤餘的恒定時間復雜度(請參閱“推後”)。

因此,與arrays相比,vector 消耗更多的內存,以換取管理存儲和以高效方式動態增長的能力。

與其他動態序列容器(deques、list和forward_list)相比,vectors可以非常高效地訪問其元素(就像數組一樣),並相對高效地從其末尾添加或刪除元素。對於涉及在結尾以外的位置插入或刪除元素的操作,它們的性能比其他操作差,迭代器和引用的一致性也不如列表和轉發列表。

2. 使用示例

#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();
}

在這裡插入圖片描述

3. 構造、析構、賦值

在這裡插入圖片描述

3.1 std::vector::vector 構造函數

在這裡插入圖片描述

(1) 空容器構造函數
(默認構造函數)構造一個沒有元素的空容器。

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

(3) 范圍構造函數
構造一個包含與range[first,last]一樣多的元素的容器,每個元素的emplace都是按照相同的順序從該范圍中的相應元素構造的。

(4) 復制構造函數(並使用分配器復制)
以相同的順序構造一個容器,其中包含x中每個元素的副本。

(5) 移動構造函數(並使用分配器移動)
構造一個獲取x元素的容器。
如果alloc被指定並且與x的分配器不同,那麼元素將被移動。否則,就不會構建任何元素(它們的所有權被直接轉移)。
x處於未指定但有效的狀態。

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

#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();
}

在這裡插入圖片描述

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;
}

在這裡插入圖片描述

4. 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;
}

在這裡插入圖片描述

5. 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;
}

在這裡插入圖片描述

6. 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;
}

在這裡插入圖片描述

7. 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;
}

在這裡插入圖片描述

 到此這篇關於C++ STL標準庫std::vector的使用詳解的文章就介紹到這瞭,更多相關C++ STL std::vector內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: