STL中的动态数组类

std::vector的特点

  • 在数组末尾添加元素所需要的时间是固定的
  • 在数组中间添加或是删除元素所需的时间和该元素后面的元素个数成正比
  • 存储的元素数是动态的,而vector类负责内存管理

典型的vector操作

实例化vector

#include <vector>

int main ()
{
   // vector of integers
   std::vector<int> integers;// 使用了默认的构造函数
   // 编译器暂时还不支持这种初始化的方法,这是C++11引入的列表初始化
   // vector with 3 elements initialized using C++11 list initialization
   //std::vector<int> initVector{ 202, 2017, -1 };

   // Instantiate a vector with 10 elements (it can still grow)
   std::vector<int> tenElements (10); // 使编程人员知道vector至少包含10个元素

   // Instantiate a vector with 10 elements, each initialized to 90
   std::vector<int> tenElemInit (10, 90);

   // Instantiate one vector and initialize it to the contents of another
   std::vector<int> copyVector (tenElemInit);// 使用一个vecto实例化另一个vector

   // Vector initialized to 5 elements from another using iterators
   // 将cbegin()换成begin(),复制vector对象的一部分
   std::vector<int> partialCopy (tenElements.begin(),
                                 tenElements.begin() + 5);

   return 0;
}

使用push_back()在末尾插入元素

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

int main ()
{
   vector <int> integers;

   // Insert sample integers into the vector:
   integers.push_back (50);
   integers.push_back (1);
   integers.push_back (987);
   integers.push_back (1001);

   cout << "The vector contains ";
   cout << integers.size () << " Elements" << endl;

   return 0;
}
STL中的动态数组类
运行的结果

用push_back在对象integers的末尾插入元素,最后调用size()方法来检验结果。

列表初始化

C++11通过std::initialize_list<>支持列表初始化,让您能够像处理静态数组那样,在实例化vector的同时初始化其元素。

vector<int> integers = {50, 1, 987, 1001};
//alternatively
vector<int> vecMoreIntegers {50, 1, 987, 1001};

使用insert()在指定位置插入元素

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


// for older C++ compilers (non C++11 compliant)
void DisplayVector(const vector<int>& inVec)
{
   for (vector<int>::const_iterator element = inVec.begin ();
        element != inVec.end ();
        ++ element )
      cout << *element << ' ';

   cout << endl;
}

/*
void DisplayVector(const vector<int>& inVec)
{
   for(auto element = inVec.cbegin();  // auto and cbegin() are C++11
       element != inVec.cend (); // cend() is new in C++11
       ++ element )
      cout << *element << ' ';

   cout << endl;
}
*/
int main ()
{
   // Instantiate a vector with 4 elements, each initialized to 90
   vector <int> integers (4, 90);

   cout << "The initial contents of the vector: ";
   DisplayVector(integers);

   // Insert 25 at the beginning
   integers.insert (integers.begin (), 25);

   // Insert 2 numbers of value 45 at the end
   integers.insert (integers.end (), 2, 45);

   cout << "Vector after inserting elements at beginning and end: ";
   DisplayVector(integers);

   // Another vector containing 2 elements of value 30
   vector <int> vecAnother (2, 30);

   // Insert two elements from another container in position [1]
   integers.insert (integers.begin () + 1,
      vecAnother.begin (), vecAnother.end ());

   cout << "Vector after inserting contents from another vector: ";
   cout << "in the middle:" << endl;
   DisplayVector(integers);

   return 0;
}
STL中的动态数组类
运行结果

书里面的代码还是很良心的,还考虑到了不支持C++11的老编译器,不错不错!

使用数组的语法访问vector中的元素

#include <iostream>
#include <vector>

int main ()
{
   using namespace std;
   //vector <int> integers{ 50, 1, 987, 1001 };
   vector <int> integers;
   integers.push_back(50);
   integers.push_back(1);
   integers.push_back(987);
   integers.push_back(1001);
   for (size_t index = 0; index < integers.size (); ++index)
   {
      cout << "Element[" << index << "] = " ;
      cout << integers[index] << endl;
   }

   integers[2] = 2011; // change value of 3rd element
   cout << "After replacement: " << endl;
   cout << "Element[2] = " << integers[2] << endl;

   return 0;
}
STL中的动态数组类
运行结果

vector中应当是重载了下标运算符,所以可以用[ ]的方式访问vector中的元素。使用[ ]的方式访问vector中的元素时,面临的风险与访问数组元素相同,即不超出容器的边界。更安全的方法是使用成员函数at( )。

// get element at position 2
vector <int> integers;
cout << integers.at(2);

