C++函数

函数

参数传递

  • C++有两种参数传递方式:值传递,引用传递,值传递是根据传入的参数重新初始化一个对象,然后对这个对象进行修改,这个不会影响原来的值;引用传递是传入变量的引用,在函数中修改该引用,就可以直接对原始变量进行修改(如果没有被const关键字修饰的话)
  • 如果需要修改变量,而不使用返回值的形式,可以使用指针传参(修改指针所指的对象)或者是引用传参

返回值

  • 对于返回值为void的函数,函数可以以return;的形式返回,如果不写这句话,则编译器会执行到函数末尾再返回
  • 编译器会保证一个函数最终只通过一个路径进行返回(即如果写了多个返回的路径,只会执行其中一条)

关于函数返回值的一些注意事项

  • 不要返回局部对象的引用或者指针
    函数完成后,其所占用的存储空间也随之被释放掉,因此函数终止时,意味着返回的引用或者指针指向一个不再有效的内存区域。即使这块无效的内存区域中的内容暂时还是我们需要的值,但是这种操作十分危险。
  • 下面的代码十分危险

    string &refAdd(string a, string b)
    {
        // 函数返回时,c所对应的内存空间就会被释放
        string c = a + b;
        return c;
    }
    
    string *refAppend(string s)
    {
        string ret = s.append("2333");
        return &ret;
    }
    
    void test()
    {
        string s = "test";
        string *ret = refAppend( "test" );
        // 下面2句话均会报出异常,但是运行没有问题
        // cout << *ret << endl;
        // cout << refAdd( s, s ) << endl;
    }
    
  • 函数不可以返回数组(数组不可以被拷贝),但是函数可以返回数组的指针或者引用,即这个指针或者引用指向这个引用,返回数组引用时,数组一定要在函数外部进行定义,否则函数结束之后该存储空间就会被释放

  • 返回数组指针:https://blog.csdn.net/jxhaha/article/details/70834041
  • 返回数组引用:https://segmentfault.com/q/1010000000580417

    int (*arr())[10]
    {
        int(*ret)[10] = (int(*)[10])new int[10];
        for (int i = 0; i < 10; i++)
            (*ret)[i] = i;
        return ret;
    }
    
    string odd[3] = { "1", "3", "5" };
    string even[3] = { "2", "4", "6" };
    decltype(odd) &sarr(int i)
    {
        return i % 2 == 0 ? even : odd;
    }
    
    // 类型别名
    typedef int arrT[10];
    arrT* arr2()
    {
        return arr();
    }
    
    void test()
    {
        int(*a)[10] = arr( );
        for (int i = 0; i < 10; i++)
            cout << (*a)[i] << " ";
        cout << endl;
    
        arrT* a2 = arr2();
        for (int i = 0; i < 10; i++)
            cout << (*a2)[i] << " ";
        cout << endl;
    
        auto ret = sarr(0);
        for (int i = 0; i < 3; i++)
            cout <<ret[i] << " ";
        cout << endl;
    }
    

关于调试过程中的一些tips

  • 在debug状态下,可以通过assert函数,判断确保程序的运行状态是正常的。assert函数在宏定义NDEBUG之后,就不会起作用
  • 除了NDEBUG之外,预处理器还定义了__FILE__,__LINE__,__TIME__,__DATE__,方便调试

  • 代码

    void test()
    {
        // assert(1 > 2); // 在debug模式下,这句话会使得程序报错,但是在release模式下,这句话不会起作用
        cout << __FILE__ << endl; //当前文件名
        cout << __LINE__ << endl; // 当前行数
        cout << __TIME__ << endl; // 当前时间
        cout << __DATE__ << endl; // 当前日期
    }
    

函数指针(数组)的使用

  • 函数指针即一个指针指向一个函数,部分参考链接:https://blog.csdn.net/u012526003/article/details/79747302

  • 代码

    void test()
    {
        vector<int(*)(int, int)> nums(3); // *与括号不可以省略
        nums[0] = myAdd;
        nums[1] = myMminus;
        nums[2] = &myMminus; //与上面的含义相同
        int a = 2, b = 3;
        cout << (nums[0])(a, b) << endl;
        cout << (nums[1])(a, b) << endl;
        cout << (nums[2])(a, b) << endl;
    
        // 函数指针数组与函数指针的定义
        int (*arr[5])(int, int);
        int(*p)(int, int);
    }
    

猜你喜欢

转载自blog.csdn.net/u012526003/article/details/80172053