C++ - vector 的使用

C++——vector vector是表示可变大小数组的序列容器。就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是。 阅读详情

目录

前言

一、认识vector

二、vector 的接口函数

1、成员函数

1.1 构造

1.2 赋值运算符重载

2、迭代器

3、容量

4、扩容机制

5、修改

6、元素访问

6.1 operator[]

6.2 at

6.3 front

6.4 back

7、非成员函数

三、vector 与 string 的区别

四、注意事项

1、隐式类型转换

2、范围for 

3、迭代器

eg.find

eg.reverse

eg.sort

总结


前言

路漫漫其修远兮,吾将上下而求索;


一、认识vector

vector ,中文含义:矢量,本质上就是顺序表;

vector 是一个可以改变大小的数组实现的顺序结构;

二、vector 的接口函数

1、成员函数

1.1 构造

Q: 已经再调用vector 的时候传了空间配置器的模板参数,为什么在调用vector 构造函数的时候还要传?

  • 因为在一般情况下我们无需传空间配置器,但是有可能让你自己显式传;显式传如果该空间配置器带参数的话,其外面就只有模板类型Alloc ,而用Alloc 只能调用默认构造(因为不知道传什么参数);故而此处这么写:的意义在于:一般情况下,我们不用自己创建空间配置器,使用其默认的就够用了;但是不排除在有些情况下,你需要自己实现一个空间配置器,那么此时就可以以传参的形式传进去使用该空间配置器;

另外在C++11 中还给了其他的初始化方式,例如:使用初始化列表进行初始化:

使用如下:

用花括号的形式将要初始化的值传给 iniltializer_list ,而inilitializer_list 会依次取到花括号中的值然后依次 push_back 到v 中;

1.2 赋值运算符重载

因为vector 底层涉及资源,所以 operator= 肯定也是深拷贝实现的;

2、迭代器

跟string 中迭代器的涉及一摸一样,此处就不做过多赘述;

3、容量

在vector 之中多了一个:resize;resize ,就是对 size 进行改变;

如果resize 中所传参数 n 比当前的size大,它会进行插入(插入 '\0');如果比当前的size 小,它会删除;

而reserve ,就是手动扩容;如果reserve 中所传参数 n ,小于当前容量,一般是不会缩容,但是也不排除会缩容的可能性(因为在不同平台之下其具体实现不同);reserve 主要是对 capacity 进行改变;

4、扩容机制

VS下的 vector 的扩容机制是怎样的?

  • vs 中vector 的扩容机制与 string 中的扩容机制是一样的,基本上也是按照1.5 倍进行扩容;
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';
		}
	}
}

在Linux 中,测试:

在Linux 中走的就是2倍扩容;

5、修改

与string 不同的是,在vector 中并没有重载 operator+= ;因为对于string 而言,string 可以尾插(拼接)一个字符、一个字符串;而对于整型来说,没有串的概念,即只有一个一个的数据而没有多个数据冗在一起的概念;对于vector , 想要实现string 中 operator+= 的功能,有 push_back 就够了;

测试使用一下尾插、尾删:

void test2()
{
	vector<int> v1;

	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);

	for (int i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << " ";
	}
	cout << endl;

	v1.pop_back();
	v1.pop_back();

	for (int i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << " ";
	}
	cout << endl;

}

并且在vector 中并没有实现头插、头删;一部分原因是因为头插、尾删需要挪动数据,效率非常低,并且可以使用 insert 或者erase 间接实现头插、头删,故而vector 中就没有提供push_front 和 pop_front;

vector 的erase 和 insert 均是支持迭代器的;

测试使用一下:

void test3()
{
	vector<int> v1 = { 10,20,30,40,50 };
	v1.insert(v1.begin(), 1);
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	v1.erase(v1.begin() + 2);
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
}

经过上述代码我们可以发现,我们可以在迭代器的基础上进行加、减,间接地实现除了类似于下标访问地方式,所以erase 和 insert 全部用迭代器实现就可以解决问题,也就没有支持下标版本的插入、删除;

6、元素访问

6.1 operator[]

6.2 at

返回向量中位置为n的元素的引用。

6.3 front

返回vector 中的第一个元素的引用。

6.4 back

返回vector 中最后一个元素的引用。

7、非成员函数

和string 不同的是,vector 的非成员函数中并没有支持 流插入和流提取的重载;因为string 是“串”,“串”可以输入一个输出一个,而vector 想要输出应该借助迭代器或者范围 for ,需要使用者自己控制;

三、vector 与 string 的区别

需要注意的是,不能使用vector<char> 去代替 string! 本质上就是字符数组与字符串的区别;

	vector<char> v = { 'a' , 'b','c' };
	string s("abc");

