Primer (十)

函数

1. void返回值,可以不写return,也可以在需要返回的地方写return;

2. 返回值有三种,变量、指针、引用,与实参赋值形参是一样的,变量和指针都是基于拷贝的,引用不是拷贝。指针指向的内容没有拷贝。

main(){
    int a=10;
}
int f1(int i) { // 返回变量,直接返回即可,复制i后返回。
    return i;
}
int *f2(int i) { // 返回指针,等价于int *temp=&i;return *temp; 复制一个指向i的指针后返回。
    return &i;
}
int &f3(int i) { // 返回引用,和实参传入形参的方式相同,返回i即可,返回值即是实参i本身,没有复制。
    return i;
}
const int& f4(int i) {
    return i; // 正确,f4(a)相当于const int temp=a;
}

3. 返回引用和指针时,不能指向函数内的对象,因为它们会销毁,只能引用或指向形参中的变量。返回变量可以随意,因为返回的是拷贝的副本。

4. 返回vector

vector<string> f() {
    return {"abc","def"}; // 用{}返回vector,类似于vector初始化
}
5. 返回数组

int (*function(int i))[10]; // 数组不可以被拷贝,所以只能返回指针或引用
int arr[] = {1,2,3};
main() {
    for (auto i:*function()) { // function()是&arr头指针的地址 *function()是arr头指针,也是数组名
        cout<<i<<endl; // 1 2 3
    }
    cout<<**function()<<endl; // 1  **function()等于*arr
}
int (*function())[3] { // [3]不可省略
    return &arr; // 不能返回arr,因为arr指向的是头元素,不是arr[3],必须返回指向arr的指针,也就是头元素的指针的指针
}
6. 函数名相同,形参列表不同是重载,形参列表相同,返回值不同不是重载,main函数不能重载。

void f(int a); // 普通变量加const不算重载
void f(const int a);
void f(int *p); // 指针的顶层const不算重载
void f(int * const p);
void f(int *p); // 指针的底层const是重载
void f(const int *p);
void f(int &r); // 引用加const是重载
void f(const int &r);
7. const_cast在重载中的使用

const string& f(const string &s) {
    return s;
}
string& f(string &s) {
    auto temp = f(const_cast<const string&>(s)); // 利用const_cast先加上const
    return const_cast<string&>(temp); // 再利用const_cast去掉const
}
8. 作用域同名变量、函数名都可以隐藏外部,C语言中,先查找名字,再检查类型。

int read(int i);
int print(int a);
void f() {
    int a = 10;
    int read = 0;
    read(a); // 错误,read被隐藏了
    void print();
    print(a); // 错误,print被隐藏了,不要在函数中声明函数
}

9. 默认实参

定义时,默认实参后面必须都是默认的。函数内局部变量不能被声明成实参的值。

声明时,如果要分多次声明:

void f(a,b,c=10); // OK
void f(a,b,c=20); // 错误,已经声明了c
void f(a=10,b=10,c); //OK

10. 内联函数,在编译时,在函数名处展开函数,避免了运行时函数的开销。一般定义在头文件中。前面加上inline

inline int f(int i) {
    return i+1;
}
main() {
    int a=10;   
    cout<<f(a)<<endl; // 等价于cout<<i+1<<endl;
}
11. assert NDEBUG

#define NDEBUG // NDEBUG表示非调试模式,所有assert不起作用。默认为#define DEBUG开启调试模式
main () {
    int a=10;
    assert(a == 20); // 在DEBUG模式下,assert为真才继续执行
}
还有几个宏用于调试:__func__当前函数名    __FILE__当前文件名    __LINE__当前行数   __TIME__编译时间    __DATE__编译日期

12. 重载如何匹配最优函数

当两个重载函数的优先级相同时,出现二义性错误,返回错误。

优先级从高至低:完全匹配->只差一个const->隐式类型转换(char提升至int)->损失精度隐式类型转换(double变成int )

void f(int);
void f(short);
char a='A‘; // char提升到int,使用int
void f(float);
void f(long);
double d=1.2; // 损失精度的类型转换无法比较哪个更优,二义性错误
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值