C++基础8:函数1

本文详细介绍了C++中的函数定义、函数放置位置、代码组织结构、参数及传参方式(值传递、引用传递、指针传递)、返回语句的使用,以及内联函数在提升程序效率中的作用。通过示例代码,阐述了如何在实际编程中有效地使用函数,以实现模块化和提高代码可读性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、函数

1.函数定义

2.函数应该放在哪里

3.更加清晰的代码组织结构

4.函数的参数

5.传参方式

a)传递值

b)引用(c++)

6.返回语句

a)无具体返回值函数

b)有具体返回值函数(可返回基本数据类型或组合类型(类、结构体))

c)其他情况return

7.内联函数(重要:关乎程序运行效率) 


一、函数

1.函数定义

目的:为编程模块化设计

示例:找到矩阵里最大值

struct Matrix
{
    int rows;//行
    int cols;//列
    float * pData;//数据
};
//找到矩阵里最大值
Matrix matA;
float maxa = FLT_MIN;//float类型最小值
for(int r = 0; r < matA.rows; r++)
    for (int c = 0; c < matA.cols; c++)
    {
        float val = matA.pData[ r * matA.cols + c];//r行c列元素
        maxa = ( maxa > val ? maxa : val);
}

函数定义格式

//返回类型 函数名(参数列表)

{

函数体

}

float matrix_max(struct Matrix mat)
{
    float max = FLT_MIN;
    for(int r = 0; r < mat.rows; r++)
        for (int c = 0; c < mat.cols; c++)
        {
            float val = mat.pData[ r * mat.cols + c];// mat.pData==null,不该返回,对输入数据检查
            max = ( max > val ? max : val);
        }
    return max;
}

2.函数应该放在哪里

// draw.cpp
// The function must be defined before it was called
bool drawLine(int x1, int y1, int x2, int y2)
{
    // Source code here
    return true;
}

bool drawRectangle(int x1, int y1, int x2, int y2)画矩形
{
    // some calculation here
    drawLine(...);
    drawLine(...);
    drawLine(...);
    drawLine(...);

    return true;
}

// draw.cpp
// declared first, parameter names can be omitted
bool drawLine(int x1, int y1, int x2, int y2);//声明函数,告诉编译器有这个函数

bool drawRectangle(int x1, int y1, int x2, int y2)
{
    // some calculation here
    drawLine(...);
    drawLine(...);
    drawLine(...);
    drawLine(...);//调用的函数在下面

    return true;
}
// define it later

bool drawLine(int x1, int y1, int x2, int y2)
{
    // Source code here
    return true;
}

3.更加清晰的代码组织结构

4.函数的参数

        a)参数是些变量名

        b)把数据从调用的环境传到被调用的环境(传参)

5.传参方式

a)传递值

基本数据类型

int foo(int x)//传的是数据拷贝,x是函数内的局部变量,作用域在花括号里
{   // x is a copy
    x += 10;
    return x;//拷贝
}

int main()
{
    int num1 = 20;
    int num2 = foo(num1);// num1不会被改变,num1和x的存储地址不同
    return 0;
}

指针类型

int foo(int * p)//地址拷贝进了函数
{
    (*p) += 10;
    return *p;
}

int main()
{
    int num1 = 20;
    int * p = &num1;
    int num2 = foo( p );// num1被修改,num1地址传进去
    return 0;
}

结构体类型

struct Matrix
{
    int rows;
    int cols;
    float * pData;
};
float matrix_max(struct Matrix mat)
{
    float max = FLT_MIN;
    for(int r = 0; r < mat.rows; r++)
        for (int c = 0; c < mat.cols; c++)
        {
            float val = mat.pData[ r * mat.cols + c];
            max = ( max > val ? max : val);
        }
    return max;
}
Matrix matA = {3,4};
matrix_max(matA);

MatA拷贝mat,pdata是一个地址指向数据区new12个 数据空间

