std::vector 是 C++ 标准库提供的“用户定义类型”。它用作动态保存其数据的容器。这就是它可以与push_back() 一起成长的原因。
让我们检查一个非常简化的 std::vector 版本:
从此类实例化的对象将仅包含整数作为数据,并且必须在创建时指定大小
class VectorOfInts {
private:
int* data; // pointer to where all of the data is stored on heap
int sz;
public:
VectorOfInts(int size) :data{new int[size]}, sz{size}
{
for (int i=0; i<sz; ++i) data[i]=0; //initialize all ints to 0
}
˜VectorOfInts() { delete[] data; } //when the VectorOfInts is destroyed,
//we have to remember to release all of our data.
int getSize() const
{
return sz;
}
void setValue(int index, const int& value)
{
if(index>=sz || index<0)
{
std::cout<<"invalid index\n";
return;
}
//since value is type int which is an integral type, it is copied
//if we had a vector of struct or class instead,
//copy constructor (or suitable move constructor if defined)
//would have been called.
//this is the most crucial part to understand about this code.
data[index] = value;
}
};
如您所见,数据由免费存储中的VectorOfInts 在内部动态管理。事实上,无论您通过构造函数创建多大的容器,类对象本身的大小都是相同的。这是因为您的VectorOfInts 本身只有一个指针和一个int。
每次设置值时,都必须将参数复制到由VectorOfInts 分配的动态内存中。对于int,这没什么大不了的,但是如果我们有一个大对象向量(具有自己的指针和对象作为字段)而不是int,建议定义一个合适的移动构造函数或考虑保留一个指针向量而不是实际对象。
这是std::vector 工作原理的精髓。有一些不同之处,包括以下内容:
1- std::vector 可以随大小而增长和缩小:std::vector 将跟踪“容量”,即在向量增长时分配和可用的空闲存储的总大小,以及“大小”是向量所包含的实际元素数。如果大小超过容量,向量将在堆中重新分配更大的内存块,复制所有旧数据,并释放旧内存位置。
2- std::vector 允许泛型类型内容:这对实现来说不是问题,因为向量将为对象类型的大小 * 元素的数量分配内存。这保证有效,因为每个向量在其生命周期内只包含特定类型的对象。
我现在将提供几个示例来说明处理std::vector 时内存的确切位置:
#include <iostream>
#include <vector>
void helper()
{
std::vector<int> A; //vector created on the stack
int a=5;
int b=6;
A.push_back(a); //a is copied to another place in memory allocated by A
A.push_back(b); //same thing with b, they are both copied;
std::vector<int>* B = new std::vector<int>(); //B is a pointer only
//B occupies as much space as any pointer on your machine, but what it points to
//is a dynamically allocated block of memory that holds a vector
B->push_back(a); //a is copied to free store
B->push_back(b); //same thing with b;
free(B); //this is extremely important,
//since B is allocated on the heap, it must be freed
//or else we will have a memory leak.
//the destructor for std::vector is smart
//it will in turn free its own dynamically allocated memory upon destruction.
} //when this function returns, a, b and A are all destroyed
// because they fall off the stack
//A's destructor is called implicitly and the block of memory
// that is allocated by A is free's by its destructor
在我们的主要功能中:
int main() {
helper();
std::vector<int> A; //created on the stack;
A.push_back(1); //the value 1 is copied to dynamic memory by A
A.push_back(2);
A.push_back(3);
std::vector<int> B; //created on the stack;
B.push_back(4); //the value 4 is copied to dynamic memory by B
B.push_back(5);
B.push_back(6);
std::vector<std::vector<int>> C; //also created on the stack
C.push_back(A); //the content of A (including its internal pointers)
//is copied to an area of heap allocated by C
C.push_back(B); //same for B, notice that A and B are copied
return 0;
} //destructor for A, B and C are called.