标准库类型vector的常用的定义初始化与输出方法

 

目录

 

一:vector的概念

二:vector的优点和局限性

(1)优点

(2)局限性

三:vector的定义与初始化

(1)一维向量

(2)二维向量

①vector vec[N]类型

②vector>  vec类型

四:vector中的元素的输出

五:vector常用方法


一:vector的概念

     标准库类型vector表示对象的集合,其中所有对象的类型相同。集合中的每个对象都有着一个与之对应的索引,索引用于访问对象。因为vector“容纳”着其他对象,所以它也常被称为容器 

    术语:何为对象? 根据<<C++primer>>C++11标准解释是这样的:认为对象是具有某种数据类型的内存空间,并不严格区分是类还是内置类型,也不区分是否命名或者是否只读。               

二:vector的优点和局限性

(1)优点

①动态大小:vector 具有动态分配内存的能力,可以根据需要动态增加或减少元素的数量,而不需要预先指定大小。
②随机访问:vector 支持常量时间的随机访问,这意味着可以直接通过索引访问元素,而不受向量大小的影响。
③管理方便:std::vector 提供了许多方便使用的函数,这些函数可以方便地对向量进行访问、修改、插入、删除等操作,这也是算法竞赛中常用原因。

(2)局限性

①插入和删除操作开销较大:在向量的中间插入或删除元素会导致其他元素的移动,因此时间复杂度是 O(n),其中 n 是向量的大小。如果进行插入操作时,如果当前容量不足,vector 需要重新分配内存以扩展容量,并将原有的元素拷贝到新的内存空间中。
②不适合大规模数据:由于连续存储的特性,当向量的大小变得非常大时,可能会导致内存分配失败或者频繁的内存重新分配,影响性能。
③不支持快速查找和删除操作:与哈希表或平衡二叉树相比,vector 不适合频繁的查找和删除操作,因为这些操作的时间复杂度较高。
④不适合存储大对象:由于连续存储的特性,向量存储大对象时可能会导致内存碎片化,增加内存开销。

三:vector的定义与初始化

(1)一维向量

vector<数据类型> 名字
vector<T> vec          定义一个T数据类型的空vector元素,执行默认初始化,有些类型不支持默认初始化
vector<T> vec(n,val)   定义n个T数据类型的元素,每个元素的值为val
vector<T> vec(n)       定义n个T数据类型的元素,执行默认初始化,有些类型不支持默认初始化
vector<T> vec{a,b,c...}vec中每个元素被赋予相应的初始值
vector<T> vec={a,b,c...}等价于vec{a,b,c...}
vector<T> vec2(vec1)   vec2中包含有vec1所有元素的副本,把vec1中的元素拷贝给vec2
vector<T> vec2=vec1    等价于vec2(vec1),注意vec2与vec1必须具有相同的数据类型

 

初始化时注意以下细节:

1.初始化vector对象的时候花括号,圆括号,中括号有区别:
vector<string> vec={"Welcome","to","C++"};//正确,列表初始化
vector<string> vec=("Welcome","to","C++");//错误

vector<int> vec(10);//vec有10个元素,每个值为0
vector<int> vec{10};//vec有一个元素,其值为10
vector<int> v=10;//这种初始化是错误的
vector<T>  vec[10];//这是个向量组,相等于二维动态数组,后面有讲

vector<int> v1(10,1);//v1中有10个元素,每个元素值为1
vector<int> v2{10,1};//v2中有2个元素,其值分别是10,1

2.此外对于vector<T> vec(n) 这种初始化有一些特殊限制;
其一:对于基本数据类型,可能是未定义的值(可能是0或者其他垃圾值,取决于编译器),
对于类类型,可能是默认构造函数初始化的值。
其二:有些类型不支持默认初始化,则必须提供初始元素值,
比如当T是一个不可默认构造的类型,那么这种初始化将会导致编译错误。

