zoukankan      html  css  js  c++  java
  • 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);  //声明一个初始大小为5的char类型vector
        vector <int> test_score(10);
         //数组定义
        int test_score []{100,99,18,81}
    
        //vector定义
        vector <char> vowels {'a' , 'e' , 'i' , 'o' ,'u'};  // 声明及初始化
        vector <int> test_score{ 100 ,98,95,90,80};
        vector <double> temperatures{26,20.7};
           return 0;
    }

    访问vector

    通过[] 和 at()取vector的元素

    • 数组的语法
    #include <iostream>
    #include <vector>
    using namespace std;
    
    int main(){
        vector<int> test_score {100,90,85};
    
        cout << "第一个成绩是: " <<test_score[0] << endl;
        cout << "第二个成绩是: " <<test_score[1] << endl;
        cout << "第三个成绩是: " <<test_score[2] << endl;
    
        cout << "第三个成绩是: " <<test_score[3] << endl;  //不会检查越界
         return 0 ;   
    }
    • vector语法
    #include <iostream>
    #include <vector>
    using namespace std;
    
    int main(){
        
        vector<int> test_score {100,90,85};
    
        cout << "第一个成绩是: " <<test_score.at(0) << endl;
        cout << "第二个成绩是: " <<test_score.at(1) << endl;
        cout << "第三个成绩是: " <<test_score.at(2) << endl;
        
        cout << "第三个成绩是: " <<test_score.at(3) << endl; //抛出越界异常
        return 0 ;
    }

    操作vector

    • 修改vector元素
    #include <vector>
    using namespace std;
    
    int main(){
    
        vector<int> test_score {100,90,85};
        test_score.at(0) = 73;
        
        return 0 ;
    }
    • 往vector追加元素
    #include <vector>
    using namespace std;
    
    int main(){
        vector<int> test_score {100,90,85};
    
        test_score.push_back(80); // 100 , 90 , 85 , 80
        test_score.push_back(95); // 100 , 90 , 85 , 80 , 95
    
        return 0 ;
    }
    • 越界检查

    只要当我们使用了vector的语法at()去获取超出索引的元素时,就会抛出异常。而使用数组的语法[]去获取元素,则不会进行越界检查

     

    • 遍历vector
    #include <iostream>
    #include <vector>
    using namespace std;
    
    int main(){
        
        //使用下标遍历
        vector<int> scores{ 100 ,95 ,88 ,80 ,75};
        for (int i = 0; i < scores.size(); ++i) {
            cout << scores[i] << endl;
        }
    
        //基于范围for遍历
        vector<int> scores{ 100 ,95 ,88 ,80 ,75};
        for(int score : scores){
            cout << score << endl;
        }
        return 0 ;
    }

    二维vector

    二维vector和二维数组实际上差不太多,二维数组是数组里面装的是数组,二维vector指的是vector里面装的还是vector。

    #include <iostream>
    #include <vecotr>
    using namespace std;
    
    int main(){
    
        //声明并初始化vector
        vector<vector<int>> scores {
                {95,77,80,85},
                {58,89,93,100},
                {69,73,81,97}
        };
    
        for (int i = 0; i < scores.size(); ++i) {  // 获取二维vector里面的一维vector
            for (int j = 0; j < scores[i].size(); ++j) {  // 获取一维vector里面的元素
               cout << scores[i][j] <<"	" ;
            }
            cout << endl;
        }
        return 0 ;
    }

    2.函数

    函数介绍

    在大多数地方,c++ 和 python的函数是一样的,都是用来包裹定义好的语句,避免重复拷贝粘贴,提高代码的复用性。不过还是有些许不一样的地方。

    1. python的函数是以回车换行结尾,c++的函数是以 大括号结尾

    2. python的函数通常使用缩进方式来表示函数体, ,c++使用大括号区域来表示

    3. 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(1,2) << endl;
        return 0 ;
    }

    定义函数

    函数返回的类型 函数名(函数参数的类型 函数参数){

    函数体

    }

    函数分为四种方式

    1. 无参数无返回值
    2. 无参数有返回值
    3. 有参数无返回值
    4. 有参数有返回值

    1.无参数无返回值

    无返回值的函数必须用void声明

    #include <iostream>
    using namespace std;
    
    void say_hello(){ 
        count << "hello" << endl;
    }
    
    int main(){
        
        say_hello();
        return 0 ;
    }

    2.无参数有返回值

    #include<iostream>
    
    using namespace std;
    
    string say_hello(){ 
       return "hello";
    }
    
    int main(){
        cout << say_hello() << endl;
        return 0 ;
    }

    3.有参数无返回值

    #include<iostream>
    
    using namespace std;
    
    void say_hello(string name){ 
        count << "你好 "<< name << endl;
    }
    
    int main(){
        say_hello("张三");
        return 0 ;
    }

    4.有参数有返回值

    #include<iostream>
    
    using namespace std;
    
    string say_hello(string name){ 
       return "你好 "+ name;
    }
    
    int main(){
        cout << say_hello("张三") << endl;
        return 0 ;
    }

    函数原型

    一般来说,c++的函数一般包含声明和定义两个部分。因为c++是静态类型语言,程序属于自上而下编译,所以在使用函数前,必须先表示函数的存在,告诉编译器函数所需要的参数以及函数的返回值是什么。把函数分成声明和定义两部分,函数的原型定义在调用的前面,具体实现可以放在后面。

    #include <iostream>
    using namespace std;
    
    //函数声明 ,也叫函数原型 并不知道这个函数具体是如何实现的。只是有一些基本架子而已。
    int add (int a , int b);
    
    int main(){
        cout << add(1 ,2)<< endl;
        return 0 ;
    }
    
    //函数定义 ,函数的真正实现。
    int add(int a , int b){
        return a + b ; 
    }

    函数重载

    在许多语言中,经常会见到两个或者两个以上的函数名称是一样的,当然他们的 参数个数 或者 参数类型 或者是 参数的顺序 是不一样的。这种现象有一个学名叫做 重载 overload, 由于python属于动态类型语言,不区分数据类型,参数可以是任意类型,所以它没有重载。

    函数重载的条件:

    1. 函数名称一样
    2. 函数的参数个数不一样或者函数参数类型不一样或者是函数的参数顺序不一样

    下面的示例代码即是对加法运行进行了重载,以便能够针对不同的数据类型,不同的参数个数做出匹配

    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(3, 3); // 6
        add(3, 3, 3); // 9
        add(2.5 , 2.5);  // 5
            
        return 0 ;
    }  

    函数参数

    python的函数,在传递参数的时候,有可变对象和不可变对象的现象,那么在C++里面也有类似的说法。只不过是另一种说辞罢了。

    python中传递不可变对象,在C++中,对应的是值的拷贝,也就是传递的只是数据的一份拷贝而已。在函数内部修改数据,并不会改变外部数据

    python中传递可变对象,在c++中,对应的是引用传递,也就是传递的是对象的引用,而不是拷贝。在函数内部修改数据,会导致外部数据也发生改变。

    值的传递

    C++默认情况下,处理函数参数传递时,多数使用的是值的拷贝,少数部分除外。

    #include<iostream>
    using namespace std;
    
    void  scale_number(int num);
    
    int main(){
        int number{1000};
        scale_number(number);
        
        //打印number 1000
        cout << number <endl;
        return 0 ;
    }
    
    void scale_number(int num){
        if(num > 100)
            num = 100;
    }

    传递数组

    函数的参数除了能传递普通简单的数据之外,数组也是可以传递的。但是数组稍微有点特殊,这里多做讲解。

    1. 前面提过,形参实际上就是实参的一份拷贝,就是一个局部变量。

    2. 数组的数据太大,如果都进行拷贝,那么比较麻烦,也造成了浪费

    3. 所以实际上传递数组的时候,并不会进行整个数组的拷贝,而只是传递数组的第一个元素内存地址 (指针 ) 进来。

    4. 数组的数据还是在内存中,只是把第一个元素(也就是数组的起始)内存地址传进来而已。

    5. 这就造成了函数的内部根本无法知道这个数组的元素有多少个。

    #include<iostream>
    using namespace std;
    
    using namespace std;
    //传递数组长度
    void print_array(int number[] , 5);
    
    int main(){
        //声明数组
        int array []{1,2,3,4,5};
        
        //打印数组
        print_array(array , 5);
        
        return 0 ;
        
    }
    
    //传递数组,打印数组
    void print_array(int array[] , int size){
        for (int i {0} ; i < size ; i++){
            count << array[i] << endl;
        }
    }

    传递引用

    目前为止,我们所有函数的参数传递,都是对数据进行了一份拷贝(数组除外)。那么在函数的内部是不能修改值的,因为这仅仅是一份值得拷贝而已(函数外部的值并不会受到影响)。如果真的想在函数内部修改值,那么除了数组之外,还有一种方式就是传递引用

    引用实际上只是原有数据的一种别名称呼而已,使用 & 定义

    #include<iostream>
    using namespace std;
    
    
    void scale_number(int &num);
    
    int main(){
        int number{1000};
        scale_number(number);
        
        //打印number100
        count << number <endl;
        return 0 ;
    }
    
    void scale_number(int &num){
        if(num > 100)
            num = 100;
    }

    内联函数

    函数可以使我们复用代码,但是一个函数的执行,需要开辟空间、形参和实参进行值得拷贝,还要指明函数返回、以及最后回收释放资源的动作,这个过程是要消耗时间的。

    作为特别注重程序执行效率,适合编写底层系统软件的高级程序设计语言,如果函数中只有简单的几行代码,那么可以使用inline 关键字来解决了函数调用开销的问题。

    #include<iostream>
    
    inline int calc_Max (int a, int b)
    {
        if(a >b)
            return a;
        return b;
    }
    
    int main(){
        
        int max = calc_Max(3, 8);
        std::cout << "max = " << max << std::endl;
        
        return 0 ;
    }

    增加了 inline 关键字的函数称为“内联函数”。内联函数和普通函数的区别在于:当编译器处理调用内联函数的语句时,不会将该语句编译成函数调用的指令,而是直接将整个函数体的代码插人调用语句处,就像整个函数体在调用处被重写了一遍一样。

    内联函数不会有函数栈压栈的动作。

    有了内联函数,就能像调用一个函数那样方便地重复使用一段代码,而不需要付出执行函数调用的额外开销。很显然,使用内联函数会使最终可执行程序的体积增加。以时间换取空间,或增加空间消耗来节省时间,这是计算机学科中常用的方法。

    那能不能把所有的函数都变成内联函数呢?

    可以,但不建议这么做,因为函数中有太多的数据,如果都变成内联函数,这将会使这些变量的生命周期变得非常的长,导致最终可执行程序的体积增加。

    范围规则

    函数中局部变量

    只能在这个函数中使用

    #include<iostream>
    using namespace std;
    
    int num{300};
    void local_example(int x){
        
        
        int num{1000};
        cout << "num =" << num << endl;
        
        num = x ;
        cout << "num =" << num << endl;
     
        
    }

    静态本地变量

    在函数定义的变量前面加static关键字

    1. 只会初始化一次

    2. 重复调用函数也只会初始化一次。

    #include<iostream>
    using namespace std;
    
    void static_local_example(){
        
        static int num{100};
        cout << "num ="<< num << endl;
        num+=100;
        cout << "num ="<< num << endl;
    }
    
    int main(){
        static_local_example();
        static_local_example();
        return 0 ;
    }

    全局变量

    全局变量通常声明在所有函数和类的外部 ,若存在局部变量和全局变量同名情况下,可以使用 域操作符 :: 来访问全局变量, 如果没有使用 域操作符::  则会采用就近原则进行寻找。  

    #include<iostream>
    using namespace std;
    
    int age = 99;
    int main(){
        
        int age =18 ;
        cout << ::age << endl;
        return 0 ;
    }

     -----------------------------------------------------------------------------------------分割线--------------------------------------------------------------------------------------------------------------------------------

      

  • 相关阅读:
    在线音视频(MP3/MP4)测试文件
    jQuery 找包含内容的节点,但不搜索子节点
    bash 脚本小练习:查看 git 提交对应的提交数
    桌面应用开发的日子(二):实现文件资源管理列表树加载
    桌面应用开发的日子(一):初识WPF
    Winform同一数据源多个控件保持同步
    Windows Form中DataGridView的基本玩法
    jsp第七周作业
    jsp第五周作业
    jsp第六周作业
  • 原文地址:https://www.cnblogs.com/yanzhongyixu/p/12751360.html
Copyright © 2011-2022 走看看