问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

C++动态数组std::vector的使用与优化

创作时间:
作者:
@小白创作中心

C++动态数组std::vector的使用与优化

引用
CSDN
1.
https://m.blog.csdn.net/lixiaorong222/article/details/145481778

在C++的标准模板库STL中,包含了很多容器的数据结构,其中vector(向量)是一种动态数组,其大小可以动态变化。本文将详细介绍vector的使用方法和优化技巧。

vector的基本使用

vector在内存中是连续存储的,可以使用push_back方法添加元素。下面是一个简单的示例:

#include <iostream>
#include <vector>

struct Vertex {
    float x, y, z;
};

std::ostream& operator<<(std::ostream& stream, const Vertex v) {
    stream << v.x << "," << v.y << "," << v.z;
    return stream;
}

void print(const Vertex& v) {
    std::cout << v << std::endl;
}

int main() {
    std::vector<Vertex> vertexs;
    vertexs.push_back({1, 2, 3});
    vertexs.push_back({4, 5, 6});

    for (int i = 0; i < vertexs.size(); ++i) {
        std::cout << vertexs[i] << std::endl;
    }

    vertexs.erase(vertexs.begin() + 1);
    std::cout << "after erase:" << std::endl;
    for (Vertex& v : vertexs) {
        std::cout << v << std::endl;
    }

    std::cout << "size:" << vertexs.size() << std::endl;
    std::cout << "capacity:" << vertexs.capacity() << std::endl;

    vertexs.clear();
    std::cout << "after clear:" << std::endl;
    for (Vertex& v : vertexs) {
        print(v);
    }

    std::cout << "size:" << vertexs.size() << std::endl;
    std::cout << "capacity:" << vertexs.capacity() << std::endl;

    vertexs.shrink_to_fit();
    std::cout << "after shrink_to_fit:" << std::endl;
    std::cout << "size:" << vertexs.size() << std::endl;
    std::cout << "capacity:" << vertexs.capacity() << std::endl;

    std::cin.get();
}

输出结果表明:

  • clear和erase只会改变数组大小,删除元素内容,但不会销毁内存capacity;
  • shrink_to_fit会将内存调整到和数组大小一样大。

vector的内存管理机制

当vector容量不足时,需要将旧内存空间中的所有元素都拷贝进新内存空间中去,之后再在新内存空间中的原数据的后面继续进行插入构造新元素,并且同时释放旧内存空间。这也是vector动态扩容的机制。起始容量为0,不同编译器的扩容策略可能不同,例如GCC是2倍扩容,VS13是1.5倍扩容。

vector的优化技巧

使用emplace_back代替push_back

push_back总是会调用拷贝构造函数,而emplace_back支持直接传入构造函数需要的参数,不会调用拷贝构造函数,直接在数组中构造元素。下面是一个对比示例:

#include <iostream>
#include <vector>

class Vertex {
private:
    int x, y, z;
public:
    Vertex(int x, int y, int z) : x(x), y(y), z(z) {}
    Vertex(const Vertex& v) : x(v.x), y(v.y), z(v.z) {
        std::cout << "copy func()" << std::endl;
    }
};

int main() {
    std::vector<Vertex> vertexs;
    vertexs.reserve(5);

    std::cout << "capacity:" << vertexs.capacity() << " size:" << vertexs.size() << std::endl;

    Vertex v(1, 2, 3);
    std::cout << "push_back instance object:" << std::endl;
    vertexs.push_back(v); // copy func()

    std::cout << "emplace_back instance object:" << std::endl;
    vertexs.emplace_back(v); // copy func()

    std::cout << "push_back temp object:" << std::endl;
    vertexs.push_back(Vertex(1, 2, 3)); // copy func()

    std::cout << "emplace_back temp object:" << std::endl;
    vertexs.emplace_back(Vertex(1, 2, 3)); // copy func()

    std::cout << "emplace_back construct func:" << std::endl;
    vertexs.emplace_back(1, 2, 3); // 不调用拷贝函数

    return 0;
}

使用reserve预分配内存

reserve用于预分配内存,避免动态增长造成的开销。下面是一个使用reserve和resize的对比示例:

std::vector<Vertex> vertexs;
vertexs.reserve(10);
std::cout << "size:" << vertexs.size() << std::endl; // 0
std::cout << "capacity:" << vertexs.capacity() << std::endl; // 10

vertexs.reserve(0);
std::cout << "size:" << vertexs.size() << std::endl; // 0
std::cout << "capacity:" << vertexs.capacity() << std::endl; // 10

vertexs.push_back({1, 2, 3});
vertexs.push_back({4, 5, 6});
std::cout << "size:" << vertexs.size() << std::endl; // 2
std::cout << "capacity:" << vertexs.capacity() << std::endl; // 10

vertexs.resize(1);
std::cout << "size:" << vertexs.size() << std::endl; // 1
std::cout << "capacity:" << vertexs.capacity() << std::endl; // 10

vertexs.resize(20);
std::cout << "size:" << vertexs.size() << std::endl; // 20
std::cout << "capacity:" << vertexs.capacity() << std::endl; // 20

总结

为了优化vector的性能,可以采取以下措施:

  1. 使用reserve进行内存预分配;
  2. 使用emplace_back进行传参添加元素;
  3. 使用引用传递数组。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号