【C++】vector类详细总结:从入门到手撕底层实现
这篇文章带你把 vector 从“会用”到“玩透”。前半部分系统梳理 vector 的常见构造方式、迭代器用法、size 与 capacity 的区别、扩容策略、增删查改接口以及迭代器失效等高频细节,再通过异或找单数、杨辉三角等 OJ 题把这些接口串起来使用。后半部分则手把手实现一个简易版 vector,围绕三根指针展开,讲清楚 reserve/resize 的本质、memcpy 深浅拷贝坑点,以
vector 几乎是 C++ 选手接触最早、出场率最高的容器,但很多人只会当“能自动扩容的数组”用。想写题稳、面试不虚、手撕源码有东西可写,就必须既会用标准库里的 std::vector,又能看懂它底层那三根指针在干什么。这篇文章用一套完整示例和手撕代码,把 vector 从上到下拆给你看,让它真正变成你的基础武器。
目录
1. vector的介绍及使用
1.1 vector是什么
简单描述:
vector就是“会自动扩容的顺序表”,底层是一块连续的动态数组。
关键特性:
-
元素在内存中连续存放,可以像普通数组一样O(1)随机访问;
-
支持尾插、尾删、任意位置插入、删除等操作;
-
内部自动帮你管理动态内存,不用自己
new[]/delete[]。
学习STL可以想成三个阶段:
-
能用:知道有哪些接口,能查文档、能写代码;
-
明理:大致理解每个接口做了什么、复杂度如何、可能有哪些坑;
-
能扩展:能自己模拟实现一个差不多的容器,或者读得懂源码。
1.2 vector的使用
学vector一定要学会查文档:构造函数有哪些、迭代器有哪些、容量相关有哪些、增删查改有哪些。这里把最常用的挑出来,按“构造→迭代器→容量→增删查改→迭代器失效→OJ实践”的顺序来。
1.2.1 vector的定义与构造
常见构造形式可以对应到下面这个表:
| 构造形式 | 说明 |
|---|---|
vector()(重点) |
无参构造,生成空vector |
vector(size_type n,const value_type& val=value_type()) |
构造并初始化n个值为val的元素 |
vector(const vector& x)(重点) |
拷贝构造 |
vector(InputIterator first,InputIterator last) |
区间构造,用[first,last)初始化 |
代码示例:
#include<iostream>
#include<vector>
using namespace std;
void TestVectorConstruct()
{
vector<int> v1; //空vector
vector<int> v2(5); //5个int,默认值0
vector<int> v3(5, 2); //5个int,每个都是2
int a[] = { 1,2,3,4 };
vector<int> v4(a, a + 4); //区间构造
vector<int> v5(v4); //拷贝构造
for (size_t i = 0; i < v5.size(); ++i)
{
cout << v5[i] << " ";
}
cout << endl;
}
1.2.2 vector迭代器的使用
迭代器可以理解成“包装过的指针”。对vector来说,迭代器本质就是T*,所以行为基本就是指针行为。
常见接口:
| 接口 | 说明 |
|---|---|
begin() |
返回指向第一个元素的iterator/const_iterator |
end() |
返回指向“最后一个元素的下一个位置”的iterator/const_iterator |
rbegin() |
返回指向最后一个元素的reverse_iterator |
rend() |
返回指向“第一个元素前一个位置”的reverse_iterator |