虽然看起来,vector<char> 和 string 均是一个“数组”,均存放了三个字符;但是 s 的底层之中还隐藏着一个 '\0', 正因其最后有 '\0' 才可以兼容C语言;而vector<char> 中没有隐藏的 '\0’,于是就不兼容C语言;并且在string 中有许多接口函数是vector 没有的(eg. vector 之中没有实现 find ,只能使用算法库中的find );vector<char> 与 string 在功能上存在本质的区别;

四、注意事项

1、隐式类型转换

vector 之中可以存int 、char等内置类型,当然也可以存 string, 是不是vector 中还可以存 vector<int> ? 是的!

	vector<int> v1;
	vector<string> v2;
	vector<vector<int>> v3;

单参数的构造函数支持隐式类型转换,也就意味着 string 支持转换,为什么要支持这种很怪的内置类型到自定义类型的转换呢?

  • eg. vector<string> v2;
  • 若想要向 v2 中push_back , 按照常规思路,就需要先创建 string 对象(有名对象或者匿名对象),然后再插入;但是实际上这样做是有一点麻烦的,直接在push_back 中放所要插入的数据(单参数的构造函数支持隐式类型转换),操作起来是会更方便的;
     
void test4()
{
	vector<int> v1;
	vector<string> v2;
	vector<vector<int>> v3;

	//有名对象
	string name1 = "张三";
	v2.push_back(name1);
	//匿名对象
	v2.push_back(string("李四"));
	//隐式类型转换
	v2.push_back("王五");
}

更加细节的是, push_back 的形参类型为 const T& , 也就是说用引用来接收参数,无论实参是内置类型数据还是自定义类型数据,均不会在传参的过程中产生巨大的消耗,提高了效率;而加上 const ,是为了支持匿名对象、临时对象传参(权限不能放大,但是权限可以平移、缩小);

实际上push_back 中形参引用的是 "王五"所创建的临时对象;

与之前所学的类型转换很像:

	int i = 0;
	const double& d = i;
  • 变量 d 不可以直接引用 i ,因为此处的 i 并不只直接赋值给 d ; d 实际上引用的是  i 产生的临时对象,而临时对象具有常性,所以要给 d 加上 const 进行修饰(引用的时候权限不可以放大);

2、范围for 

在使用范围 for 的时候需要注意传值与引用;

void test4()
{
	vector<int> v1;
	vector<string> v2;
	vector<vector<int>> v3;

	//有名对象
	string name1 = "张三";
	v2.push_back(name1);
	//匿名对象
	v2.push_back(string("李四"));
	//隐式类型转换
	v2.push_back("王五");

	for (auto e : v2)
	{
		cout << e << " ";
	}
	cout << endl;
}

这样写范围for 非常不好;首先v2 中存放的是string对象;而范围for 最终是会转换成迭代器让其去取 v2 中的每一个数据,而现在每个数据是string 对象,那么将每个string 对象给给(传值) e , 会进行深拷贝(自定义类型对象的深拷贝的代价很大);所以写范围for 的时候建议用上引用,如果不改变该数据可以考虑再加一个const 修饰;

	for (const auto&e : v2)
	{
		cout << e << " ";
	}
	cout << endl;

结合编码的知识我们可以思考汉字是如何存储起来的;在实际的内存当中并非存储的是汉字本身,而是先去对应的编码表中查询“张” “三”等汉字在编码表中所对应的字符(一般常见的汉字是由两个字符构成),而当我们将汉字取出准备打印的时候,又会去调查对应的编码表显示成对应的汉字;

3、迭代器

STL的六大组件中比较重要的两个:容器和算法,而容器和算法又是通过迭代器进行访问的;

迭代器本质上就是封装的体现;(封装是面向对象的三大特性)

Q:迭代器为什么需要封装?

  • 首先,容器有很多种,eg.vector、list、set(树)……如果没有迭代器,先要了解清楚容器结构才可以去遍历,即需要暴露底层的结构;而暴露一个容器的底层结构就意味着需要知道这个容器的底层命名,并且在不同的平台之下其命名需要统一;这样处理,不仅加大了程序员们的工作量,而且使用者也会感到非常麻烦(需要对应不同的容器使用不同的遍历方式);

但倘若有迭代器就不一样了;迭代器封装的实现,屏蔽了容器底层实现的细节,提供了统一的访问方式;我们无需去管这个容器、算法等其底层的具体是如何实现的,并且迭代器的使用方式均是完全类似的;而对于算法(eg.查找函数,若没有迭代器,就需要针对不同的容器写对应的查找函数),而有了迭代器之后就可以提供统一的算法,算法的本质是一个模板,针对迭代器设计的模板;

