一、Vector
- 1. vector 源码剖析与仿写
- 2. 容器初始化
- 3. 元素访问
- 4. 迭代器
- 5. 容量
- 6. 修改器
- 7. 元素容量和元素个数
- 8. 对元素进行访问的几种方式
- 10. vector扩容函数
- 11. 原位构造函数
一、Vector 1. vector 源码剖析与仿写
vector简介:
1.vector是表示可以改变大小的数组的序列容器。
// SegList
2.vector与数组一样,元素使用连续的存储空间,就可以使用常规指针,指向其元素,使用偏移量来访问存储空间中的元素。
3.vector与数组不同的是,vector的大小可以动态变化,容器会自动扩容存储空间。
4.vector使用一个动态分配的连续存储空间来存储元素。
在插入新元素时存储空间可能需要重新分配,以便增大大小,这意味着分配一个新存储空间要将所有元素移动到其中。
就处理时间而言,这是一项相对昂贵的任务,因此,向量不会在每次向容器添加元素时重新分配。
5.vector容器可以分配一些额外的存储空间以适应可能的增长,因此容器的实际容量可能大于严格需要的存储容量(即容器的大小)。
6.vector与array相比,向量消耗更多的内存,以换取管理存储和以高效方式动态增长的能力。
7.与其他动态序列容器(deques、 list和forward_list)相比,vectors可以非常高效地访问其元素(就像数组一样),并相对高效地从其末尾添加或删除元素。
对于在结尾以外的位置插入或删除元素的 *** 作,其性能较差。
学习STL的方法,首先会使用,其次掌握原理,再次可以扩展(二次开发)。
#include
#include
using namespace std;
int main()
{
//vector初始化
vector<int> ar1;
vector<int> ar2 = { 12,23,34,45,56,67,78,89,90,100 };
vector<int> ar3(10, 23); //开辟10个空间,每个空间的元素都是23
vector<int> ar4({ 12,23,34,45,56,67,78,89,90,100 }); //把列表加入
vector<int> ar5(ar1); //用一个对象初始化另一个对象
vector<int> ar6(std::move(ar2)); //移动构造
return 0;
}
3. 元素访问
at | 访问指定的元素,同时进行越界检查 |
---|---|
operator[] | 返问指定的元素 |
front | 访问第一个元素 |
back | 访问最后一个元素 |
data | 访问指向内存中数组的第一个元素的指针 |
begin / cbegin | 返回指向起始的迭代器 |
---|---|
end / cend | 返回指向末尾的迭代器 |
rbegin / crbegin | 返回指向起始的逆向迭代器 |
rend /crend | 返回指向末尾的逆向迭代器 |
empty | 检查容器是否为空 |
---|---|
size | 返回容纳的元素数 |
max_size | 返回可容纳的最大元素数 |
reserve | 预留存储空间 |
capacity | 返回当前存储空间能够容纳的元素数 |
shrink_to_fit | 通过释放未使用的内存减少内存的使用 |
clear | 清除内容 |
---|---|
insert | 插入元素 |
emplace | 原位构造元素 |
erase | 擦除元素 |
push_back | 将元素添加到容器末尾 |
emplace_back | 在容器末尾就地构造元素 |
pop_back | 移除末元素 |
resize | 改变容器中可存储元素的个数 |
swap | 交换内容 |
size = last - first;
cap = end - first;
int main()
{
vector<Object> objvec = { Object(10),Object(20),Object(30),Object(40) };
cout << objvec.size() << endl;
cout << objvec.capacity() << endl;
for (int i = 0; i < objvec.size(); ++i)
{
cout << objvec[i].Value() << endl;//下标对元素进行访问
}
for (int i = 0; i < objvec.capacity; ++i)
{
cout << objvec.at(i).Value() << endl;//at函数对元素进行访问
}
//普通迭代器对元素进行访问
vector<Object>::iterator it = objvec.begin();
for (; it != objvec.end(); ++it)
{
cout << it->Value << " " << endl;
it->Value() += 100;
cout << " " << (*it).Value() << endl;
}
//常性迭代器对元素进行访问
for (; cit != objvec.end(); ++cit)
{
cout << cit->Value() << endl;
cout << (*cit).Value() << endl;
}
return 0;
}
10. vector扩容函数
void reserve( size_type new_cap ); (C++20前)
constexpr void reserve( size_type new_cap ); (C++20起)
增加vector的容量到大于或等于new_cap的值。
若new_cap大于当前的capacity(),则分配新存储,否则该方法不reserve()不更改vector的size。
若new_cap大于capacity(),则所有迭代器,包含尾后迭代器和所有到元素的引用都被非法化。
否则,没有迭代器或引化。
初始化
template<class T>
class SeqList
{
T* data;
int maxsize;
int cursize;
public:
SeqList(int sz = 10) :data(T new[sz]), maxsize(sz), cuisize(sz) {}
SeqList(std::initializer_list<T> init)
{
maxsize = init.size();
cursize = maxsize;
data = (T*)malloc(sizeof(T) * maxsize);
}
};
int main()
{
SeqList<int> seqlist{ 12,23,34,45,56 };//可以用此方式进行初始化
}
11. 原位构造函数
原位构造函数示例讲解(直接在定位中写)
int main()
{
vector<Object> objvec;
objvec.reserve(10);
objvec = { Object(10),Object(20) ,Object(30) ,Object(40) };
cout << objvec.size() << endl;
cout << objvec.capacity() << endl;
objvec.emplace_back(100);
}
原为构造函数重写
将构建对象的地址传递,用定位New直接
调动构造函数构建对象
class Object
{
private:
int value;
public:
Object(int x = 0)
:value(x)
{
cout << " Object " << endl;
}
Object(int x, int y)
:value(x + y)
{
cout << " Object " << endl;
}
Object(const Object& obj)
:value(obj.value)
{
cout << " Object& " << endl;
}
Object(Object&& obj)
:value(obj.value)
{
cout << " move Object&& " << endl;
}
Object& operator=(const Object& obj)
{
value = obj.value;
cout << " operator = " << endl;
return *this;
}
Object& operator=(Object&& obj)
{
value = obj.value;
cout << " move operator = " << endl;
return *this;
}
~Object()
{
cout << " ~Object " << endl;
}
int& Value()
{
return value;
}
const int& Value() const
{
return value;
}
};
template<class T,class...Arg>
void Make(T* p, Arg... arg)
{
new(p) T(arg...);// 定位new
}
int main()
{
Object* p = (Object*)malloc(sizeof(Object));
Make(p, 12);
return 0;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)