示例:
#include<iostream>
#include<vector>
using namespace std;
void TestVectorIterator()
{
vector<int> v{ 1,2,3,4,5 };
//正向迭代器
for (auto it = v.begin(); it != v.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
//反向迭代器
for (auto rit = v.rbegin(); rit != v.rend(); ++rit)
{
cout << *rit << " ";
}
cout << endl;
//范围for(底层也是begin+end)
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
}
1.2.3 vector的容量与空间增长
关键知识点:size 和 capacity。
-
size():当前“有效元素”的个数; -
capacity():当前底层数组能容纳的最大元素个数。
常用容量相关接口:
| 容量空间 | 接口说明 |
|---|---|
size() |
当前元素个数 |
capacity() |
当前容量 |
empty() |
是否为空 |
resize()(重点) |
改size,必要时扩容并初始化新元素 |
reserve()(重点) |
改capacity,不改size |
重点区别:
-
resize(n)会把size改成n,如果变大了,新位置要么填默认值,要么填你传进来的值; -
reserve(n)只保证capacity至少为n,不改变size,等于提前打地基。
扩容策略对比
代码示例:
void TestVectorExpand()
{
size_t sz;
vector<int> v;
sz = v.capacity();
cout << "making v grow:" << '\n';
for (int i = 0; i < 100; ++i)
{
v.push_back(i);
if (sz != v.capacity())
{
sz = v.capacity();
cout << "capacity changed:" << sz << '\n';
}
}
}
在不同编译器下运行,会发现:
-
VS下capacity大致按1.5倍扩;
-
g++下capacity大致按2倍扩。
想要减少扩容带来的拷贝开销,可以搭配reserve使用:
//提前reserve,避免频繁扩容
void TestVectorExpandOP()
{
vector<int> v;
size_t sz = v.capacity();
v.reserve(100); //提前把容量拉满
cout<<"making v grow:"<<'\n';
for(int i = 0; i < 100; ++i)
{
v.push_back(i);
if(sz != v.capacity())
{
sz = v.capacity();
cout<<"capacity changed:"<<sz<<'\n';
}
}
}
1.2.4 vector的增删查改
这里把最常用的接口整理成表:
| 接口名 | 说明 |
|---|---|
push_back(重点) |
尾插一个元素 |
pop_back(重点) |
尾删一个元素 |
insert |
在迭代器position前插入元素 |
erase |
删除position位置元素 |
swap |
交换两个vector的内部空间 |
operator[](重点) |
像数组一样通过下标访问 |
find |
在线性区间中查找元素(算法库里的普通函数) |
代码示例:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void TestVectorCRUD()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.insert(v.begin(), 0); //在最前面插入0
auto pos = find(v.begin(), v.end(), 2);
if(pos != v.end())
{
v.erase(pos); //删除2
}
v.pop_back(); //删除最后一个元素
for(size_t i = 0; i < v.size(); ++i)
{
cout<<v[i]<<" ";
}
cout<<endl;
}
1.2.5 vector迭代器失效问题
迭代器底层就是指针,只要这块指针指向的空间“失效”了,迭代器就失效了。失效之后继续用它去解引用、++、--,都是未定义行为,要么崩,要么给你一些诡异的数据。
对于vector,典型会“搞坏”迭代器的操作有两类:
-
可能引起底层空间变化的操作:
-
resize -
reserve -
insert -
assign -
push_back
-
-
删除指定位置元素的
erase。
例子:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> v{ 1,2,3,4,5,6 };
auto it = v.begin();
//将有效元素个数增加到100,多出的用8填充,过程中会扩容
//v.resize(100, 8);
//reserve只改变容量,操作期间也可能导致底层空间改变
//v.reserve(100);
//在前面插入元素,也可能导致扩容
//v.insert(v.begin(), 0);
//尾插也有可能触发扩容
//v.push_back(8);
/*
上面这些操作只要触发了扩容,底层旧空间就会被释放。
但it还指向旧空间,后面while里继续用it遍历,相当于在操作一块已经被free掉的内存,
结果要么崩溃,要么打印出完全莫名其妙的数据。
*/
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
return 0;
}
正确用法:只要做了可能改变空间的操作,如果还想使用迭代器,先给它重新赋值:
it = v.begin();
erase例子:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
int a[] = { 1,2,3,4 };
vector<int> v(a, a + sizeof(a) / sizeof(int));
auto pos = find(v.begin(), v.end(), 3);
v.erase(pos); //删除3
cout << *pos << endl; //行为未定义
return 0;
}
逻辑上看,erase只是在原地搬移后面的元素,没有扩容,也没换空间,似乎pos还能继续用。
但标准规定:被删除位置的迭代器就是失效的,不要再用。
最容易错误的地方,是“边遍历边删除”:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> v{ 1,2,3,4 };
auto it = v.begin();
while (it != v.end())
{
if (*it % 2 == 0)
v.erase(it);
++it;
}
return 0;
}
这段代码想删掉所有偶数,结局是要么跳着删,要么崩掉。
正确写法是:用erase的返回值接住新的位置:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> v{ 1,2,3,4 };
auto it = v.begin();
while (it != v.end())
{
if (*it % 2 == 0)
{
//继续从删除位置的“下一个”元素开始
it = v.erase(it);
}
else
{
++it;
}
}
for (auto e : v)
cout << e << " ";
cout << endl;
return 0;
}
再看一下Linux下g++的:
//扩容后继续用旧迭代器
int main()
{
vector<int> v{ 1,2,3,4,5 };
for (size_t i = 0; i < v.size(); ++i)
cout << v[i] << " ";
cout << endl;
auto it = v.begin();
cout << "扩容之前,vector的容量为:" << v.capacity() << endl;
//通过reserve强制扩容
v.reserve(100);
cout << "扩容之后,vector的容量为:" << v.capacity() << endl;
//此时it一定失效了,但在g++下不一定当场崩溃,而是打印各种诡异数据
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
return 0;
}
在g++下输出:
1 2 3 4 5
扩容之前,vector的容量为:5
扩容之后,vector的容量为:100
0 2 3 4 5 409 1 2 3 4 5
程序没崩,但结果显然不对。
同样的问题出现在erase上:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
vector<int> v{ 1,2,3,4,5 };
auto it = find(v.begin(), v.end(), 3);
v.erase(it); //删除中间的3
cout << *it << endl; //g++下会输出4
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
return 0;
}
这段在g++下看起来没问题,但标准意义上这就是在用失效迭代器,只能说运气好没崩。
结论:
只要涉及可能改变
vector结构的操作(扩容、插入、删除等),用之前先判断迭代器是不是需要重置;erase要用返回值接收新位置。
string同理,在插入、扩容、erase之后,迭代器照样会失效:
#include<iostream>
#include<string>
using namespace std;
void TestStringIterator()
{
string s("hello");
auto it = s.begin();
//resize会触发扩容,旧迭代器it直接失效
//s.resize(20,'!');
while (it != s.end())
{
cout << *it;
++it;
}
cout << endl;
it = s.begin();
while (it != s.end())
{
cout << *it;
++it;
}
cout << endl;
}
1.2.6 vector在OJ中的使用
题一:只出现一次的数字 I
题目大意:一个整数数组中,除了一个数字只出现一次外,其余每个数字都出现两次,找出这个只出现一次的数字。
套路:异或。
class Solution {
public:
int singleNumber(vector<int>& nums) {
int value = 0;
for (auto e : nums)
{
value ^= e;
}
return value;
}
};
题二:杨辉三角
题目大意:给定一个行数
numRows,生成杨辉三角的前numRows行。
核心思想:
-
每行头尾都是1;
-
中间的第
j个数是上一行j和j-1之和。
//核心思想:每一行先resize到合适长度,头尾设为1,中间用上一行相邻两数之和
class Solution {
public:
vector<vector<int>> generate(int numRows) {
vector<vector<int>> vv(numRows);
for (int i = 0; i < numRows; ++i)
{
vv[i].resize(i + 1, 1);
}
for (int i = 2; i < numRows; ++i)
{
for (int j = 1; j < i; ++j)
{
vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];
}
}
return vv;
}
};
通过这些练习可以发现:
-
vector最常用的就是“构造+遍历+插入/删除”; -
遍历时多数情况下大家更喜欢用
operator[]或范围for; -
删除时要特别注意迭代器失效问题。
后面可以继续用vector完成这些题作为练习:
-
删除排序数组中的重复项
-
只出现一次的数II
-
只出现一次的数III
-
数组中出现次数超过一半的数字
-
电话号码字母组合
2. vector深度剖析及模拟实现
2.1 std::vector的核心框架
可以把vector的内部想象成管理三根指针的类:
-
_start:指向首元素; -
_finish:指向“最后一个元素的下一个位置”; -
_end_of_storage:指向“整块空间的尾后位置”。


