为了支持快速的随机访问,vector容器的元素以连续方式存放。设想一下,vector每添加一个元素,为了满足连续存放的特性,需要重新配置、移动元素、释放原空间,这样性能上难以接受。因此STL实现者在对vector进行内存分配时,其实际分配的容量要比当前所需的空间多一些。也就是说,vector容器预留了一些额外的存储区,用于存放新添加的元素,这样就不必为每个新元素就重新分配整个容器的内存空间。
vector容器的内存空间只会增长,不会减小,每当其不得不分配新的存储空间时,会以一定的分配策略实现重新分配。
#include迭代器#include using namespace std; void printVector(vector & vec) { for (vector ::iterator it = vec.begin(); it != vec.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { vector vec; cout << "size capacity" << endl; for (int i = 0; i < 30; i++) { cout << vec.size() << " " << vec.capacity() << endl; vec.push_back(i); } } void test02() { vector vec = { 0,1,2,3,4,5,6,7,8,9 }; if (vec.empty()) { cout << "vector为空" << endl; } else { cout << "capacity = " << vec.capacity() << endl; // 10 cout << "size = " << vec.size() << endl; // 10 } // 重新指定大小 // 若指定的更大,默认用0填充,其重载版本第二个参数指定填充值 vec.resize(15); printVector(vec); // 0 1 2 3 4 5 6 7 8 9 0 0 0 0 0 cout << "capacity = " << vec.capacity() << endl; // 15 cout << "size = " << vec.size() << endl; // 15 // 重新指定大小 // 若指定的更小,超出的部分元素被删除 vec.resize(5); printVector(vec); // 0 1 2 3 4 cout << "capacity = " << vec.capacity() << endl; // 15 cout << "size = " << vec.size() << endl; // 5 // 【C++11】vector容器的capacity缩小为size vec.shrink_to_fit(); cout << "capacity = " << vec.capacity() << endl; // 5 cout << "size = " << vec.size() << endl; // 5 // 清空内容,但不释放内存 vec.clear(); cout << "capacity = " << vec.capacity() << endl; // 5 cout << "size = " << vec.size() << endl; // 0 } void test03() { vector vec = { 0,1,2,3,4,5,6,7,8,9 }; cout << "capacity = " << vec.capacity() << endl; // 10 cout << "size = " << vec.size() << endl; // 10 vec.resize(5); cout << "capacity = " << vec.capacity() << endl; // 10 cout << "size = " << vec.size() << endl; // 5 // vector (vec)是一个匿名对象 cout << "capacity = " << vector (vec).size() << endl; // 5 cout << "size = " << vector (vec).capacity() << endl; // 5 // 收缩内存 vector (vec).swap(vec); cout << "capacity = " << vec.capacity() << endl; // 5 cout << "size = " << vec.size() << endl; // 5 } void test04() { vector vec; // 预留空间 // 直接把vector扩充到设定的大小,避免重新配置、移动元素、释放原空间等一系列操作 vec.reserve(1000); cout << "capacity = " << vec.capacity() << endl; // 1000 cout << "size = " << vec.size() << endl; // 0 // 统计开辟的次数 int num = 0; int* p = nullptr; for (int i = 0; i < 1000; i++) { vec.push_back(i); if (p != &vec[0]) { p = &vec[0]; num++; } } // 未预留空间,num = 18;预留空间,num = 1 cout << "num = " << num << endl; } int main() { test01(); test02(); test03(); test04(); system("pause"); return 0; }
- 对vector的任何操作一旦引起了空间的重新配置,指向原vector的所有迭代器都会失效。
- 当删除容器中一个元素后, 该迭代器所指向的元素已经被删除,造成迭代器失效。erase方法会返回下一个有效的迭代器,所以要删除某个元素时,需要使用it = vec.erase(it)。
#include#include #include using namespace std; class Test { public: // 默认构造函数 Test(const char* str = nullptr) { if (str == nullptr) { m_data = new char[1]; *m_data = ' '; } else { size_t length = strlen(str); m_data = new char[length + 1]; strcpy_s(m_data, length + 1, str); } cout << "Construct: " << m_data << endl; } // 拷贝构造函数 Test(const Test& other) { deepcopy(other); cout << "Copy Constructor: " << m_data << endl; } // 赋值运算符 Test& operator = (const Test& other) { cout << "Assignment Operator" << endl; // 检测自赋值 if (this == &other) { return *this; } free(); deepcopy(other); return *this; } // 析构函数 ~Test() { cout << "Destructor: " << m_data << endl; free(); } void deepcopy(const Test& other) { size_t length = strlen(other.m_data); // 深拷贝 m_data = new char[length + 1]; strcpy_s(m_data, length + 1, other.m_data); } void free() { delete[] m_data; } private: char* m_data; }; int main() { // Constructor -> Copy Constructor // 在外面构造好对象,再调用拷贝构造函数 { vector vStr; vStr.push_back(Test("first")); } // Constructor // 将参数传递给构造函数,在容器中直接构造元素 { vector vStr; vStr.emplace_back("second"); } system("pause"); return 0; }
参考:https://www.bilibili.com/video/BV1et411b73Z



