C++学习笔记(4)

C++ Primer Chapter 6

function 函数

  1. return type
  2. function name
  3. body
  4. comments(optional)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// |comments
// @param a: blablabla 
//|return type
int func(int a, int b, int c)
//   |function name
//body
{
    cout << a << b << c << endl; 
    return a + b + c;
}
  • 参数列表中的参数不一定从左到右进行初始化,只能保证调用函数的时候所有值已经完成初始化,如果参数之间存在依赖关系则可能出现问题。
  • 函数中定义的变量的生命周期到函数结束时就结束

static关键字

1
2
3
4
5
6
7
8

int func(){
    static int a = 0; 
    //只会在最开始调用的时候初始化,后面再调用会使用以前的值,
    //不会在函数结束后被销毁
    cout << a << endl; 
    return a;
}

参数传递

  1. pass by value(copy拷贝)
  2. pass by reference/pointer
1
2
3
4
5
6
//                   |pass by pointer
int func(int a, int* b, int &c)
//           |pass by value  |pass by reference
{
    ;
}
  • top-level const 能被drop, low-level不能
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17

void func1(const int a){
    // 实际编译产生的代码:
        // const int tmp = 123; //先产生一个tmp对象
        // a = tmp; //再赋值给a
    // top-level const被drop掉了
    a = 10;
}

void func2(const int& a){
    a = 10;
}

int main(){
    func1(123);//
    func2(123);//会出错
}

main function 接受参数

  • main函数使用(int argc, char** argv)
  • 使用std::initializer_list
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include<initializer_list>
using std::initializer_list

int func(initializer_list<int> initializer_list){
    for(int number : initializer_list){
        cout << number << endl;
    }

}

int main(int argc, char** argv){ 
//main函数可以接受多个参数,数量为argc,存在argv数组中,且为const
    for(int i = 0; i < argc; i ++){
        cout << argv[i] << endl;
    }
    func({1,2,3,4}) //使用initializer_list传递多个参数,const
}

返回值

  • void类型的函数必须有返回值,且类型要一致
  • 不要返回local variable的引用
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
int * func(){
    int b = 10;
    int *a = &b;
    return a;
}

int main(){
    int * x = func();
    //可能在func()结束的时候变量的内存已经被销毁,有概率会出bug
    return 0;
}

Overload 重载

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
void func(int a, int b){
    cout << "(int, int)" << endl;
}

void func(int a, double b){
    cout << "(int, double)" << endl;
}

int main(){
    func(10,10);
    func(10,10.)
    return 0;
}
  • 重载的参数设置要符合直觉,本身就是两个功能的函数没必要使用重载
  • 重载中的top-level const 能被drop
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void func(int a){
    cout << "int" << endl;
}

//top-level,重复定义会报错
void func(const int a){
    cout << "int" << endl;
}

//top-level
void func(int * const a){
    cout << "int" << endl;
}

//最左边的是low-level
void func(const int* const a){
    cout << "int" << endl;
}

//最左边的是low-level
void func(const int* a){
    cout << "int" << endl;
}

int main(){
    int *a = nullptr;
    func(a);//
    return 0;
}

default argument 默认参数

1
2
3
4
5
6
7
8
9
void func(int a = 7, int b = 3, char c = 'j'){
    cout << a << " " << b << " " << c << " " << endl;
}

int main(){
    func(10);//只能从左到右匹配,func(int a = 10, int b = 3, char c = 'j')
    func(,2,);//❌不能跳过前面的参数去穿中间的参数的值
    return 0;
}

inline

  • 减小开销
  • 可读性
  • 什么时候不会处理inlien:函数是递归或者包含static
1
2
3
4
inline
int func(){
    cout << '' << endl;
}

constexpr

用于一些常量值

1
constexpr int get_size(){ return 10;}

assert

1
2
3
4
5
void func(int a){
    assert(a == 10);
    //符合则继续执行
    //不符合则Assertion failed,程序停止
}

在预处理语句使用#define NDBUG会无视assert

function matching 函数匹配

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
void func(int a){
    cout << "int" << endl;
}

void func(int a, double b){
    cout << "int" << endl;
}


int main(){
    func(10);// call is ambiguous
    func(10, 2.);//✔️
    return 0;
}

pointers of function 函数指针

函数指针指向一个函数,不关心函数名字

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
bool is_shorter(const string& s1, const string& s2,){
    return s1.size() < s1.size();
}

bool (*pfun) (const string& s1, const string& s2);

int main(int argc, cha** argv){
    pfunc = &is_shorter;
    cout << pfunc("abc", "abcdef") << endl;
    return 0;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#include<iostream>
using std::cout;
using std::endl;

void func1(){
    cout << "func1" << endl;
}

void func2(){
    cout << "func2" << endl;
}

int main(int argc, char** argv){
    void (*pfunc) ();
    pfunc = &func1;
    pfunc();
    pfunc = &func2;
    pfunc();
}