用指针语法访问vector中的元素

#include <iostream>
#include <vector>

int main ()
{
   using namespace std;
   //vector <int> integers{ 50, 1, 987, 1001 };
   vector <int> integers;
   integers.push_back(50);
   integers.push_back(1);
   integers.push_back(987);
   integers.push_back(1001);
   //这是没有常迭代器?
   vector <int>::iterator element = integers.begin ();
   // auto element = integers.cbegin (); // same as above, using auto

   while (element != integers.end ())
   {
      size_t index = distance (integers.begin (), element);

      cout << "Element at position ";
      cout << index << " is: " << *element << endl;

      // move to the next element
      ++ element;
   }

   return 0;
}
STL中的动态数组类
运行结果

删除vector中的元素

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

template <typename T>
void DisplayVector(const vector<T>& inVec)
{
   for(vector<int>::const_iterator element = inVec.begin();  // auto & cbegin() are C++11
       element != inVec.end (); // cend() is C++11
       ++ element )
     cout << *element << ' ';

   cout << endl;
}

int main ()
{
   vector<int> integers;

   // Insert sample integers into the vector:
   integers.push_back (50);
   integers.push_back (1);
   integers.push_back (987);
   integers.push_back (1001);

   cout << "Vector contains " << integers.size () << " elements: ";
   DisplayVector(integers);

   // Erase one element at the end
   integers.pop_back ();

	cout << "After a call to pop_back()" << endl;
   cout << "Vector contains " << integers.size () << " elements: ";
   DisplayVector(integers);

   return 0;
}
STL中的动态数组类
运行结果

理解vector的大小和容量

#include <iostream>
#include <vector>

int main ()
{
   using namespace std;

   // Instantiate a vector object that holds 5 integers of default value
   vector <int> integers (5);

   cout << "Vector of integers was instantiated with " << endl;
   cout << "Size: " << integers.size ();
   cout << ", Capacity: " <<  integers.capacity () << endl;

   // Inserting a 6th element in to the vector
   integers.push_back (666);

   cout << "After inserting an additional element... " << endl;
   cout << "Size: " << integers.size ();
   cout << ", Capacity: " <<  integers.capacity () << endl;

   // Inserting another element
   integers.push_back (777);

   cout << "After inserting yet another element... " << endl;
   cout << "Size: " << integers.size ();
   cout << ", Capacity: " <<  integers.capacity () << endl;

   integers.clear();

   return 0;
}
STL中的动态数组类
运行结果

实例化一个包含5个整型对象的vector,这些整型对象使用默认值0,它的大小和容量在实例化后相等。这时大小和容量相等,这表明vector的容量已经用完了,再次插入元素将导致vector重新分配其内部缓冲区,复制现有的元素再插入新值。

PS:在重新分配vector内部缓冲区时提前增加容量方面,C++标准没有做任何规定,因此性能的优化程度取决于STL的实现。

STL的deque类

#include <deque>
#include <iostream>
#include <algorithm>

int main ()
{
   using namespace std;

   // Define a deque of integers
   deque<int> intDeque;

   // Insert integers at the bottom of the array
   intDeque.push_back (3);
   intDeque.push_back (4);
   intDeque.push_back (5);

   // Insert integers at the top of the array
   intDeque.push_front (2);
   intDeque.push_front (1);
   intDeque.push_front (0);

   cout << "The contents of the deque after inserting elements ";
   cout << "at the top and bottom are:" << endl;

   // Display contents on the screen
   for (size_t count = 0
      ; count < intDeque.size ()
      ; ++ count )
   {
      cout << "Element [" << count << "] = ";
      cout << intDeque [count] << endl;
   }

   cout << endl;

   // Erase an element at the top
   intDeque.pop_front ();

   // Erase an element at the bottom
   intDeque.pop_back ();

   cout << "The contents of the deque after erasing an element ";
   cout << "from the top and bottom are:" << endl;

   // Display contents again: this time using iterators
   // if on older compilers, remove auto and uncomment next line
   // deque <int>::iterator element;
   for (deque <int>::iterator element = intDeque.begin ()
      ; element != intDeque.end ()
      ; ++ element )
   {
      size_t Offset = distance (intDeque.begin (), element);
      cout << "Element [" << Offset << "] = " << *element << endl;
   }

   intDeque.clear();
   if (intDeque.empty())
      cout << "The container is now empty" << endl;

   return 0;
}
STL中的动态数组类
运行结果

deque和vector比起来,它除了尾插,还可以头插。clear()方法可以删除容器中的所有元素。