C++ 第三天 Vector、函数
1.Vector
vector是一个动态增长的数组,它会随着我们添加的内容,会逐步的增加空间。实际上它并不是在原来的地方追加空间,而是开辟新的空间,然后把原来的数据都拷贝到新的空间里面去,接着让容器指向这块新的空间。
Vector其实很大程度上和数组一样,只是数组是固定长度,而vector是不定长度(动态增长)。vector更类似于Python中的列表可以进行增删改查,但Python的列表中可以 存储多种类型的数据,vector只能装单一类型的数据。
vector 在C++STL(标准模板库)中的一个容器,可以看成是对容器的一种扩展。在运行时可以改变长度 , 与数组具有相似的语法 , 相比数组更高效 , 提供越界检查。
vector声明和初始化
使用vector除了要导入#include <vector>
之外,由于它声明于std命名空间里面,所以要配合std命名空间使用
#include <vecotr>
using namespace std; int main(){ vector <char> vowels; // 声明 vector<int>里面代表了 这个容器装的元素是int类型
vector <int> test_score; vector <char> vowels(); //声明一个初始大小为5的char类型vector
vector <int> test_score();
//数组定义
int test_score []{,,,} //vector定义
vector <char> vowels {'a' , 'e' , 'i' , 'o' ,'u'}; // 声明及初始化
vector <int> test_score{ ,,,,};
vector <double> temperatures{,20.7};
return ;
}
访问vector
通过[] 和 at()取vector的元素
- 数组的语法
#include <iostream>
#include <vector>
using namespace std; int main(){
vector<int> test_score {,,}; cout << "第一个成绩是: " <<test_score[] << endl;
cout << "第二个成绩是: " <<test_score[] << endl;
cout << "第三个成绩是: " <<test_score[] << endl; cout << "第三个成绩是: " <<test_score[] << endl; //不会检查越界
return ;
}
- vector语法
#include <iostream>
#include <vector>
using namespace std; int main(){ vector<int> test_score {,,}; cout << "第一个成绩是: " <<test_score.at() << endl;
cout << "第二个成绩是: " <<test_score.at() << endl;
cout << "第三个成绩是: " <<test_score.at() << endl; cout << "第三个成绩是: " <<test_score.at() << endl; //抛出越界异常
return ;
}
操作vector
- 修改vector元素
#include <vector>
using namespace std; int main(){ vector<int> test_score {,,};
test_score.at() = ; return ;
}
- 往vector追加元素
#include <vector>
using namespace std; int main(){
vector<int> test_score {,,}; test_score.push_back(); // 100 , 90 , 85 , 80
test_score.push_back(); // 100 , 90 , 85 , 80 , 95 return ;
}
- 越界检查
只要当我们使用了vector的语法at()去获取超出索引的元素时,就会抛出异常。而使用数组的语法[]去获取元素,则不会进行越界检查
- 遍历vector
#include <iostream>
#include <vector>
using namespace std; int main(){ //使用下标遍历
vector<int> scores{ , , , ,};
for (int i = ; i < scores.size(); ++i) {
cout << scores[i] << endl;
} //基于范围for遍历
vector<int> scores{ , , , ,};
for(int score : scores){
cout << score << endl;
}
return ;
}
二维vector
二维vector和二维数组实际上差不太多,二维数组是数组里面装的是数组,二维vector指的是vector里面装的还是vector。
#include <iostream>
#include <vecotr>
using namespace std; int main(){ //声明并初始化vector
vector<vector<int>> scores {
{,,,},
{,,,},
{,,,}
}; for (int i = ; i < scores.size(); ++i) { // 获取二维vector里面的一维vector
for (int j = ; j < scores[i].size(); ++j) { // 获取一维vector里面的元素
cout << scores[i][j] <<"\t" ;
}
cout << endl;
}
return ;
}
2.函数
函数介绍
在大多数地方,c++ 和 python的函数是一样的,都是用来包裹定义好的语句,避免重复拷贝粘贴,提高代码的复用性。不过还是有些许不一样的地方。
python的函数是以回车换行结尾,c++的函数是以 大括号结尾
python的函数通常使用缩进方式来表示函数体, ,c++使用大括号区域来表示
python是动态类型语言,而c++是静态类型语言,所以有时候需要像声明变量一样,声明函数。
Python函数
# 定义函数
def add(a, b):
return a + b # 调用函数并接收它的返回值
sum = add(1,2)
# 打印结果
print(sum)
C++ 函数
#include<iostream> using namespace std; // 声明并初始化函数 函数名前面的int代表这个函数的返回值为int类型
// 参数里面的int 指定这个参数传入的必须是int类型
int add(int a, int b){
return a + b ;
} int main(){
// 调用add函数并打印结果
cout << add(,) << endl;
return ;
}
定义函数
函数返回的类型 函数名(函数参数的类型 函数参数){
函数体
}
函数分为四种方式
- 无参数无返回值
- 无参数有返回值
- 有参数无返回值
- 有参数有返回值
1.无参数无返回值
无返回值的函数必须用void声明
#include <iostream>
using namespace std; void say_hello(){
count << "hello" << endl;
} int main(){ say_hello();
return ;
}
2.无参数有返回值
#include<iostream> using namespace std; string say_hello(){
return "hello";
} int main(){
cout << say_hello() << endl;
return ;
}
3.有参数无返回值
#include<iostream> using namespace std; void say_hello(string name){
count << "你好 "<< name << endl;
} int main(){
say_hello("张三");
return ;
}
4.有参数有返回值
#include<iostream> using namespace std; string say_hello(string name){
return "你好 "+ name;
} int main(){
cout << say_hello("张三") << endl;
return ;
}
函数原型
一般来说,c++的函数一般包含声明和定义两个部分。因为c++是静态类型语言,程序属于自上而下编译,所以在使用函数前,必须先表示函数的存在,告诉编译器函数所需要的参数以及函数的返回值是什么。把函数分成声明和定义两部分,函数的原型定义在调用的前面,具体实现可以放在后面。
#include <iostream>
using namespace std; //函数声明 ,也叫函数原型 并不知道这个函数具体是如何实现的。只是有一些基本架子而已。
int add (int a , int b); int main(){
cout << add( ,)<< endl;
return ;
} //函数定义 ,函数的真正实现。
int add(int a , int b){
return a + b ;
}
函数重载
在许多语言中,经常会见到两个或者两个以上的函数名称是一样的,当然他们的 参数个数 或者 参数类型 或者是 参数的顺序 是不一样的。这种现象有一个学名叫做 重载 overload, 由于python属于动态类型语言,不区分数据类型,参数可以是任意类型,所以它没有重载。
函数重载的条件:
- 函数名称一样
- 函数的参数个数不一样或者函数参数类型不一样或者是函数的参数顺序不一样
下面的示例代码即是对加法运行进行了重载,以便能够针对不同的数据类型,不同的参数个数做出匹配
int add(int a , int b){
return a + b ;
} int add(int a , int b , int c){
return a + b + c;
} int add(double a , double b){
return a + b ;
} int main(){
// 会自动根据参数的不同,进行匹配函数
add(, ); //
add(, , ); //
add(2.5 , 2.5); // return ;
}
函数参数
python的函数,在传递参数的时候,有可变对象和不可变对象的现象,那么在C++里面也有类似的说法。只不过是另一种说辞罢了。
python中传递不可变对象,在C++中,对应的是值的拷贝,也就是传递的只是数据的一份拷贝而已。在函数内部修改数据,并不会改变外部数据
python中传递可变对象,在c++中,对应的是引用传递,也就是传递的是对象的引用,而不是拷贝。在函数内部修改数据,会导致外部数据也发生改变。
值的传递
C++默认情况下,处理函数参数传递时,多数使用的是值的拷贝,少数部分除外。
#include<iostream>
using namespace std; void scale_number(int num); int main(){
int number{};
scale_number(number); //打印number 1000
cout << number <endl;
return ;
} void scale_number(int num){
if(num > )
num = ;
}
传递数组
函数的参数除了能传递普通简单的数据之外,数组也是可以传递的。但是数组稍微有点特殊,这里多做讲解。
前面提过,形参实际上就是实参的一份拷贝,就是一个局部变量。
数组的数据太大,如果都进行拷贝,那么比较麻烦,也造成了浪费
所以实际上传递数组的时候,并不会进行整个数组的拷贝,而只是传递数组的第一个元素内存地址 (指针 ) 进来。
数组的数据还是在内存中,只是把第一个元素(也就是数组的起始)内存地址传进来而已。
这就造成了函数的内部根本无法知道这个数组的元素有多少个。
#include<iostream>
using namespace std; using namespace std;
//传递数组长度
void print_array(int number[] , ); int main(){
//声明数组
int array []{,,,,}; //打印数组
print_array(array , ); return ; } //传递数组,打印数组
void print_array(int array[] , int size){
for (int i {} ; i < size ; i++){
count << array[i] << endl;
}
}
传递引用
目前为止,我们所有函数的参数传递,都是对数据进行了一份拷贝(数组除外)。那么在函数的内部是不能修改值的,因为这仅仅是一份值得拷贝而已(函数外部的值并不会受到影响)。如果真的想在函数内部修改值,那么除了数组之外,还有一种方式就是传递引用
。
引用实际上只是原有数据的一种别名称呼而已,使用 &
定义
#include<iostream>
using namespace std; void scale_number(int &num); int main(){
int number{};
scale_number(number); //打印number100
count << number <endl;
return ;
} void scale_number(int &num){
if(num > )
num = ;
}
内联函数
函数可以使我们复用代码,但是一个函数的执行,需要开辟空间、形参和实参进行值得拷贝,还要指明函数返回、以及最后回收释放资源的动作,这个过程是要消耗时间的。
作为特别注重程序执行效率,适合编写底层系统软件的高级程序设计语言,如果函数中只有简单的几行代码,那么可以使用inline
关键字来解决了函数调用开销的问题。
#include<iostream> inline int calc_Max (int a, int b)
{
if(a >b)
return a;
return b;
} int main(){ int max = calc_Max(, );
std::cout << "max = " << max << std::endl; return ;
}
增加了 inline 关键字的函数称为“内联函数”。内联函数和普通函数的区别在于:当编译器处理调用内联函数的语句时,不会将该语句编译成函数调用的指令,而是直接将整个函数体的代码插人调用语句处,就像整个函数体在调用处被重写了一遍一样。
内联函数不会有函数栈压栈的动作。
有了内联函数,就能像调用一个函数那样方便地重复使用一段代码,而不需要付出执行函数调用的额外开销。很显然,使用内联函数会使最终可执行程序的体积增加。以时间换取空间,或增加空间消耗来节省时间,这是计算机学科中常用的方法。
那能不能把所有的函数都变成内联函数呢?
可以,但不建议这么做,因为函数中有太多的数据,如果都变成内联函数,这将会使这些变量的生命周期变得非常的长,导致最终可执行程序的体积增加。
范围规则
函数中局部变量
只能在这个函数中使用
#include<iostream>
using namespace std; int num{};
void local_example(int x){ int num{};
cout << "num =" << num << endl; num = x ;
cout << "num =" << num << endl; }
静态本地变量
在函数定义的变量前面加static关键字
只会初始化一次
重复调用函数也只会初始化一次。
#include<iostream>
using namespace std; void static_local_example(){ static int num{};
cout << "num ="<< num << endl;
num+=;
cout << "num ="<< num << endl;
} int main(){
static_local_example();
static_local_example();
return ;
}
全局变量
全局变量通常声明在所有函数和类的外部 ,若存在局部变量和全局变量同名情况下,可以使用 域操作符 :: 来访问全局变量, 如果没有使用 域操作符:: 则会采用就近原则进行寻找。
#include<iostream>
using namespace std; int age = ;
int main(){ int age = ;
cout << ::age << endl;
return ;
}
-----------------------------------------------------------------------------------------分割线--------------------------------------------------------------------------------------------------------------------------------
C++ 第三天 Vector、函数的更多相关文章
- 受限玻尔兹曼机(RBM)学习笔记(三)能量函数和概率分布
去年 6 月份写的博文<Yusuke Sugomori 的 C 语言 Deep Learning 程序解读>是囫囵吞枣地读完一个关于 DBN 算法的开源代码后的笔记,当时对其中涉及的算 ...
- Oracle笔记(三)单行函数
-函数 函数像一个黑盒子一样(看不到里边的构造),有参数返回值,可以为我们完成一定的功能. -单行 这种函数会对结果中的每一行计算一次,每行返回一个结果,单行概念区别于分组函数. 单行函数主要分为以下 ...
- 驱动调试(三)oops确定函数PC
目录 驱动调试(三)oops确定函数PC 什么是oops 流程简述 代码仓库 模块例子分析 找到PC值 判断是否属于模块 查看符号表 找到模块 反汇编模块 内核例子分析 找到PC值 判断是否属于模块 ...
- python自动化开发-[第三天]-编码,函数,文件操作
今日概要 - 编码详解 - 文件操作 - 初识函数 一.字符编码 1.代码执行过程 代码-->解释器翻译-->机器码-->执行 2.ASCII ASCII:一个Bytes代表一个字符 ...
- JS三个编码函数和net编码System.Web.HttpUtility.UrlEncode比较
JS三个编码函数和net编码比较 总结 1.escape.encodeUri.encodeUriComponent均不会对数字.字母进行编码.2.escape:对某些字符(如中文)进行unicode编 ...
- [教程]Delphi 中三种回调函数形式解析
Delphi 支持三种形式的回调函数 全局函数这种方式几乎是所有的语言都支持的,类的静态函数也可以归为此类,它保存的只是一个函数的代码起始地址指针( Pointer ).在 Delphi 中声明一般为 ...
- javascript进阶课程--第三章--匿名函数和闭包
javascript进阶课程--第三章--匿名函数和闭包 一.总结 二.学习要点 掌握匿名函数和闭包的应用 三.匿名函数和闭包 匿名函数 没有函数名字的函数 单独的匿名函数是无法运行和调用的 可以把匿 ...
- TypeScript入门三:TypeScript函数类型
TypeScript函数类型 TypeScript函数的参数 TypeScript函数的this与箭头函数 TypeScript函数重载 一.TypeScript函数类型 在上一篇博客中已经对声明Ty ...
- day 53-1 Django基础三之视图函数
Django基础三之视图函数 本节目录 一 Django的视图函数view 二 CBV和FBV 三 使用Mixin 四 给视图加装饰器 五 Request对象 六 Response对象 一 Dja ...
- day 67 Django基础三之视图函数
Django基础三之视图函数 本节目录 一 Django的视图函数view 二 CBV和FBV 三 使用Mixin 四 给视图加装饰器 五 Request对象 六 Response对象 一 Dja ...
随机推荐
- ORA-04063: package body "DBSNMP.BSLN" has errors
ORA-04063: package body "DBSNMP.BSLN" has errors 问题描述: 警告日志出现报错: Sun Jun 28 00:00:01 2020 ...
- SpringCloud Alibaba (四):Dubbo RPC框架
Dubbo简介 Apache Dubbo |ˈdʌbəʊ| 是一款高性能.轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现.致 ...
- elasticsearch 单节点搭建与爬坑记录
elasticsearch 单节点搭建与爬坑记录 prepare 虚拟机或者云服务器(这里用的是阿里云ECS) linux---centos7 安装完毕的jdk 相应的安装包(在https:/ ...
- 火车运输(最大生成树+lca) 洛谷P1967
货车运输 题目描述 \(A\) 国有 \(n\) 座城市,编号从 \(1\) 到 \(n\) ,城市之间有 \(m\) 条双向道路.每一条道路对车辆都有重量限制,简称限重. 现在有 \(q\) 辆货车 ...
- mac篇---iterm2的基本常用命令
标签 新建标签:command + t 关闭标签:command + w 切换标签:command + 数字 command + 左右方向键 切换全屏:command + enter 查找:comma ...
- Jmeter系列(41)- Jmeter + Ant +Jenkins 持续集成
如果你想从头学习Jmeter,可以看看这个系列的文章哦 https://www.cnblogs.com/poloyy/category/1746599.html Window 环境准备 安装 ant: ...
- 深克隆(deepclone)
1.简单版: <script type="text/javascript"> const newObj = JSON.parse(JSON.stringify(oldO ...
- 使用命名管道承载gRPC
最近GRPC很火,感觉整RPC不用GRPC都快跟不上时髦了. gRPC设计 刚好需要使用一个的RPC应用系统,自然而然就盯上了它,但是它真能够解决所有问题吗?不见得,先看看他的优点: gRPC是一种与 ...
- flask 源码专题(四):wtforms Form实例化流程以及csrf验证
class LoginForm(Form): #首先执行后得到的结果是UnboundField()对象 name=simple.StringField( label='用户名', validators ...
- Spring Boot 2.3.0正式发布:优雅停机、配置文件位置通配符新特性一览
当大潮退去,才知道谁在裸泳..关注公众号[BAT的乌托邦]开启专栏式学习,拒绝浅尝辄止.本文 https://www.yourbatman.cn 已收录,里面一并有Spring技术栈.MyBatis. ...