STL-vector-size

本文通过几个实例探讨了 C++ 中 vector 的不同初始化方式及其背后的行为差异,特别是使用下标与 push_back 方法的区别。文章揭示了不当使用可能导致的程序崩溃问题。

Env:

MacBook$ g++ –version
Configured with: –prefix=/Applications/Xcode.app/Contents/Developer/usr –with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix

OS:

Mac OSX 10.9.2

Compile:

-std=c++11

代码:

#include <iostream>
#include <vector>
#include <list>

int main (int argc, char *argv[])
{
    int n = 5;
    std::vector<int> nv(n, -1);
    std::vector<int> nv1, nv2, nv3, nv4, nv5, nv6, nv7;
    nv1.reserve(n);
    nv2.reserve(n);
    nv3.reserve(n);
    nv1[0] = 111;
    nv1[1] = 222;
    std::cout << "nv1 size " << nv1.size() << ", " << "nv1 capacity " << nv1.capacity() << std::endl    ;
    std::cout << "nv1[0] " << nv1[0] << ", " << "nv1[1]" << nv1[1] << std::endl;
    nv2.push_back(111);
    nv2.push_back(222);
    std::cout << "nv2 size " << nv2.size() << ", " << "nv2 capacity " << nv2.capacity() << std::endl    ;
    std::cout << "nv2[0] " << nv2[0] << ", " << "nv2[1]" << nv2[1] << std::endl;
    nv3[0] = 111;
    nv3.push_back(222);
   std::cout << "nv3 size " << nv3.size() << ", " << "nv3 capacity " << nv3.capacity() << std::endl    ;
    std::cout << "nv3[0] " << nv3[0] << ", " << "nv3[1]" << nv3[1] << std::endl;
    nv4.push_back(111);
    std::cout << "nv4 size " << nv4.size() << ", " << "nv4 capacity " << nv4.capacity() << std::endl    ;
    std::cout << "nv4[0] " << nv4[0] << std::endl;
    nv5[0] = 111;
    std::cout << "nv5 size " << nv5.size() << ", " << "nv5 capacity " << nv5.capacity() << std::endl    ;
    std::cout << "nv5[0] " << nv5[0] << std::endl;
    nv6[0] = 111;
    std::cout << "nv6 size " << nv6.size() << ", " << "nv6 capacity " << nv6    .capacity() << std::endl;
    std::cout << "nv6[0] " << nv6[0] << std::endl;
    std::list<int> nl7(n, -1);
    nv7.assign(nl7.begin(), nl7.end());
    std::cout << "nv7 size " << nv7.size() << ", " << "nv7 capacity " << nv7.capacity() << std::endl;
    nv7[0] = 111;
    std::cout << "nv7[0] " << nv7[0] << ", nv7[1]" <<  nv7[1] << std::endl;

    return 0;
}

结果:

nv1 size 0, nv1 capacity 5
nv1[0] 111, nv1[1]222
nv2 size 2, nv2 capacity 5
nv2[0] 111, nv2[1]222
nv3 size 1, nv3 capacity 5
nv3[0] 222, nv3[1]0
nv4 size 1, nv4 capacity 1
nv4[0] 111
Segmentation fault: 11

分析:

nv1 nv2 nv3均使用了 reserve 进行申请空间,所以 capacity 为 5.
nv1 使用下标赋值能够访问赋值成功并正常读取,但是 vector 的 size 并没有更新,所以 size 为 0.
nv2 使用 push_back() 进行赋值,成功并能正常读取,而且 size 也更新了.
nv3 先用下标赋值,赋值成功,显然 size 也没有更新了,后面再用 push_back() 赋值时,把 vector 当成空的来处理,把本来想放到第二个位置的元素值追加到第一个元素的位置了,所以再用下标读取第一个元素的时候是 push_back() 所追加的元素,而第二个元素是系统默认给的值 0.

nv4 nv5 没有申请空间.

nv4 用 push_back() 追加元素的时候,追加成功,能正常读取,并且 size 和 capacity 都为 1,说明 push_back() 申请了空间.

nv5 没有用debug 看细节,应该是赋值的时候就出问题了,目标内存不存在,没办法赋值.

把nv5注释掉,则nv6也是 Segmentation fault: 11

把nv5 nv6 都注释掉,nv7可以输出正常

nv7 size 5, nv7 capacity 5
nv7[0] 111, nv7[1] -1

结论:

看来使用 vector 用下标还是需要多注意 :) :) push_back()适合初始化,另外如果不是定义的时候指定大小,要先 reserve.

vector 两种初始化方法:

1.

std::vector<yourtype> var(numofvalue, intialvalue);

2.

std::vector<yourtype> var;
var.reserve(numofvalue);
for (int i=0; i<numofvalue; i++)
{
    var.push_back(intialvalue);
}
### C++ STL Vector 使用指南 #### 向量简介 `std::vector` 是一种动态数组,能够自动调整大小来容纳新元素。相比固定尺寸的 `std::array`,它提供了更灵活的数据存储方式[^4]。 #### 创建与初始化 可以创建不同类型的向量并对其进行初始化: ```cpp // 定义一个整数型向量 std::vector<int> intVector; // 初始化含有三个元素{1, 2, 3}的向量 std::vector<int> initVector = {1, 2, 3}; // 使用n个相同值elem初始化向量 size_t n = 5; int elem = 7; std::vector<int> sameValueVec(n, elem); ``` #### 添加和移除元素 支持多种方法用于增加或减少向量内的项目数量: - **push_back()**: 在向量末尾追加单个项目。 ```cpp int newItem = 9; intVector.push_back(newItem); // 追加到末尾 ``` - **pop_back()**: 移除最后一个元素而不返回其值。 ```cpp if (!intVector.empty()) { intVector.pop_back(); } ``` - **insert()**: 插入多个元素至指定位置。 ```cpp auto pos = intVector.begin() + 2; // 指定插入的位置 intVector.insert(pos, 4); // 单一数值插入 intVector.insert(pos, 3, 6); // 多个重复数值插入 ``` - **erase()**: 删除特定范围内的元素或者通过迭代器删除单一元素[^2]。 ```cpp // 清除第一个元素 if(!intVector.empty()){ intVector.erase(intVector.begin()); } // 或者清除某个具体位置上的元素 size_t indexToRemove = 3; if(indexToRemove < intVector.size()){ intVector.erase(intVector.begin() + indexToRemove); } ``` #### 访问元素 提供安全的方式访问内部储存的内容: - **下标运算符[]** - **at()** 方法(带边界检查) ```cpp if (!initVector.empty()) { std::cout << "First element is " << initVector[0]; try{ std::cout << "\nor first with at(): " << initVector.at(0); } catch(const std::out_of_range& e){ std::cerr << "Error accessing out of range."; } } ``` #### 赋值操作 允许整体替换现有内容或将两个对象之间的数据互相交换[^5]: ```cpp // 整体复制另一个向量的内容 sameValueVec.assign(initVector.begin(), initVector.end()); // 数据交换 sameValueVec.swap(initVector); // 等价于上面的操作也可以这样写 sameValueVec = initVector; ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值