C++ 容器vector等中为什么尽量使用const引用

1 无疑使用const引用是一个好习惯,除非有理由拒绝它

在C++中容器都是值拷贝的,因此不使用引用的化,会大量拷贝垃圾数据
其实,可以这么说C/C++是值拷贝编程语言。不使用额外的技术,比如指针、引用,都会发生垃圾数据的拷贝。当然,到底是不是垃圾数据由你自己决定,值拷贝是无法彻底摒弃的。

2 看一个案例

下面是一个提交记录,注意红色方框的部分,加上引用,和不加引用的区别
两次消耗内存的,相比下,节省了90M,你想想90M内存要存多少int的数据???
时间也节省了很多,16ms的CPU处理时间,,,
在这里插入图片描述

3 不改变元素一定要加上const,不需要拷贝需要加上&

其实,有时候要返回一个空的容器,那么问题来了,返回值不能是空容器的引用,语法错误,
这时候,你直接放进形参[out]即可
最重要的是,不要把容器作为返回值,至少有如下缺点

  1. 不能返回空容器的引用
  2. 返回临时变量的引用,直接异常

其实函数的返回值的目的是记录函数是否正确运行,没有出错,void就行了

4 最后,简谈下数组和容器

我觉的容器的一个最大的优点是,存储在堆上,也就是它的大小动态变化的,就是常使用的push_back方法。
这样很好,因为数组实际储存在栈上的,这样会导致不能定义大数组,比如在windows上栈的大小是1M,大概不超过26万个int, 2 10 ∗ 2 10 / 4 = 2 18 2^{10} * 2^{10}/4 =2^{18} 210210/4=218,Linux的栈是8M

我认为一个缺点是,使用下标访问的时候,容器的大小必须给定,比如在很多的API中,都需要提前给定容器的大小,当然后面提出了back_insert迭代器解决了这个问题,但是,其他其他任然会有问题

请看一个案例,这里用res做为输出,前面已经解释了不用容器最为返回值哈,由于传进来的res,容器为0,如果直接返回将会异常。

void count0_1(const string& str, vector<int>& res) {
    for (const auto& e : str){
    	res[0]++;		/**<ERROR */
    }
}

修改, 需要多少,我就提前push_back

void count0_1(const string& str, vector<int>& res) {
	/**<increase size of res*/
	for i to needed:
		res.push_back(0);
		
    for (const auto& e : str){
    	res[0]++;		/**<ERROR */
    }
}

当然,如果函数内部返回的数组大小已知,就用原始数组(栈),或者array,没错,array存储在堆上的。
下面看看,用array来解决固定大小数组的问题,
注意,array不会初始化,这里用初值列进行初始化,
实际上array和原始数组的性能基本一致,所以也建议使用。

void count0_1(const string& str, array<int, 2>& res) {
    for (const auto& e : str)
        ++res[e - '0'];
}

array<int, 2> weight{};		/**<2个固定大小的数组 */

用原始数组,

void count0_1(const string& str, int *res) {
    for (const auto& e : str)
        ++res[e - '0'];
}

int weight[2];

最后,总结下,不管怎么说,

  1. 函数返回值只是表征函数正确执行与否
  2. 形参是出参的很常见,尤其在C中,通过指针送出大量数据
  3. array的性能和原始数组差不多,C++人员不妨习惯使用它
  4. vector需要注意的是,容器大小没有提前给定,访问元素是错误的

一个小问题,既然堆上能分配大量数组,那么它的极限是多少呢?
很明显,和物理内存的大小有关,不过还与操作系统有关,比如下面一个常见的错误,
0x7fffffff 字节,也就是 2 31 2^{31} 231个元素,int的数据就有8G大小,感兴趣可以学习下

ERROR: 数组的总大小不得超过 0x7fffffff 字节
C++vector是一个动态数组容器,可以存储任意类型的元素。它提供了许多方法来方便地操作和管理数组。 以下是C++vector容器的一些常用用法: 1. 包含头文件: ```cpp #include <vector> ``` 2. 创建Vector对象: ```cpp std::vector<T> vec; // 创建一个空的vector std::vector<T> vec(size); // 创建一个具有指定大小的vector std::vector<T> vec(size, value); // 创建一个具有指定大小和初始值的vector ``` 3. 添元素: - 使用push_back()方法在vector末尾添元素: ```cpp vec.push_back(element); ``` - 使用insert()方法在指定位置插入元素: ```cpp vec.insert(vec.begin() + index, element); ``` 4. 访问元素: - 使用下标运算符[]访问指定索引位置的元素: ```cpp T element = vec[index]; ``` - 使用at()方法访问指定索引位置的元素,可以进行越界检查: ```cpp T element = vec.at(index); ``` 5. 获取容器大小: ```cpp int size = vec.size(); // 获取容器元素的个数 ``` 6. 遍历容器: - 使用for循环遍历: ```cpp for (int i = 0; i < vec.size(); ++i) { // 处理vec[i] } ``` - 使用迭代器遍历: ```cpp for (auto it = vec.begin(); it != vec.end(); ++it) { // 处理*it } ``` - 使用C++11的范围for循环遍历: ```cpp for (const auto& element : vec) { // 处理element } ``` 这些只是vector容器的一些基本用法,还有许多其他方法可以用于插入、删除、修改和查找元素。你可以根据具体需求选择适合的方法来操作vector容器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值