std::vector

std::vector 是 C++ 标准模板库 (STL) 中的一个动态数组容器。

std::vector 初始化

#include <array>
#include <iostream>
#include <vector>
int main() {
    // 默认初始化 创建一个空的 std::vector。
    std::vector<int> vec1;

    // 指定大小的初始化 创建一个包含10个元素的vector,元素值为0(对于int类型)
    std::vector<int> vec2(10);

    // 指定大小和初始值的初始化 创建一个包含10个元素的vector,元素值均为5
    std::vector<int> vec3(10, 5);

    // 列表初始化 使用花括号 {} 直接初始化 std::vector。
    std::vector<int> vec4 = {1, 2, 3, 4, 5};

    // 使用迭代器范围初始化 从另一个容器或 std::vector 中复制元素。
    std::vector<int> source = {1, 2, 3, 4, 5};
    std::vector<int> vec5(source.begin(), source.end());

    // 使用 std::array 初始化 从 std::array 初始化 std::vector。
    std::array<int, 5> arr = {1, 2, 3, 4, 5};
    std::vector<int> vec6(arr.begin(), arr.end());

    // 从指针范围初始化 通过指针初始化 std::vector。
    int arr2[] = {1, 2, 3, 4, 5};
    std::vector<int> vec7(arr2, arr2 + 5);

    return 0;
}

插入元素

vector::push_backvector::emplace_back 都是 C++ 标准库中 std::vector 提供的成员函数,用于在向量末尾添加元素。它们之间的主要区别在于处理对象的方式和效率:

push_back

push_back 会将一个已经存在的对象复制(或移动)到向量的末尾。这意味着需要调用对象的拷贝构造函数或移动构造函数。如果对象的拷贝或移动操作比较昂贵,那么 push_back 的性能可能会受到影响。

示例:

std::vector<std::string> vec;
std::string str = "Hello, World!";
vec.push_back(str);  // 将str的副本添加到vec的末尾

emplace_back

emplace_back 直接在向量的末尾构造对象,避免了不必要的拷贝或移动。这通常会带来性能上的提升,特别是对于复杂对象。

示例:

std::vector<std::string> vec;
vec.emplace_back("Hello, World!");  // 直接在vec的末尾构造一个std::string对象

选择 push_back 还是 emplace_back

  • 如果你已经有一个现成的对象,并且只是想将它添加到向量末尾,使用 push_back
  • 如果你希望直接在向量末尾构造一个对象,避免不必要的拷贝或移动,使用 emplace_back

示例代码对比

#include <iostream>
#include <vector>
#include <string>

struct MyClass {
    MyClass(int x, double y) {
        std::cout << "Constructed with (" << x << ", " << y << ")\n";
    }
    MyClass(const MyClass& other) {
        std::cout << "Copy constructed\n";
    }
    MyClass(MyClass&& other) noexcept {
        std::cout << "Move constructed\n";
    }
};

int main() {
    std::vector<MyClass> vec;

    // 使用 push_back
    MyClass obj(10, 20.5);
    vec.push_back(obj);  // 会调用一次拷贝构造函数

    // 使用 emplace_back
    vec.emplace_back(30, 40.5);  // 直接构造,没有拷贝或移动

    return 0;
}

运行结果:

Constructed with (10, 20.5)
Copy constructed
Constructed with (30, 40.5)

从上面的输出可以看出,push_back 会调用一次拷贝构造函数,而 emplace_back 直接在向量末尾构造对象,避免了额外的拷贝操作。

reserve() 方法 预留 std::vector 的容量

使用 reserve() 可以预留 std::vector 的容量,而不改变其大小。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 预留容量为 10
    vec.reserve(10);

    std::cout << "Vector size: " << vec.size() << "\n";         // 输出:Vector size: 5
    std::cout << "Vector capacity: " << vec.capacity() << "\n"; // 输出:Vector capacity: 10

    return 0;
}

上面代码,虽然 vec 的实际大小仍然是原来的大小(5),但容量增加到了至少能容纳 10 个元素的大小。这对于避免多次动态分配内存,提高性能是有帮助的,特别是在你知道 std::vector 将来会存储更多元素的情况下。

reserve(n) 只有在需要时才会增加容量,而不会减少容量,因此如果 n 小于当前容量,容量保持不变。
比如vec初始大小为5,调用vec.reserve(2) 不会改变vec.capacity()

resize()方法 改变 std::vector 的大小

resize() 函数用于改变 std::vector 的大小,可以增加或减少元素数量。如果增加大小,新元素会被默认初始化。如果减少大小,多余的元素会被删除。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    vec.resize(7);
    std::cout << "Vector size: " << vec.size() << "\n"; 		// 输出:Vector size: 7
    std::cout << "Vector capacity: " << vec.capacity() << "\n"; // 输出:Vector capacity: 10
    return 0;
}

为什么resize分配了7,而capacity容量确是10?
std::vector 的 capacity 是由标准库实现管理的,以优化性能和内存使用。resize 方法改变的是 size(元素数量),而不是 capacity(已分配内存)。当 resize 增加 size 时,vector 可能会重新分配内存以容纳新元素,新的 capacity 往往是以某种策略(例如倍增策略)增加的,以减少将来频繁分配内存的次数。

clear()方法 移除 std::vector 的所有元素

std::vector 的 clear 方法用于移除 vector 中的所有元素,但不改变 vector 的容量(capacity)。也就是说,clear 会将 vector 的大小(size)变为零,但 vector 仍然保留它已经分配的内存。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    vec.clear();
    std::cout << "Vector size: " << vec.size() << "\n";
    std::cout << "Vector capacity: " << vec.capacity() << "\n";
    for (int i : vec) {
        std::cout << i << " ";
    }
    return 0;
}

检查方法

  • vec.size() 容器中的元素数量
  • vec.empty() 容器是否为空
  • vec.capacity() 容器容量

删除元素

#include <vector>
#include <iostream>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 删除最后一个元素
    vec.pop_back();

    // 使用迭代器删除指定位置的元素
    vec.erase(vec.begin() + 1); // 删除第二个元素

    // 清空 vector
    vec.clear();

    std::cout << "Size after clear: " << vec.size() << std::endl;

    return 0;
}

遍历元素

#include <vector>
#include <iostream>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 使用下标遍历
    for (size_t i = 0; i < vec.size(); ++i) {
        std::cout << vec[i] << " ";
    }
    std::cout << std::endl;

    // 使用迭代器遍历
    for (auto it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // 使用范围for循环
    for (const auto &elem : vec) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

修改元素

#include <vector>
#include <iostream>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 修改元素值
    vec[0] = 10;
    vec.at(1) = 20;

    for (const auto &elem : vec) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值