结构:
namespace my
{
template<class T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
vector()
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{}
size_t size() const
{
return _finish - _start;
}
size_t capacity() const
{
return _end_of_storage - _start;
}
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator begin() const
{
return _start;
}
const_iterator end() const
{
return _finish;
}
T& operator[](size_t i)
{
return _start[i];
}
const T& operator[](size_t i) const
{
return _start[i];
}
//push_back/resize/reserve/insert/erase等操作
//本质都是在这三根指针基础上移动和重分配
private:
iterator _start;
iterator _finish;
iterator _end_of_storage;
};
}
执行:
my::vector<int> v(2,9);
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
比如:
-
一开始
size=2,capacity=2,里面两个9; -
最多只多塞一个1时会扩容,重新new一块更大的空间;
-
把老数据搬过去,更新
_start/_finish/_end_of_storage,旧空间释放; -
之后继续push_back,直到再次触发扩容。
2.2 使用memcpy拷贝问题
现在假设你在自己的bit::vector里实现reserve时图省事,直接用了memcpy:
int main()
{
my::vector<my::string> v;
v.push_back("1111");
v.push_back("2222");
v.push_back("3333");
return 0;
}
这里的my::string可以理解成类似在string那一篇博客中模拟实现的自定义String类:内部有char* _str,构造时new[]一块空间,析构时delete[]。
关于memcpy:
-
它做的是内存的二进制拷贝,哪怕是结构体/对象,也只是把字节照抄一份;
-
拷贝“纯值类型”时(比如
int/double)没问题,拷贝“带资源”的类型(比如内部有指针、句柄)时,就是浅拷贝。
过程:
-
插入
"1111"后,v[0]里的_str指向一块堆上的"1111"; -
插入
"2222"时触发扩容,reserve里:-
new出一块更大的raw内存;
-
用
memcpy把老数组里的三个bite::string对象“按字节复制”到新数组; -
释放老数组整块内存;
-
-
结果:
-
新数组里的三个my::string对象,它们的
_str指针仍然指向老数组里那块已经被释放的"1111"/"2222"/"3333"空间; -
老数组这一块空间已经被
delete[]掉了; -
稍后新数组里的my::string析构时,又会再
delete[] _str一次,出现二次析构。
-