注意:对于使用 vector<int> vec(n) 这样初始化的向量 vec,vec 的大小已经固定为 n,并且其中的元素已经被初始化了。在这种情况下,使用 push_back() 方法来添加新的元素的时候,会在向量的末尾添加一个新的元素,这个末尾什么意思呢?以下有段代码可以演示。

#include<iostream>
#include<vector>
using namespace std;
int main()
{
	int n=5;
	vector<int> vec(n);
	vec.push_back(6);
	for (int i = 0; i <= 5; i++)  cout << vec[i];
	return 0;
}

 vector<int> vec(n);这一句会执行初始化,vec里面全是0,那么输出是什么?

000006

没错!就是000006,它会在添加6在向量末尾(伴随一个扩容操作)。

(2)二维向量

假如声明一个常量N

①vector<T> vec[N]类型

它是一个向量组,动态数组的个数确定,每个动态数组个数不确定,可自由添加或删除元素。

②vector<vector<T>>  vec类型

每个维度都可以变,动态数组个数可自由变化,每个动态数组的元素也可自由变化。

如果想要初步固定两个维度长度,可以这么初始化。

vector<vector<int>> vec(n, vector<int>(n, 0)); // 创建一个 n 个长度为 n 的二维向量,并将所有元素初始化为 0

其它维度暂时不举例了。

四:vector中的元素的输出

1.vector支持下标运算符,把vector理解为动态数组:

例如1)int类型:

vector<int> a{5,2,1};
for (int i = 0; i < 3; i++)
	cout << a[i]<<" ";

输出:

5 2 1

2)char类型:

int n;
cin >> n;
vector<char> b(n, '.');
for (int i = 0; i < n; i++)
    cin >> b[i];
for (int i = 0; i < n; i++)
	cout << b[i]<<" ";

输入:

6
A B C D E F

输出:

A B C D E F

3)string类型

vector<string> c(n);
for (int i = 0; i < n; i++)
	cin >> c[i];
for (int i = 0; i < n; i++)
	cout << c[i] <<" ";
	

输入:

3
Hello!
C++
Program.

输出:

Hello! C++ Program.

剩下的数据类型就不举例了。

2.可以使用范围for语句处理vector对象中的所有元素,访问vector对象中的元素方法和访问string对象中的字符方法差不多,也是通过元素在vector对象中的位置。vector对象(以及string对象)的下标运算符号可以用于访问已存在的元素,而不能用于添加元素。添加元素可以用vec.push_back(t)函数(向vec尾端添加一个值为t的元素)

vector<int> vec{ 1,2,3,4,5,6,7,8,9 };
for (auto& i : vec)//i是一个引用,类似于别名,但有区别!
	i *= i;//求元素值的平方
for (auto i : vec)
	cout << i << " ";

输出:

1 4 9 16 25 36 49 64 81

 3.使用迭代器。除了vector之外,标准库还定义了其他几种容器,所有标准库容器都可以使用迭代器,但是其中只有少数几种才同时支持下标运算符。

vector<char> s{ 'a','b','c','d','e' };
for (auto it = s.begin(); it != s.end(); it++)//迭代器类型为vector<char>::iterator it;
{
	*it = toupper(*it);
	cout << *it;
}
//可以改写为for (vector<char>::iterator it = s.begin(); it != s.end(); it++),auto可以让编译器自己判断迭代器类型

输出:

ABCDE

4.使用标准库算法std::for_each()来遍历容器,定义在头文件<algorithm>中,STL算法中for_each, for_each算法很常用,值得深入学习一下,很灵活。

vector<int> v{ 1,2,3,4,5 };
auto print = [](int i) { cout << i << " "; };
for_each(v.begin(), v.end(), print);

还可以这样写:

for_each(v.begin(), v.end(), [](int i){cout << i << " ";});

输出都是:

1 2 3 4 5

剩下的输出方法后续再补充...

五:vector常用方法

