欢迎关注我的大众号 [极智视界],获取我的更多经历共享
大家好,我是极智视界,本文介绍一下 从数组求和来看C++的开展。
邀您参加我的常识星球「极智视界」,星球内有超多好玩的项目实战源码下载,链接:t.zsxq.com/0aiNxERDq
从一个事例来看 C++ 的开展。
定义一个数组 {4, 2, 6, 7},求数组里所有数的和,并将之打印
如果是 python 的话,完成十分简练 (但你要清楚的是,代码简练并不代表程序效率高):
- python
arr = [4, 2, 6, 7]
print(sum(arr))
那用 C++ 该如何完成呢。大家知道 C++ 是由 C言语开展而来,所以先来看一下 C言语的完成。
- 古代:C言语
#include <stdlib.h>
#include <stdio.h>
int main(){
size_t nums = 4;
int *arr = (int *)malloc(nums * sizeof(int));
arr[0] = 4;
arr[1] = 2;
arr[2] = 6;
arr[3] = 7;
int sum = 0;
for(size_t i = 0; i < nums; i++){
sum += arr[i];
}
printf("%d\n", sum);
free(v);
return 0;
}
C言语看起来显着要比 python 费事不少吧,多了 malloc内存管理、指针逐个赋值、循环加和的进程。
再来看 C++98。
- 近代:C++98 引进了 STL 容器库
#include <iostream>
#include <vector>
int main(){
std::vector<int> arr(4);
arr[0] = 4;
arr[1] = 2;
arr[2] = 6;
arr[3] = 7;
int sum = 0;
for(size_t i = 0; i < arr.size(); i++){
sum += arr[i];
}
std::cout << sum << std::endl;
return 0;
}
C++98 引进了 vector 这个模板类,自带内存管理,所以相比C言语不需求自己进行手动管理内存了。输出函数这里采用了运算符重载的特性,不必像C言语 printf 那样需求显式指定是要用 %d 仍是 %f 了,便利挺多。不过在数组赋值那一块仍是和C言语相同的。
接着来看 C++11。
- 近现代:C++11 引进了 {} 初始化表达式
#include <iostream>
#include <vector>
int main(){
std::vector<int> arr = {4, 2, 6, 7};
int sum = 0;
for(int i = 0; i < arr.size(); i++){
sum += arr[i];
}
std::cout << sum << std::endl;
return 0;
}
这样,经过花括号就把 C++98 中对数组的初始化给优化地愈加简练了。
别的,C++11 还引进了一个很便利的、根据规模的 for循环,来看看经过根据规模的 for循环怎样来进一步做简化。
- 近现代:C++11 引进了 range-based for-loop
#include <iostream>
#include <vector>
int main(){
std::vector<int> arr = {4, 2, 6, 7};
int sum = 0;
for(int a: arr){
sum += a;
}
std::cout << sum << std::endl;
return 0;
}
很显着,for 循环变得愈加简练了。
接着经过 C++11 的 for_each 还能够继续改造。
- 近现代:C++11 引进了 for_each 算法模板
#include <iostream>
#include <vector>
#include <algorithm>
int sum = 0;
void func(int a){
sum += a;
}
int main(){
std::vector<int> arr = {4, 2, 6, 7};
std::for_each(arr.begin(), arr.end(), func);
std::cout << sum << std::endl;
return 0;
}
for_each 是一个算法模版,能够套用到任何支持迭代器的容器。而 for_each 有个不太便利的地方,就是它的 func 是一个外部函数,需求去声明一个大局的 sum 就比较费事。对此,C++11 又引进了 lambda 表达式,这样就能够把 func 写在局部了,这样 sum 就能够为一个局部变量。
- 近现代:C++11 引进了 lambda 表达式
#include <iostream>
#include <vector>
#include <algorithm>
int main(){
std::vector<int> arr = {4, 2, 6, 7};
int sum = 0;
std::for_each(arr.begin(), arr.end(), [&] (int a){
sum += a;
});
std::cout << sum << std::endl;
return 0;
}
接着来到了 C++14,在 C++14 中答应 lambda 运用 auto 主动揣度类型了。
- 现代:C++14 的 lambda 答应用 auto 主动揣度类型
#include <iostream>
#include <vector>
#include <algorithm>
int main(){
std::vector<int> arr = {4, 2, 6, 7};
int sum = 0;
std::for_each(arr.begin(), arr.end(), [&] (auto a){
sum += a;
});
std::cout << sum << std::endl;
return 0;
}
运用了 auto 后,优点就在于 既能够用于 int 类型,也能够用于 float 类型等,要是哪天 arr 的数据类型改变了,auto 也不需求改就能够习惯,这样就愈加通用了。
继续,来到了 C++17,参加了编译期参数揣度,什么意思呢,来看。
- 今世:C++17 CTAD / compile-time argument deduction / 编译期参数揣度
#include <iostream>
#include <vector>
#include <algorithm>
int main(){
std::vector arr = {4, 2, 6, 7};
int sum = 0;
std::for_each(arr.begin(), arr.end(), [&] (auto a){
sum += a;
});
std::cout << sum << std::endl;
return 0;
}
看 arr 的声明,在 vector 后能够省掉 的类型定义了,由于右值都是整型,所以会主动揣度为整型。
别的,在 C++17 里边还引进了一些常用的数值算法,放在 这个头里边,比方这里能够用 reduce 归约来求和。
- 今世:C++17 引进了常用的数值算法
#include <iostream>
#include <vector>
#include <numeric>
int main(){
std::vector arr = {4, 2, 6, 7};
int sum = std::reduce(arr.begin(), arr.end());
std::cout << sum << std::endl;
return 0;
}
当然,reduce 不只能够用于加法,还能够用于乘法,如果我们是要求 arr 中每个数的乘积,运用 reduce 的话能够是这样:
#include <iostream>
#include <vector>
#include <numeric>
int main(){
std::vector arr = {4, 2, 6, 7};
int sum = std::reduce(arr.begin(), arr.end(), 1, std::plus{});
std::cout << sum << std::endl;
return 0;
}
愈加拓展一点,reduce 内的函数还能够自定义,而自定义函数能够用 lambda 表达式来完成,比方仍是要求 arr 中每个数的和,运用 reduce 内自定义函数,能够是这样:
#include <iostream>
#include <vector>
#include <numeric>
int main(){
std::vector arr = {4, 2, 6, 7};
int sum = std::reduce(arr.begin(), arr.end(), 0, [] (int x, int y){
return x + y;
});
std::cout << sum << std::endl;
return 0;
}
继续进化,在 C++20 中引进了区间 ranges,来看看 ranges 将带来什么样的完成改变。
- 未来:C++20 引进区间 ranges
#include <iostream>
#include <vector>
#include <numeric>
#include <ranges>
#include <cmath>
int main(){
std::vector arr = {4, 2, 6, 7, 0, -2, -5};
int sum = 0;
for(auto &&a: arr
| std::views::filter([] (auto &&x) {return x >= 0;})){
sum += a;
}
std::cout << sum << std::endl;
return 0;
}
经过 ranges 能够有一个挑选的功能在里边,甚至还能够经过 ranges 对挑选出来的元素再直接做一些操作再抛出来用,比方如果想要对以上数组 arr 中大于等于 0 的元素开个根号再求和,经过 ranges 能够这样写:
#include <iostream>
#include <vector>
#include <numeric>
#include <ranges>
#include <cmath>
int main(){
std::vector arr = {4, 2, 6, 7, 0, -2, -5};
int sum = 0;
for(auto &&a: arr
| std::views::filter([] (auto &&x) {return x >= 0;})
| std::views::transform([] (auto &&x) {return sqrtf(x);})){
sum += a;
}
std::cout << sum << std::endl;
return 0;
}
别的,不得不说 C++ 一直也在学习一些 python 的特性,在往 python 挨近,原本 C++ 中是经过 include 来包含头文件的,而在 C++ 20 中引进了模块 module 的概念。
- 未来:C++20 引进模块 module
import <iostream>;
import <vector>;
import <numeric>;
import <ranges>;
import <cmath>;
int main(){
std::vector arr = {4, 2, 6, 7, 0, -2, -5};
int sum = 0;
for(auto &&a: arr
| std::views::filter([] (auto &&x) {return x >= 0;})){
sum += a;
}
std::cout << sum << std::endl;
return 0;
}
看到这里,是不是会让你有一种错觉:我是在写 C++ 吗?[捂脸]
在 C++20 中,还对 auto 进行了再次的升级,答应函数参数为 auto 了。
- 未来:C++20 答应函数参数为主动揣度 auto
import <iostream>;
import <vector>;
import <numeric>;
import <ranges>;
import <cmath>;
int func(auto &&a){
int sum = 0;
for(auto &&a: arr
| std::views::filter([] (auto &&x) {return x >= 0;})){
sum += a;
}
return sum;
}
int main(){
std::vector arr = {4, 2, 6, 7, 0, -2, -5};
int sum = func(arr);
std::cout << sum << std::endl;
return 0;
}
这里,是不是感觉会有一点了解呢?func 是不是看起来是和模板函数 template 的作用比较像。
别的在 20 里边还引进了一些多线程的特性,比方 std::future、协程之类的。虽然 C++20 挺香的,但是还没有遍及落地,甚至连 CMake 对 C++20 modules 的支持也不够好,所以暂时仍是能够把 C++20 作为拓展来进行学习,项目中仍是用 C++17 及以下的较多。
好了,以上共享了 从数组求和来看 C++ 的开展,希望我的共享能对你的学习有一点协助。
【大众号传送】
《极智开发 | 从数组求和来看C++的开展》
畅享人工智能的科技魅力,让好玩的AI项目不难玩。邀请您参加我的常识星球, 星球内我精心整备了很多好玩的AI项目,皆以工程源码方式敞开运用,包括人脸、检测、切割、多模态、AIGC、主动驾驶、工业等。不敢说会对你学习有所协助,但一定十分好玩,并继续更新愈加有趣的项目。 t.zsxq.com/0aiNxERDq