eg.find

之所以vector 、list等容器之中并未提供find ,是因为算法库中有一个函数模板 find,是针对所有容器设计的;

Q:但是不同的容器结构不同;eg. 顺序表是一个数组的结构,链表是一个链式结点的结构、set 是一个二叉树树型的结构……那么 find 是如何针对每一种不同的结构实现的?

  • find 基于模板的迭代器来实现的;也就意味着,使用 find 的时候并不会关心你是哪一个容器;

Q:想要查找该容器中的数据又该如何查找呢?

  • 提供一段迭代器区间(该区间是左闭右开的), 以及所要查找的值 val;

需要注意的是,所有迭代器其访问的区间一定都是左闭右开的!!

所有迭代器封装屏蔽了容器底层的实现细节,提供了统一的访问方式:首先可以让我们访问并修改容器;其次也可以让算法作用到容器上去;

再看看算法库中的其他算法:

eg.reverse

Q: 为什么要比较  first != --last?

  • 此处还存在奇数和偶数的问题;只要两指针从两边向中间走就需要考虑数据奇偶数的问题;

 

Q: 能否将 ((first != last) && (first != -- last)) 的判断改为 first < last?

不能,因为所有迭代器都支持 == 以及 != 的比较,但是有的却不支持 < 、> 等的比较;因为数据的结构有可能是数组也有可能是链表……像vector 这种底层是连续的空间所以支持迭代器比较大小,但是如果底层空间不连续则就不支持;

eg.sort

sort , 底层是快排,严格来说是自省排序;

注:自省排序是快排与堆排的结合;因为快排可能在极端情况下效率低下;在 sgi 版本的算法库中的sort 使用的就是自省排序;

倘若想利用sort 排降序,此时就会涉及到“仿函数”的概念,sort 默认排升序,实质其第三个参数默认传 less<T>() ;在库之中定义了有两个类模板: greater<T>() 、less<T>() ;

此处我们大致了解一下即可;

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

void test1()
{
	vector<int> v1 = { 10,6,8,32,3,1,90,11 };
	sort(v1.begin(), v1.end());//默认排升序
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	greater<int> gt;
	sort(v1.begin(), v1.end(), gt);//传排降序的仿函数,传有名对象
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

    sort(v1.begin(), v1.end(), less<int>());//排升序,传匿名对象
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

}
int main()
{
	test1();
	return 0;
}

还需要注意的是。list 不支持使用算法库中的sort 进行排序,这是源于list 中迭代器种类;从迭代器功能角度分为:单向迭代器(只支持 ++ ,eg.单链表)、双向迭代器(支持 ++、--) 、随机迭代器(支持 ++、--、+、-);将算法库中的sort转到定义 :

而显然,对于list 来说,结点的地址之间没有任何关系,所以对于list 来说,迭代器相减是没有任何意义的;而算法库中sort 的实现用到了迭代器相减,故而list 不能使用算法库中的sort 来进行排序;


总结

1、vector ,中文含义:矢量,本质上就是顺序表, 是一个可以改变大小的数组实现的顺序结构;

2、与string 相比,vector不支持find等string特有功能

3、所以写范围for 的时候建议用上引用,如果不改变该数据可以考虑再加一个const 修饰;

4、sort 默认排升序,实质其第三个参数默认传 less<T>() ;在库之中定义了有两个类模板: greater<T>() 、less<T>() ;

Vector(向量容器) Vector是一个线性顺序结构。相当于数组,但其大小可以不预先指定,并且自动扩展。它可以像数组一样被操作,由于它的特性我们完全可以将vector 看作动态数组。 一、在创建一个vector 后,它会自动在内存中分配一块连续的内存空间进行数据存储,初始的空间大小可以预先指定也可以由vector 默认指定,这个大小即capacity ()函数的返回值。当存储的数据超过分配的空间时vector 会重新 阅读详情

相关推荐

C++里的vector详细讲解

vector是C++ STL中非常强大且易于使用的动态数组容器。它提供了灵活的内存管理、高效的元素访问和丰富的操作函数。然而,在使用vector时,我们也应该注意其性能特点和最佳实践,以确保代码的高效运行。通过合理使用vector的成员函数和注意避免一些常见陷阱,我们可以充分利用这个容器的优势来编写高效且可靠的C++代码。

Weirdo的博客 1万+

详解c++---vector介绍

c++ vector库中函数讲解

qq_68695298的博客 1万+

【C++】动态数组vector的使用