b)引用(c++

一个对象或变量的别名

基本数据类型

int num = 0;
int & num_ref = num;//&放在类型后边是引用
num_ref是num的别名

num_ref = 10;

对象引用

struct Matrix
{
    int rows;
    int cols;
    float * pData;
};
Matrix matA = {3,4};
matA.pData = new float[matA.rows * matA.cols]{};//堆区开辟内存空间
Matrix & matA_ref = matA;
Matrix * pMatA = &matA;//4or8(32位操作系统是4字节,64位是8个字节)

 

 指针和引用的区别

int & num_ref; // error 引用一定要初始化
Matrix & mat_ref; // error 
//引用比指针更安全,指针容易越界,不会乱指

 结构体很大传参怎么办

struct PersonInfo
{
    char firstname[256];
    char middlename[256];
    char lastname[256];
    char address[256];
    char nationalID[16];
     // and more
};

char * fullname(struct PersonInfo pi)//拷贝需要很大一块内存
{
    // ...
}
char * fullname(struct PersonInfo * ppi)
{
    if (ppi == NULL)
    {
        cerr << "Invalid pointer" << endl;
        return NULL;
    }
    // ...
}

引用不是拷贝,效率更高

但函数内部修改mat外面的mat也会变,因为是起别名

float matrix_max(const struct Matrix & mat)//就修改不了了
{
    float max = FLT_MIN;
    // ...
    return max;
}

const引用注意事项:
(1)对const的引用可能引用一个并非const的对象:引用的对象是常量还是非常量可以决定其能参与的操作,却无论如何都不会影响到引用和对象的绑定关系。

r2绑定(非常量)整数i是合法的行为。然而,不允许通过r2修改i的值。尽管如此,i的值仍然允许通过其他途径修改,既可以直接给i赋值,也可以通过像r1一样绑定到i的其他引用来修改。
(2)初始化的必要性: 一旦引用已经定义,它就不能再指向其他的对象.

6.返回语句

a)无具体返回值函数

void print_gender(bool isMale)//void类型函数不需要具体返回值
{
    if(isMale)
        cout << "Male" << endl;
    else
        cout << "Female" << endl;

    return;//可写可不写
}

b)有具体返回值函数(可返回基本数据类型或组合类型(类、结构体))

返回也是值传递

i)基本数据类型:常量或变量值拷贝传出

ii)指针:地址拷贝出去

iii)结构体:结构体拷贝

float maxa = matrix_max(matA);//函数内的局部变量消失,拷贝给maxa
Matrix * pMat = create_matrix(4,5);
Matrix * create_matrix(int rows, int cols)
{
    Matrix * p = new Matrix{rows, cols};
    p->pData = new float[p->rows * p->cols]{1.f, 2.f, 3.f};
    // you should check if the memory is allocated successfully
    // and don’t forget to release the memory
    return p;
}

c)其他情况return

矩阵加法A+B->C

bool matrix_add(const Matrix & matA, const Matrix & matB, Matrix & matC)
{
//检查A和B的宽高是否相等,不相等 return false打印错误信息
    // matC是引用,释放其内存,重新创建和AB一样大小的矩阵
    // do: matC = matA + matB
    // return true if everything is right
}

bool 函数是否正常运行的标识

利用引用避免内存拷贝,效率高,但有可能被修改加const

OpenCV

7.内联函数(重要:关乎程序运行效率) 

A)函数的调用是有代价的,每次调用把数据压栈,跳转,做完事情再回来,然后把栈取出来,再执行

如果函数复杂计算量很大这个代价可以忽略不计

如果很小的函数,频繁调用,是非常搞的代价

inline float max_function(float a, float b)
{
    if (a > b)
        return a;
    else
        return b;
}

Inline只会建议编译器inline方式编译

B)宏处理(不鼓励使用)

#define MAX_MACRO(a, b) (a)>(b) ? (a) : (b)

宏是预处理在编译之前文本替换,而且类型不定可以int,float等

注意加括号,避免优先级出问题

宏虽然效率没问题,但是很危险

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值