文章目录
安插和移除元素
c.push_back()
在C++中,std::vector的push_back成员函数用于在vector的末尾添加一个元素。这个操作的时间复杂度通常是常数时间,即O(1),这是因为vector通常在其内部进行动态内存分配,以便在需要时能够容纳更多的元素。当vector的大小达到其当前分配的内存大小时,它会自动分配更多的内存空间,并将所有现有元素复制到新的内存区域,然后再添加新元素。
下面是一个使用std::vector::push_back的示例:
#include <iostream>
#include <vector>
int main() {
// 创建一个空的vector
std::vector<int> numbers;
// 使用push_back添加元素到vector的末尾
numbers.push_back(10);
numbers.push_back(20);
numbers.push_back(30);
// 遍历vector并输出所有元素
for (const auto& num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// 添加另一个元素到末尾
numbers.push_back(40);
// 再次遍历vector以显示新添加的元素
for (const auto& num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,我们首先创建了一个空的std::vector,然后使用push_back添加了几个整数到vector的末尾。每次调用push_back时,它都会在vector的末尾添加一个新元素。然后,我们通过范围for循环遍历vector并输出所有元素的值。在添加最后一个元素之后,我们再次遍历vector以显示新添加的元素。
值得注意的是,当vector需要重新分配内存以容纳更多元素时,这个过程可能会导致一定的性能开销,因为需要重新复制所有现有元素。因此,在已知vector最终大小的情况下,使用std::vector::reserve预先分配足够的内存空间可以提高性能。例如,numbers.reserve(100);将预先为vector分配足够的空间以容纳至少100个元素,从而减少了因内存重新分配而导致的性能开销。
c.pop_back()
在C++中,std::vector的pop_back()成员函数用于删除vector的最后一个元素。换句话说,它缩减了vector的大小,使其减少一个元素,并释放了最后一个元素所占用的内存。如果vector已经是空的,调用pop_back()会导致未定义行为,所以通常在使用pop_back()之前,你应该检查vector是否至少有一个元素。
下面是一个使用std::vector::pop_back()的示例:
#include <iostream>
#include <vector>
int main() {
// 创建一个包含一些整数的vector
std::vector<int> numbers = {10, 20, 30, 40, 50};
// 输出vector的大小和元素
std::cout << "Size of vector: " << numbers.size() << std::endl;
std::cout << "Elements in vector: ";
for (const auto& num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// 删除最后一个元素
numbers.pop_back();
// 再次输出vector的大小和元素
std::cout << "Size of vector after pop_back(): " << numbers.size() << std::endl;
std::cout << "Elements in vector after pop_back(): ";
for (const auto& num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// 尝试在空vector上调用pop_back()会导致未定义行为
// if (!numbers.empty()) {
// numbers.pop_back();
// }
return 0;
}
在这个例子中,我们首先创建了一个包含5个整数的vector。然后,我们输出vector的大小和所有元素。接着,我们调用pop_back()来删除最后一个元素,并再次输出vector的大小和剩余元素。
请注意,如果你尝试在一个已经为空的vector上调用pop_back(),程序的行为将是未定义的。因此,在调用pop_back()之前,通常应该检查vector是否至少有一个元素,这可以通过使用empty()成员函数来完成。
if (!numbers.empty()) {
numbers.pop_back();
}
添加这样的检查可以避免在空vector上调用pop_back(),从而防止未定义行为。
c.insert(pos,n,elem)
在C++中,std::vector的insert成员函数用于在指定位置插入一个或多个元素。具体来说,insert函数的签名如下:
iterator insert(const_iterator pos, size_type n, const value_type& elem);
这里的参数解释如下:
- pos:一个指向vector中某个位置的迭代器,表示要在哪里开始插入新元素。
- n:要插入的元素数量。
- elem:要插入的元素的值。
insert函数会在pos指定的位置之前插入n个值为elem的元素。这会导致vector的大小增加n,并且所有在pos及之后位置的元素都会被向后移动n个位置。如果n为0,则insert函数不会有任何效果。
下面是一个使用std::vector::insert的示例:
#include <iostream>
#include <vector>
int main() {
// 创建一个包含一些整数的vector
std::vector<int> c = {1, 2, 4, 5};
// 在位置2插入3个值为3的元素
auto pos = c.begin() + 2; // pos指向c中的4
c.insert(pos, 3, 3); // 在4之前插入3个3
// 遍历并输出vector的所有元素
for (const auto& elem : c) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,我们创建了一个包含四个整数的vector:{1, 2, 4, 5}。然后,我们使用insert函数在位置2(即数字4之前)插入了3个值为3的元素。因此,vector现在变为{1, 2, 3, 3, 3, 4, 5}。
请注意,插入操作可能会导致vector重新分配内存(如果当前分配的内存不足以容纳所有元素),这可能会是一个相对昂贵的操作。因此,如果你知道vector最终将包含多少元素,使用reserve预先分配足够的内存空间可以提高性能。
c.insert(pos,beg,end)
在C++中,std::vector的insert成员函数有一个重载版本,它允许你插入一个迭代器范围内的元素。这个版本的insert函数接受三个参数:
- pos:一个指向vector中某个位置的迭代器,表示要在哪里开始插入新元素。
- beg:一个指向要插入元素范围的起始位置的迭代器。
- end:一个指向要插入元素范围的结束位置的迭代器(该位置的元素不会被插入)。
这个版本的insert函数会将[beg, end)范围内的所有元素插入到pos指定的位置之前。这会导致vector的大小增加,并且所有在pos及之后位置的元素都会被向后移动以容纳新插入的元素。
下面是一个使用std::vector::insert的示例,其中插入了一个来自另一个vector的元素范围:
#include <iostream>
#include <vector>
int main() {
// 创建第一个vector并添加一些元素
std::vector<int> source = {1, 2, 3, 4, 5};
// 创建第二个vector并添加一些元素
std::vector<int> destination = {10, 20, 30};
// 指定在destination的哪个位置插入元素
auto insert_pos = destination.begin() + 1; // 在20之前插入
// 使用insert函数插入source中的元素到destination中
destination.insert(insert_pos, source.begin(), source.end());
// 遍历并输出destination的所有元素
for (const auto& elem : destination) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,我们有两个vector:source和destination。我们想要将source中的所有元素插入到destination的第二个位置(即数字20之前)。我们使用begin()和end()函数来获取source的迭代器范围,并将其作为参数传递给destination的insert函数。
执行这段代码后,destination vector将包含以下元素:10 1 2 3 4 5 20 30。
请注意,如果beg和end迭代器不属于同一个容器(在这个例子中是source),那么它们指向的元素类型必须与被插入的vector(在这个例子中是destination)的元素类型相同或兼容。此外,beg不能等于end,否则插入操作将不会有任何效果。
c.insert(pos,initlist)
在C++中,std::vector的insert成员函数有一个重载版本,它允许你插入一个初始化列表(initializer list)的元素。这个版本的insert函数接受两个参数:
- pos:一个指向vector中某个位置的迭代器,表示要在哪里开始插入新元素。
- initlist:一个C++11引入的初始化列表,其中包含要插入的元素。
使用初始化列表来插入元素可以很方便地构造和插入一组值。以下是一个使用std::vector::insert和初始化列表的示例:
#include <iostream>
#include <vector>
int main() {
// 创建一个vector并添加一些元素
std::vector<int> vec = {1, 2, 4, 5};
// 指定在vector的哪个位置插入元素
auto pos = vec.begin() + 2; // 在位置2(即4之前)插入元素
// 使用初始化列表插入元素
vec.insert(pos, {3, 3, 3}); // 插入3个值为3的元素
// 遍历并输出vector的所有元素
for (const auto& elem : vec) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,我们有一个包含四个整数的vector:{1, 2, 4, 5}。我们想要在位置2(即数字4之前)插入三个值为3的元素。我们使用insert函数和一个初始化列表{3, 3, 3}来实现这一点。执行这段代码后,vector将变为{1, 2, 3, 3, 3, 4, 5}。
初始化列表是C++11及以后版本中引入的一种特性,它提供了一种方便的方式来初始化对象,特别是当需要多个相同类型的值时。使用初始化列表来插入元素可以简化代码,并且通常比使用insert的其他重载版本更加直观和高效。
c.emplace(pos,args…)
在C++中,std::vector的emplace成员函数允许你在指定位置构造并插入一个元素,而不需要进行额外的拷贝或移动操作。这与insert函数不同,因为insert通常涉及现有元素的拷贝或移动。
emplace函数的签名如下:
iterator emplace(const_iterator pos, args&&... args);
这里的参数解释如下:
- pos:一个指向vector中某个位置的迭代器,表示要在哪里构造并插入新元素。
- args:传递给元素构造函数的参数。这些参数是前向声明的(forwarding references),这意味着它们可以以最优的方式传递给元素构造函数,支持完美转发(perfect forwarding)。
emplace函数会在pos指定的位置之前构造一个新元素,并将它插入到vector中。这不会导致vector的大小增加,因为emplace是就地构造元素,不需要额外的空间来存储临时对象。
下面是一个使用std::vector::emplace的示例:
#include <iostream>
#include <vector>
int main() {
// 创建一个包含一些整数的vector
std::vector<int> v = {1, 2, 4, 5};
// 在位置2就地构造并插入一个值为3的元素
auto pos = v.begin() + 2; // pos指向v中的4
v.emplace(pos, 3); // 在4之前构造并插入一个值为3的元素
// 遍历并输出vector的所有元素
for (const auto& elem : v) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,我们创建了一个包含四个整数的vector:{1, 2, 4, 5}。然后,我们使用emplace函数在位置2(即数字4之前)就地构造并插入了一个值为3的元素。因此,vector现在变为{1, 2, 3, 4, 5}。
使用emplace而不是insert或push_back等可能导致拷贝或移动的函数,在性能上是更优的,尤其是在元素类型涉及到复杂构造或资源分配时。
c.emplace_back(args…)
在C++中,std::vector的emplace_back成员函数是一个方便的方式来在vector的末尾就地构造并添加一个新元素。这个函数接受一组参数,这些参数会被直接传递给元素的构造函数,避免了不必要的拷贝或移动操作。
emplace_back的签名类似于emplace,但它总是在vector的末尾插入元素,所以不需要提供迭代器来指定位置。
这是emplace_back的一个基本示例:
#include <iostream>
#include <vector>
class MyClass {
public:
MyClass(int x, double y) : x_(x), y_(y) {}
void print() const {
std::cout << "MyClass(" << x_ << ", " << y_ << ")" << std::endl;
}
private:
int x_;
double y_;
};
int main() {
// 创建一个空的vector
std::vector<MyClass> vec;
// 使用emplace_back在vector的末尾就地构造并添加一个元素
vec.emplace_back(10, 20.5);
// 遍历并打印vector中的所有元素
for (const auto& elem : vec) {
elem.print();
}
return 0;
}
在这个例子中,我们定义了一个简单的MyClass类,它接受两个参数(一个int和一个double)的构造函数。然后,我们创建了一个std::vector类型的vector,并使用emplace_back在vector的末尾添加了一个MyClass的实例,通过直接传递构造函数的参数来就地构造这个实例。
使用emplace_back而不是push_back的好处是,当插入一个元素时,不需要先创建一个临时对象,然后再将其拷贝或移动到vector中。这可以提高效率,尤其是当元素类型涉及到复杂的构造或资源分配时。
需要注意的是,emplace_back只能用于在vector的末尾添加元素,如果你需要在vector的中间位置插入元素,应该使用emplace函数并提供一个迭代器来指定插入位置。
c.erase()
在C++中,std::vector的erase成员函数用于删除指定位置的元素。它接受一个指向要删除元素的迭代器作为参数,并返回一个指向被删除元素之后元素的迭代器。
这是erase函数的基本用法:
iterator erase(const_iterator pos);
如果你想删除一系列元素,可以使用erase的另一个重载版本,它接受两个迭代器作为参数,一个指向要删除范围的起始位置,另一个指向结束位置的下一个位置:
iterator erase(const_iterator first, const_iterator last);
下面是使用erase删除单个元素的示例:
#include <iostream>
#include <vector>
int main() {
// 创建一个包含一些整数的vector
std::vector<int> vec = {1, 2, 3, 4, 5};
// 指定要删除的元素的位置
auto pos = vec.begin() + 2; // 删除位置2的元素,即数字3
// 使用erase删除元素
vec.erase(pos);
// 遍历并输出vector的所有元素
for (const auto& elem : vec) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,vector {1, 2, 3, 4, 5} 中的数字3被删除了,所以输出将是 {1, 2, 4, 5}。
如果你想删除一系列元素,可以使用两个迭代器的版本,如下所示:
#include <iostream>
#include <vector>
int main() {
// 创建一个包含一些整数的vector
std::vector<int> vec = {1, 2, 3, 4, 5};
// 指定要删除的元素范围
auto first = vec.begin() + 1; // 删除从位置1开始的元素,即数字2
auto last = vec.begin() + 4; // 到位置4之前的元素,即数字5(但不包括5)
// 使用erase删除元素范围
vec.erase(first, last);
// 遍历并输出vector的所有元素
for (const auto& elem : vec) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,vector {1, 2, 3, 4, 5} 中的数字2、3和4被删除了,所以输出将是 {1, 5}。注意,last迭代器指向的是要删除范围之后的第一个元素,所以它不被包括在删除范围内。
c.resize(num)
在C++中,std::vector的resize成员函数用于改变vector的大小。这个函数接受一个参数num,表示vector应该被调整为多少个元素。如果num大于当前vector的大小,resize会在vector的末尾添加新元素,并使用默认值来初始化这些元素。如果num小于当前vector的大小,resize会删除末尾的一些元素。
这里有几个resize的使用示例:
#include <iostream>
#include <vector>
int main() {
// 创建一个包含一些整数的vector
std::vector<int> vec = {1, 2, 3, 4, 5};
// 输出原始vector的大小和内容
std::cout << "Original size: " << vec.size() << std::endl;
for (int num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;
// 使用resize增大vector的大小
vec.resize(10);
std::cout << "After resizing to 10 elements:" << std::endl;
for (int num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;
// 使用resize减小vector的大小
vec.resize(3);
std::cout << "After resizing to 3 elements:" << std::endl;
for (int num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,我们首先创建了一个包含5个整数的vector。然后,我们使用resize(10)将vector的大小增大到10个元素。因为vector原先只有5个元素,所以resize会在末尾添加5个新元素,这些新元素会被初始化为int类型的默认值(通常是0)。
接下来,我们使用resize(3)将vector的大小减小到3个元素。这会删除vector末尾的7个元素,只保留前3个元素。
注意,如果你想要用特定的值来初始化新添加的元素,你可以给resize函数传递第二个参数,这个参数是一个值,用于初始化新添加的元素。例如,vec.resize(10, 100)会在vector末尾添加10个新元素,并将它们初始化为100。
c.resize(num,elem)
在C++中,std::vector的resize成员函数有两个参数的形式,允许你调整vector的大小,并在需要的情况下用指定的元素值填充新添加的元素。
这个函数的签名如下:
void resize(size_type num, const value_type& elem = value_type());
其中:
- num 是你想要调整到的vector的新大小。
- elem 是一个可选参数,表示用于初始化新添加元素的值。如果不提供这个参数,新添加的元素将会使用类型的默认构造函数进行初始化。
下面是使用两个参数形式的resize函数的示例:
#include <iostream>
#include <vector>
int main() {
// 创建一个包含一些整数的vector
std::vector<int> vec = {1, 2, 3, 4, 5};
// 输出原始vector的大小和内容
std::cout << "Original size: " << vec.size() << std::endl;
for (int num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;
// 使用resize增大vector的大小,并用100初始化新元素
vec.resize(10, 100);
// 输出调整大小后的vector
std::cout << "After resizing to 10 elements with value 100:" << std::endl;
for (int num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,原始的vector {1, 2, 3, 4, 5} 通过 resize(10, 100) 被调整到了10个元素的大小。因为原始vector只有5个元素,所以resize函数添加了5个新元素,并用100初始化它们。因此,调整大小后的vector将是 {1, 2, 3, 4, 5, 100, 100, 100, 100, 100}。
请注意,如果num小于vector的当前大小,resize函数将删除末尾的一些元素,以保持vector的大小为num。在这种情况下,elem参数将被忽略,因为不需要初始化任何新元素。
c.clear()
在C++中,std::vector的clear成员函数用于移除vector中的所有元素,使其大小变为0,但保留其容量不变。这意味着vector仍然分配了内存,但不再包含任何元素。
clear函数的定义很简单,不需要任何参数:
void clear();
使用clear函数可以高效地清空一个vector,因为它只是简单地设置vector的大小为0,而不会释放其内部分配的内存。如果需要释放vector占用的内存,可以使用swap方法或者重新分配内存(例如通过resize(0)或shrink_to_fit)。
下面是一个使用clear函数的示例:
#include <iostream>
#include <vector>
int main() {
// 创建一个包含一些整数的vector
std::vector<int> vec = {1, 2, 3, 4, 5};
// 输出原始vector的大小和内容
std::cout << "Original size: " << vec.size() << std::endl;
for (int num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;
// 使用clear清空vector
vec.clear();
// 输出清空后vector的大小
std::cout << "After clearing, size: " << vec.size() << std::endl;
// 由于vector已清空,这里不会输出任何数字
for (int num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,vec.clear()调用将vector vec中的所有元素移除,使其大小变为0。清空后的vector不再包含任何元素,因此循环遍历它时不会输出任何数字。
如果你想要减少vector占用的内存,可以使用resize(0)或shrink_to_fit。resize(0)会将vector的大小设置为0,并可能释放一些内存,但不一定会完全释放所有内存。shrink_to_fit是一个尝试减少vector容量的方法,但它并不保证一定会减少容量,这取决于具体的实现和内存管理器。
// 释放vector占用的内存
vec.resize(0);
// 或者
vec.shrink_to_fit();
请注意,shrink_to_fit是一个C++11引入的函数,并且不是所有的标准库实现都会减少容量。在一些实现中,它可能只是简单地调用resize(0)。要确定是否真正减少了容量,可以查看vector的capacity成员函数返回的值。