本文介绍了C++标准库中vector容器的核心方法及其应用。主要内容包括:基础属性查询方法(size/empty/capacity)、元素访问方式(operator[]/at/front/back)、增删改操作(push_back/emplace_back/insert/erase)、内存管理(reserve/shrink_to_fit/resize)以及迭代器使用。文章提供了int类型和自定义struct的vector使用示例,展示了三种遍历方式,并演示了查找、添加和删除元素的操作。通过代码示例和运行结果

Dust的博客 907

C++关于vector的详细介绍

本文介绍了C++中vector的详细内容,其中关于vector的迭代器失效问题着重进行讲解。

写博客记录分享学习笔记 1万+

cpp中vector的使用

C++中vector的两种访问方式v[]和v.at()都能访问元素且都不能越界,但存在重要区别:v[]不进行边界检查,越界时返回错误引用可能导致程序崩溃;v.at()会进行边界检查,越界时抛出异常,可通过try-catch捕获使程序继续运行。实际使用中v[]更常见但风险较高,v.at()更安全但性能稍低。

youzjuer的博客 174

Apache-Plc4x-Modbus-Tcp学习记录(一)

Apache-Plc4x-Modbus-Tcp学习记录(一)

weixin_45325423的博客 6988

【C++游记】Vector的使用和模拟实现

构造函数声明接口说明vector()无参数构造构造并初始化n个val拷贝构造使用迭代器进行初始化构造今日C++到这里就结束啦,如果觉得文章还不错的话,可以三连支持一下。感兴趣的宝子们欢迎持续订阅小枫の主页还有更多生动有趣的文章,欢迎宝子们去点评鸭~C++的学习很陡,时而巨难时而巨简单,希望宝子们和小枫一起坚持下去​。

枫の大一分享 1839

基于Java+Maven+Testng+RestAssured+Allure+Jenkins搭建一个接口自动化框架

2、有一个提取表达式列,通过编写每个接口的JSON提取表达式,后边在解析Excel时,对接口执行后的响应数据用该表达式提取出来,保存到环境变量,如果某些接口需要前置接口的响应数据,我们就可以从环境变量中获取该数据出来,从而解决了接口关联的问题。1、在之前介绍过全局配置类Contants中添加一个控制台日志开关控制权限,如果选择为false,则控制台不输出日志,将日志输出到allure报表,选择为true,则在控制台输出日志,不输出到allure报表。

专注于技术分享的博主 1185

C++中vector使用详细说明

C++中vector使用详细说明 转自:http://blog.chinaunix.net/uid-26000296-id-3785610.html    http://www.cnblogs.com/mr-wid/archive/2013/01/22/2871105.html    https://www.cnblogs.com/aminxu/p/4686332.html 一、向量的介绍   ...

weixin_42430671的博客 2万+

uniapp运行钉钉小程序

因项目原因,公司需要在钉钉里面开发小程序。之前用uniapp开发过app,H5,小程序。还真没尝试过钉钉小程序,今天就简单的记录下uniapp运行钉钉小程序中的过程。

YL 2919

Visual Studio Git 使用指南

Visual Studio 2022深度集成了Git功能,提供了直观的图形界面管理源代码。本文详细介绍了VS中Git的使用方法:从环境准备、克隆/创建仓库开始,重点讲解了"Git更改"窗口的日常操作,包括查看修改、暂存文件、提交推送等。同时涵盖了分支管理、查看历史、解决冲突等核心功能,以及储藏、重置等高级操作。文章还提供了实用技巧,如提交规范、频繁提交等最佳实践。VS的Git集成覆盖了日常开发需求,图形界面与命令行可互补使用,适合各层次开发者高效管理代码版本。

guigenyi的专栏 1570

C++ vector的使用总结及常用vector操作

一、介绍 C++ vector类为内置数组提供了一种替代表示,与string类一样 vector 类是随标准 C++引入的标准库的一部分,使用时需包含头文件: #include <vector> 二、使用方式 C++ vector类有两种使用方式: 第一种:STL方式 vector< string > text; 1. 我们向 vector 中插入元素,而不...

学之知之的博客 7348

Innovus时钟树综合CTS实战:从原理到signoff的完整指南

时钟树综合(CTS)是数字后端实现中保障同步电路时序收敛的核心环节,其本质是在物理层面构建低偏斜、可控延迟的全局时钟分发网络。它基于静态时序分析(STA)原理,通过平衡clock skew、insertion delay、transition time与功耗面积等多维约束,对抗工艺电压温度(PVT)变异带来的时序不确定性。技术价值在于支撑GHz级高频芯片的setup/hold签核,广泛应用于CPU、GPU、AI加速器等复杂SoC的Innovus后端流程。本文聚焦CTS在Innovus工具链中的工程落地,覆盖

