本文总结vector的原理和使用方法。

1 vector的实现原理

1.2 vector保存在栈上还是堆上?

  1. 示例代码1:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
vector<int>* test_vec(void) {
    vector<int> vec;
    vec.push_back(1);
    vec.push_back(2);
    return &vec;
}

int main()
{
    vector<int>* o_vec = test_vec();
    printf("%d\n", (*o_vec)[0]);
    return 0;
}

在编译时会有如下提示:warning: reference to local variable 'vec' returned [-Wreturn-local-addr]。 而忽略该告警直接编译运行,进程会coredump。

  1. 示例代码2
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
vector<int> test_vec(void) {
    vector<int> vec;
    vec.push_back(1);
    vec.push_back(2);
    return vec;
}

int main()
{
    vector<int> o_vec = test_vec();
    printf("%d\n", o_vec[0]);
    return 0;
}

该段代码可以正常编译运行,无任何报错。

  1. 示例代码3
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
vector<int>* test_vec(void) {
    vector<int>* vec = new vector<int>;
    vec->push_back(1);
    vec->push_back(2);
    return vec;
}

int main()
{
    vector<int>* o_vec = test_vec();
    printf("%d\n", (*o_vec)[0]);
    return 0;
}

这段代码可以正常运行。

原因分析:

  1. 为什么示例代码1和实例代码2中的函数test_vec()相同,为啥返回vector变量的地址会coredump,而直接将vector的名字返回却可以正常运行呢? 答:因为C++ 11新特性中支持直接返回容器名会默认调用move()函数,参考1.3.1和1.3.2的内容。

1.3 C++中返回一个vector的方法

1.3.1 通过value返回

1
2
3
4
5
6
#include <vector> 
 
std::vector<int> createVector() { 
    std::vector<int> vec = {1, 2, 3, 4, 5}; 
    return vec;  // Move semantics will be applied here 
} 

1.3.2 通过move()函数

1
2
3
4
std::vector<int> createVector() { 
    std::vector<int> vec = {1, 2, 3, 4, 5}; 
    return std::move(vec);  // Explicitly moving the vector 
}

1.3.3 返回静态引用

1
2
3
4
std::vector<int>& getGlobalVector() { 
    static std::vector<int> vec = {1, 2, 3, 4, 5}; 
    return vec;  // Return a reference to a static vector 
} 

1.3.4 通过传入引用实现

1
2
3
void fillVector(std::vector<int>& vec) { 
    vec = {1, 2, 3, 4, 5};  // Modify the existing vector 
}

1.3.5 使用std::optional

1
2
3
4
5
6
7
8
9
#include <optional> 
#include <vector> 
 
std::optional<std::vector<int>> createVector(bool shouldCreate) { 
    if (shouldCreate) { 
        return std::vector<int>{1, 2, 3, 4, 5}; 
    } 
    return std::nullopt;  // No vector created 
}

相关参考文档:
Is there a way to return a vector more efficiently
一文带你详细介绍c++中的std::move函数
【Modern C++】深入理解左值、右值

2 vector的使用方法

2.1 vector初始化的方法

1
2
3
4
5
6
7
std::vector<int> first;                               // empty vector of ints
std::vector<int> second(4, 100);                      // four ints with value 100
std::vector<int> third(second.begin(),second.end());  // iterating through second
std::vector<int> fourth(third);                       // a copy of third

int tmp[] = { 10, 20, 30 };
std::vector<int> v(tmp, tmp + 3 ); // use some utility to avoid hardcoding the size here

2.2 vector容量相关

1
2
3
std::vector<int> vec(3, 235);
vec.size();  // return the number of elements
vec.empty(); // checks whether the container is empty

2.3 vector数据修改

1
2
3
std::vector<int> vec(3, 235); // init vector
vec.push_back(12);            // adds an element to the end 
vec.pop_back();               // removes the last element