(1)访问元素
operator[]:通过索引访问向量中的元素。
at():通过索引访问向量中的元素,提供范围检查。
(2)容量操作
size():返回向量中的元素数量。
empty():检查向量是否为空。
capacity():返回向量当前的容量。
reserve():请求向量预留额外的存储空间。
shrink_to_fit():请求向量释放多余的存储空间。
(3)修改操作
push_back():在向量末尾添加一个元素。
pop_back():从向量末尾删除一个元素。
insert():在指定位置插入一个或多个元素。
erase():删除指定位置的一个或多个元素。
clear():清空向量中的所有元素。
(4)元素操作
front():返回向量中第一个元素的引用。
back():返回向量中最后一个元素的引用。
assign():用新值替换向量中的元素。
swap():交换两个向量的内容。
(5)查找
find():查找指定值在向量中的位置。
count():统计指定值在向量中出现的次数。
(6)迭代器
begin():返回指向第一个元素的迭代器。
end():返回指向最后一个元素之后的迭代器。

更新日志:

2023.5.22《C++primer》vector学习flag

2024.5.10 0:44 睡不着,起来更新vector的优缺点和维度问题,概述常用方法,有人看再更......

<think>好的,我现在需要帮助用户解决如何在C++中正确输出vector结构体的示例和用法。首先,我应该回忆一下C++vector的基本操作,以及如何遍历和输出其中的元素。用户提到了结构体,所以可能需要自定义一个结构体,比如Person,然后创建该结构体的vector,并输出每个元素的信息。 接下来,我需要确保使用正确的语法。对于结构体,通常需要重载输出运算符<<,这样在使用cout时可以直接输出结构体对象。不过,用户可能只需要一个简单的示例,所以也可以直接访问结构体的成员变量并输出。 然后,考虑如何初始化vector。用户提供的引用中提到了初始化std::vector<Person>并添加一些元素,所以示例中应该包括如何创建结构体实例并将它们添加到vector中。 遍历vector方法有多种,比如使用范围for循环、迭代器或者传统的下标访问。选择范围for循环可能更简洁易懂,适合示例代码。 还要注意包含必要的头文件,比如<iostream>和<vector>,以及使用命名空间std,或者明确使用std::前缀,避免潜在的作用域问题。 可能还需要考虑结构体的成员访问权限,如果是public的话,可以直接访问;否则可能需要提供公共的getter方法。但为了示例的简洁性,结构体的成员应该定义为public。 最后,确保代码能够编译运行,没有语法错误,并且输出结果符合预期,比如每个Person的姓名和年龄分行显示。 现在把这些思路整理成一个步骤清晰的示例,并验证代码的正确性。然后生成相关问题,确保问题主题相关,帮助用户进一步学习。</think>以下是C++输出vector结构体的示例和用法说明: ### 实现步骤 1. **定义结构体**:创建包含多个成员变量的自定义数据类型 ```cpp struct Person { std::string name; int age; }; ``` 2. **初始化vector**:创建并填充结构体vector ```cpp std::vector<Person> people = { {"Alice", 25}, {"Bob", 30}, {"Charlie", 28} }; ``` 3. **遍历输出**:使用范围for循环访问每个元素 ```cpp for (const auto& p : people) { std::cout << "Name: " << p.name << ", Age: " << p.age << std::endl; } ``` ### 完整示例代码 ```cpp #include <iostream> #include <vector> #include <string> struct Person { std::string name; int age; }; int main() { std::vector<Person> people = { {"Alice", 25}, {"Bob", 30}, {"Charlie", 28} }; for (const auto& p : people) { std::cout << "Name: " << p.name << ", Age: " << p.age << std::endl; } return 0; } ``` ### 输出结果 ``` Name: Alice, Age: 25 Name: Bob, Age: 30 Name: Charlie, Age: 28 ``` ### 关键点说明 - 使用`const auto&`避免不必要的拷贝[^1] - 范围循环`for (element : container)`是C++11引入的简洁遍历方式 - 结构体成员默认为public访问权限
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值