weixin_28523493的博客 224

c++中vector的使用优化

/ 显式默认移动构造函数{}std::cout << "Vertex被Copy了一次" << std::endl;// 预分配内存,避免扩容// 直接构造,无拷贝return 0;可以看到就没有打印"Vertex被Copy了一次"了,说明没有拷贝构造函数的调用。

Ming_811的博客 1730

SolidWorks 小车底盘 装配体

通过制作小车底盘了解solidworks装配体的部分知识

及时总结 2229

我写了一个自动识别火车车厢位置的算法【lidar点云识别】

我写了一个自动识别火车车厢位置的算法【lidar点云识别】

qq_43212290的博客 798

【C++】vector的简单使用

1.vector定义 2.vector元素的写入 3.vector元素的访问 4.vector传参

讨厌水的鱼 1万+

使用MATLAB实现PAC2002轮胎模型的TIR文件解析和模型计算详解

PAC2002轮胎模型是由荷兰TNO公司开发的一种半经验的轮胎模型,用于描述轮胎在不同工况下的力学特性。该模型基于一系列物理和经验参数,通过复杂的数学表达式来模拟轮胎的力学行为,包括纵向力、侧向力、回正力矩等。

qq_38334677的博客 2430

C++ vector的使用

STL 中的vector是 C++ 标准库中最核心的动态数组容器,用于替代原始数组,提供自动内存管理和丰富功能。核心接口速查// 构造// 空vector// 100个0// 100个5// 元素访问// 无边界检查// 带边界检查(越界抛异常)// 获取底层数组指针// 容量操作// 预分配内存(不初始化)// 改变元素数量// 释放多余内存// 增删元素// 尾部插入// 尾部删除// 指定位置插入// 删除指定位置// 工具函数// 是否为空vec.size()

jingfeng514的博客 1321

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

【C++】vector的使用

中_a的类型是vector<int>*,指向的每个元素都是vector<int>类型的。v中_a的类型是int*,指向的每个元素都是int类型的。2. 我们可以使用[]+下标的方式,访问二维vector中的每一个元素,vv.operator[](i)返回值是对象vv中的第i个元素(是vector<int>类型的)的引用,vv.operator[](i).operator[](j),访问的是对象vv[i]中的第j个元素(是int类型)的引用,也可以写成vv[i][j]。改变vector的size。

2301_80485351的博客 1200

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

C++—vector的使用

一、vector的介绍 说的简单点:  vector是可以动态增长的数组容器 二、vector的使用  2.1vector构造函数 构造函数 功能 vector() 无参构造 vector 构造并初始化n个val void test1() { vector<int> v1;//无参的构造用的最多 vector<int> v2(10,1);//用10个1来初始化 vector<int> v3(v2.begin(),v2.end());/

想要上进的coder的博客 3400

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

C++ vector使用详解

C++是一门广泛应用于计算机程序设计的编程语言,而vector则是C++中非常常用的一个容器。下面将详细介绍C++ vector的特性和使用方法。

sushhsishdgsusk的博客 9440

c++ vector使用方法收集

一、 在c++中,vector是一个十分有用的容器,下面对这个容器做一下总结。 1.基本操作 (1)头文件#include<vector>. (2)创建vector对象,vector<int> vec; (3)尾部插入数字:vec.push_back(a); (4)使用下标访问元素,cout<<vec[0]<<endl;记住下标是从0开始...

mikasoi的博客 1万+

【C++】vector的使用及模拟实现

vector是一个可变大小数组的容器,与数组一样,vector也是一块连续的空间,可以像数组一样对元素进行高效的遍历访问,但是普通数组的大小是不变的,vector可以改变自身大小。vector是采用动态分配数组来存储数据,即插入新元素时要改变存储空间大小,往往要分配一个新的数组,然后把原来数组的元素转移到新的空间里。vector的尾插尾删效率高,中间插入和删除效率较低。

2301_77459845的博客 1546

C++ 中vector的使用方法

C++ 中vector的使用方法(纯干货!)

那年聪聪 35万+

【C++】14.vector的使用

vectorvector的文档介绍vector在实际中非常的重要,在实际中我们熟悉常见的接口就可以,下面列出了哪些接口是要重点掌握的。构造函数声明接口说明vector()(重点)无参构造构造并初始化n个val(重点)拷贝构造使用迭代器进行初始化构造vector的构造代码演示。

hlyd520的博客 1452
上一篇: string的底层实现
下一篇: 动态规划 - 简单多状态 dp 问题
秦少游在淮海
博客等级 码龄3年 1071粉丝 88原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值