1)插入"1111"后,v[0]的_str指向0x0012ffa0
2)插入"2222"扩容,新空间里有两个空string,对它们memcpy拷贝后,_str都指向旧地址0x0012ffa0
3)释放旧空间后,这些指针全都变成野指针,后面二次析构就会崩。
结论:
只要对象里“涉及资源管理”,就千万不能用
memcpy做对象之间的拷贝。memcpy只是浅拷贝,很容易导致内存泄漏、重复释放甚至程序直接崩溃。
正确思路是:
-
对于有资源管理的对象,要逐个调用拷贝构造函数:
void reserve(const size_t n)
{
if (n > capacity())
{
size_t old_size = size();
T* tmp = new T[n];
// 若是需要深拷贝类型(自定义类型)如vector<string>/vector<vector<int>>,memcpy就会失败
// memcpy只把_start内存的字节拷贝到tmp,不会调用拷贝构造
// 新旧两个对象的指针会指向同一块堆内存,析构时二次释放 就报错
//memcpy(tmp, _start, sizeof(T) * old_size);
for (size_t i = 0; i < old_size; ++i)
{
tmp[i] = _start[i];
}
delete[] _start;
_start = tmp;
_finish = tmp + old_size;
_end_of_storage = tmp + n;
}
}
2.3 动态二维数组理解
用vector构建“动态二维数组”,以杨辉三角为例。
//以杨辉三角的前n行为例:假设n为5
void test2vector(size_t n)
{
//使用vector定义二维数组vv,vv中的每个元素都是vector<int>
my::vector<my::vector<int>> vv(n);
//将二维数组每一行中的vector<int>中的元素全部设置为1
for (size_t i = 0; i < n; ++i)
vv[i].resize(i + 1, 1);
//给杨辉三角第一列和对角线之外的元素赋值
for (int i = 2; i < (int)n; ++i)
{
for (int j = 1; j < i; ++j)
{
vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];
}
}
}
如果n = 5,vv的结构可以想象成:
-
vv本身是一个my::vector<my::vector<int>>,内部有5个元素; -
每个
vv[i]都是一个my::vector<int>对象,初始时里面还没有任何元素; -
调用
resize之后,每行的_start/_finish/_end_of_storage都指向自己那一行的数据。

