目的

本文从实际使用的角度出发,简介C++中vector的基本用法,如增,删,改,查等,并举例说明。

如下代码演示如何向vector中添加元素,其中:

#include <iostream>
#include <vector>

#include <iostream>
#include <vector>

int main() {
    std::vector<int> ilist;
    ilist.push_back(1);
    ilist.emplace_back(5); // append last
    ilist.insert(ilist.begin(), 3); // insert first
    ilist.emplace(ilist.begin(), 2);

    return 0;
}
  • push_back()和emplace_back()方法都是向数组末尾插入元素。
  • insert()方法和emplace()方法都接受数组的迭代器(上例中完整的类型为std::vector::iterator)作为插入的位置信息。其中begin()方法返回迭代器,表示数组的首地址。
  • insert()和emplace()方法的区别是emplace()方法可以帮助构建对象,因此对性能有点儿帮助,如下例中所示。
class Student {
    public: Student(std::string name) { }
};

int main() {
    std::vector<Student> slist;
    slist.push_back(Student("hello"));
    slist.emplace_back("hello");

    return 0;
}

通过erase()方法可以删除迭代提所指向的某个数据,如删除vector的第一个数据:

std::vector<int> ilist = { 1, 2, 3 };
ilist.erase(ilist.begin());

或者通过erase()方法删除连续的几个数据,如下把数组的前三个数据都删除:

std::vector<int> ilist = { 1, 2, 3, 4, 5 };
ilist.erase(ilist.begin(), ilist.begin() + 3);

在数据中查找具体的值然后删掉也经常会用到,如下代码片段将数组中所有的3删除:

std::vector<int> ilist = { 1, 2, 3, 3, 5 };

std::vector<int>::iterator i = ilist.begin();
while (i != ilist.end()) {
    if (*i == 3)
        i = ilist.erase(i);
    else
        i++;
}
  • erase()方法会返回下一个迭代器。
  • 这里用while比用for好写点儿,因为erase()可能会返回end(),在for的++中容易crash。

如果觉得写起来很麻烦的话,用stl 的algorithm 中的remove()方法也可以把所有值为3的数据删除:

#include <algorithm>

std::vector<int> ilist = { 1, 2, 3, 3, 5 };
ilist.erase(std::remove(ilist.begin(), ilist.end(), 3), ilist.end());

使用stl 的algorithm 中的remove_if()方法与lambda的组合可以更灵活的删除vector中的数据,如下删除所有>3的数据:

std::vector<int> ilist = { 1, 2, 3, 3, 5 };

auto removeLambda = [](int number) -> bool {
    return number > 3;
};
ilist.erase(std::remove_if(ilist.begin(), ilist.end(), removeLambda), ilist.end());

使用下标运算符[]修改数据中的数据:

std::vector<int> ilist = { 1, 2, 3, 3, 5 };
ilist[0] = 3;

或者使用迭代器指针与*运算符修改:

std::vector<int> ilist = { 1, 2, 3, 3, 5 };
auto i = ilist.begin();
*i = 3;

使用数组下标在for循环中查找所有为3的数据:

std::vector<int> ilist = { 1, 2, 3, 3, 5 };
for (int i = 0; i < ilist.size(); i++) {
    if (ilist[i] == 3) {
        // TODO FIND IT
    }
}

或者使用迭代器查找,一般来说,C++中的迭代器使用!=运算符作为终止条件,不像下标使用<:

std::vector<int> ilist = { 1, 2, 3, 3, 5 };
for (auto i = ilist.begin(); i != ilist.end(); i++) {
    if (*i == 3) {
        // TODO FIND IT
    }
}

感谢C++11的语法,有了更简介的for循环用法:

std::vector<int> ilist = { 1, 2, 3, 3, 5 };
for (auto i : ilist) {
    if (i == 3) {
        // TODO FIND IT
    }
}
  • 需要注意的是,auto i : ilist中的i需要发生一次数据拷贝。
  • 使用auto &i : ilist可以避免数据的拷贝,如果vector中存放的是unique_ptr, 这会很有用,因为只能这么写:)。

排序

使用stl 的algorithm 中的sort()方法对数组做升序排列,使用reverse()方法做降序排列。

std::vector<int> ilist = { 3, 2, 7, 5, 9};
std::sort(ilist.begin(), ilist.end());

如果vector中存放了自定义的类型,恰好又没有重载>或者<运算符的话,sort()数据也可以接收自定义的排序函数或者使用lambda:

std::vector<int> ilist = { 3, 2, 7, 5, 9};
std::sort(ilist.begin(), ilist.end(),
          [](int a, int b) { return a > b; });

总结

  • 新版本的c++标准容器中已经可以存放unique_ptr了。

引用

[1] https://stackoverflow.com/questions/9025084/sorting-a-vector-in-descending-order
[2] https://en.cppreference.com/w/cpp/algorithm/remove
[3] https://stackoverflow.com/questions/5122804/how-to-sort-with-a-lambda

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