左边是vv本体,右边是vv[0]~vv[4],每个都是一个vector对象
填充完后每一行分别是:
vv[0]:1
vv[1]:1 1
vv[2]:1 2 1
vv[3]:1 3 3 1
vv[4]:1 4 6 4 1
使用标准库std::vector<std::vector<int>>去做动态二维数组,实际底层布局和上面这张图是一致的:
-
外层vector是一维数组,存的是每一行的vector对象;
-
每一行又是一个独立的动态数组,长度可以不一样,非常适合存放像杨辉三角这种每行长度不同的结构。
这种嵌套写法,既保留了a[i][j]这种二维访问方式,又能享受自动扩容带来的内存安全。
3.手撕vector完整代码
vector.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<algorithm>
#include<vector>
#include<assert.h>
using namespace std;
namespace my {
template<class T>
class vector {
public:
//迭代器
typedef T* iterator;
typedef const T* const_iterator;
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator begin() const
{
return _start;
}
const_iterator end() const
{
return _finish;
}
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
while (first != last)
{
push_back(*first);
++first;
}
}
vector(size_t n, const T& val = T())
{
reserve(n);
for (int i = 0; i < n; ++i)
push_back(val);
}
//在vector<int> v(10,1) 的形式中,不这样写参数将被识别成两个迭代器,执行InputIterator类构造
vector(int n, const T& val = T())
{
reserve(n);
for (int i = 0; i < n; ++i)
push_back(val);
}
// 默认构造 不写默认构造,因为类中有拷贝构造,
// 编译器认为也有构造函数,将不会默认生成默认构造,会报错
/*vector()
{}*/
//C++11 强制生成默认构造
vector() = default;
//拷贝构造
vector(const vector<T>& v)
{
reserve(v.size());
for (auto& e : v)
{
push_back(e);
}
}
//析构函数
~vector()
{
delete[] _start;
_start = _finish = _end_of_storage = nullptr;
}
void clear()
{
_finish = _start;
}
//传统写法
//vector<int> operator=(const vector<T>& v)
//{
// if (this != &v)
// {
// clear();
// reserve(v.size());
// for (auto& e : v)
// {
// push_back(e);
// }
// }
// return *this;
//}
//现代写法
void swap(vector<T> v)
{
std::swap(_start, v._star);
std::swap(_finish, v._finish);
std::swap(_end_of_storage, v._end_of_storage);
}
vector<int> operator=(vector<T> v)
{
swap(v);
return *this;
}
size_t size() const
{
return _finish - _start;
}
size_t capacity() const
{
return _end_of_storage - _start;
}
bool empty()
{
return _start == _finish;
}
void reserve(const size_t n)
{
if (n > capacity())
{
size_t old_size = size();
T* tmp = new T[n];
// 若是需要深拷贝类型(自定义类型)如vector<string>/vector<vector<int>>,memcpy就会失败
// memcpy只把_start内存的字节拷贝到tmp,不会调用拷贝构造
// 新旧两个对象的指针会指向同一块堆内存,析构时二次释放 就报错
//memcpy(tmp, _start, sizeof(T) * old_size);
for (size_t i = 0; i < old_size; ++i)
{
tmp[i] = _start[i];
}
delete[] _start;
_start = tmp;
_finish = tmp + old_size;
_end_of_storage = tmp + n;
}
}
void resize(const size_t n, const T& val = T())
{
if (_finish > _start + n)
_finish = _start + n;
else
{
reserve(n);
while (_finish < _start + n)
{
*_finish = val;
++_finish;
}
}
}
void push_back(const T& x)
{
if (_finish == _end_of_storage)
reserve(capacity() == 0 ? 4 : capacity() * 2);
*_finish = x;
++_finish;
}
T& operator[](size_t n)
{
assert(n < size());
return _start[n];
}
const T& operator[](size_t n) const
{
assert(n < size());
return _start[n];
}
void pop_back()
{
assert(!empty());
--_finish;
}
iterator insert(iterator pos, const T& x)
{
if (_finish == _end_of_storage)
{
size_t len = pos - _start;
reserve(capacity() == 0 ? 4 : 2 * capacity());
pos = _start + len;
}
iterator end = _finish;
while (end > pos)
{
*end = *(end - 1);
--end;
}
*pos = x;
++_finish;
return pos;
}
iterator erase(iterator pos)
{
assert(pos >= _start && pos < _finish);
iterator it = pos + 1;
while (it != end())
{
*(it - 1) = *it;
++it;
}
--_finish;
return pos;
}
private:
iterator _start = nullptr;
iterator _finish = nullptr;
iterator _end_of_storage = nullptr;
};
template<class T>
void print_vector(const vector<T>& v)
{
//规定:没有实例化的类模板中取东西,编译器不能判断const_iterator
//是类型还是静态成员变量
//typename vector<T>::const_iterator it = v.begin();
auto it = v.begin();
while (it != v.end())
{
cout << *it << " ";
it++;
}
cout << endl;
//for (auto& x : v)
// cout << x << " ";
//cout << endl;
}
//通用模版
template<class Container>
void print_container(const Container& v)
{
auto it = v.begin();
while (it != v.end())
{
cout << *it << " ";
it++;
}
cout << endl;
//for (auto& x : v)
// cout << x << " ";
//cout << endl;
}
void test01()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(4);
v.push_back(5);
//for (int i = 0; i < v.size(); ++i)
// cout << v[i] << " ";
//cout << endl;
print_vector(v);
v.insert(v.begin() + 3, 99);
print_vector(v);
int x; cin >> x;
//typename vector<int>::iterator p = find(v.begin(), v.end(), x);
auto p = find(v.begin(), v.end(), x);
if (p != v.end())
{
//insert以后p就失效,不要直接访问,要访问就需要更新这个失效的迭代器的值
/*v.insert(p, 40);
(*p) *= 10;*/
p = v.insert(p, 40);
*(p + 1) *= 10;
}
}
void test02()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
//v.push_back(4);
//2v.push_back(5);
print_vector(v);
//typename vector<int>::iterator it = v.begin();
auto it = v.begin();
while (it != v.end())
{
if (*it % 2 == 0)
//v.erase(it);
it = v.erase(it);
else
++it;
}
print_vector(v);
}
void test03()
{
vector<int> v;
v.resize(5, 1);
print_vector(v);
}
void test04()
{
vector<string> v1(10, "1111111111");
print_container(v1);
vector<int> v2(10);
print_container(v2);
//需要参数更匹配的拷贝构造,如第一个参数为int n
vector<int> v3(10, 1);
print_container(v3);
}
void test05()
{
vector<string> v;
v.push_back("1111111111111");
v.push_back("1111111111111");
v.push_back("1111111111111");
v.push_back("1111111111111");
print_container(v); //没扩容
v.push_back("1111111111111");
print_container(v); //扩容,检查扩容不能使用memcpy
}
}
test.cpp:
#include"vector.h"
int main()
{
//my::test01();
//my::test02();
//my::test03();
//my::test04();
my::test05();
return 0;
}
完
更多推荐

所有评论(0)