码迷,mamicode.com
首页 > 编程语言 > 详细

【C++ Primer Chapter 6 总结】函数

时间:2021-06-02 15:48:31      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:列表   数列   plain   函数重载   返回   转换   隐式转换   ptr   constexpr   

1.变量名的作用域(the scope of name)
   对象的生命周期(the lifetime of an object)
2.各源文件(.cpp)可以单独编译得到目标代码(.obj),所有目标代码链接得到可执行程序(.exe)
3.局部静态对象 local static objects 在通过定义在第一次被访问之前被初始化。不随函数的结束而被销毁,直到整个程序结束才被销毁。
4.函数声明(即:函数原型 function prototype)
5.分离式编译,程序可以分别保存在数个文件中,分别编译,然后链接成一个可执行文件。
6.形参(parameter),实参(argument)。如果形参是引用,则形参是实参的别名,该形参绑定到该实参,叫做引用传递(passed by reference)。否则,实参的值被复制(深拷贝),之后形参和实参就是独立的两个对象,这叫做值传递(passed by value)。
函数调用的时候,实参向形参类型转换。形参是const变量,实参可以是const可以不是;形参不是const变量,实参也不能是const。(因为const实参没办法转换为非const)
7.形参为(plain)引用类型 e.g. int&,不能接受结果为右值的表达式:literal(字面值),结果为右值的表达式(4+5),const int对象。
8.对于不改变参数的函数的形参要定义为const 引用类型。
9.const形参和实参。当拷贝实参来初始化形参时,形参的top-level的const被忽视。
void fcn(const int i);         // const is ignored: 既可以接受const的实参,也可以接受非const的实参
void fcn(int i);             // error: redefined, 和上面的定义都可以接受非cosnt的实参,重定义了
 
10.plain reference只接受左值。cosnt reference可以接受字面值,结果为同类型的表达式,const类型。
void reset(int& i);
int i = 0;
const int ci = i;
string::size_type ctr = 0;
reset(i);
reset(ci);           // error: can‘t bind a plain reference to the const object
reset(42);           // error: can‘t bind a plain reference to a literal
reset(ctr);         // error: types don‘t match

  

11.数组参数。因为数组不能复制,所以数组作为参数时通常被(隐式)转换为指针类型。因为数组名会被转换为指针,所以通常函数不知道数组的size,需要单独作为一个参数传递。
void print(cosnt int*);
void print(const int[]);
void print(const int[10]);  // same
 
int i = 0, j[2] = {0,1};
print(&i);
print(j);  // ok: 数组名会被隐式转换为指针
 
void print(int (*matrix)[10], int rowSize);  // 二维数组,matrix指向大小为10的一维数组的指针
void print(int matrix[][10], int rowSize);  // 数组名会被转为指针类型
 
12.数组的引用参数
void print(int (&arr)[10]);                //只能接受实参大小为10的数组,arr是绑定到大小为10的数组上的引用

 

13.未知数量的参数。
可以使用initializer_list参数作为函数未知数量的参数。
initializer_list<T> lst{a, b, c, ...};
void print(initializer_list<string> il);
 
14.函数调用返回引用类型的是左值,其他的是右值。
15.C++11中可以返回多个值。返回vector类型。
return {v1, v2};
 
16.返回指向数组的指针。因为数组不能拷贝,所以要返回数组类型时,只能返回指向数组的指针或者数组的引用。
声明时候要带数组维度数字?参数是数组本身的时候不用,参数是指向数组的指针或数组的引用的时候必须带。
如果我们要定义一个返回指向数组的指针的函数,则维数说明必须跟随该函数的名称。 但是,函数包含一个参数列表,该名称列表也紧随其后。 参数列表在维度说明之前。
int arr[10];
int *p1[10];                          // p1是大小为10的指针数组
int (*p2)[10];                         // p2是指向大小为10的数组的指针,数组元素是int
 
int (*func(int i))[10];                  // (*func(int i))必须带括号. 否者int *func(int i)[10]返回的就是大小为10的指针数组。func(int i) 函数 -> *func(int i)函数调用的结果可以解引用,是个指针 -> (*func(int i))[10]该指针指向的是大小为10的数组 -> int (*func(int i))[10]数组元素类型是int
auto func(int i) -> int(*)[10];             //trailing return type尾置返回类型
 
17.尾置返回类型。当返回类型过于复杂时,可以使用尾置返回类型简化函数声明。
如果已知函数返回的指针指向哪个数组时可以使用decltype。
int (*func(int i))[10];                   // 返回指向数组的指针
auto func(int i) -> int(*)[10];           // same
 
int odd[] = {1, 3, 5, 7, 9};
int even[] = {2, 4, 6, 8, 10};
decltype(odd) *arrPtr(int i){              // 注意decltype不会自动将数组类型转换为指针类型,因此返回类型要显式指出指针类型
    return (i % 2)? &odd : &even;
}
 
18.函数重载。同样的名字不同的参数列表(参数数量或类型),出现在同样的作用域。
有top-level const的形参不区别于没有top-level const的形参。low-level const属于重载。
调用重载函数时,一定要能找到一个和实参最match的形参列表,否则算作歧义调用。参数与参数的类型越接近越match。The best match:  每个参数的匹配不比任何其他可行函数所需的匹配差, 至少有一个参数的匹配度比任何其他可行函数提供的匹配度都要好。
int lookup(int);
int lookup(const int);                // 重复声明
int lookup(int*);
int lookup(int const*);              // 重复声明
 
int lookup(int*);
int lookup(const int*);              // ok
int lookup(int&);
int lookup(const int&);              // ok
 
void f();
void f(int);
void f(int, int);                   // 3
void f(double, double);             // 4
f(42, 2.56);                    // error: 编译器找不到唯一的best match, 无法决定调用3还是4

  

18.内联函数关键字:inlline。只是请求编译器,编译器可以选择忽视。
19.constexpr函数的返回值和参数必须是字面值类型(rvalue)。编译器会将调用的constexpr函数用其结果代替。
20.指向函数的指针。函数指针指向特殊的类型。函数的类型由其返回类型和其参数类型决定。
bool lengthCompare(const string&, const string&);
bool (*pf)(const string&, const string&);  // pf是指向函数的指针,该函数的类型是:bool (const string&, const string&)
bool *pf(const string&, const string&);   // pf是函数,返回类型是指向bool的指针

  

21.函数指针作为参数。当传递函数作为实参时,会被自动转换为函数指针。
void useBigger(const string &s1, const string &s2, bool pf(const string &, const string &));         // 第三个参数是函数类型,会自动被当做指向函数的指针
void useBigger(const string &s1, const string &s2, bool (*pf)(const string &, const string &));      // same
 
useBigger(s1, s2, lengthCompare);                      // 函数作为参数的函数调用
 
// 函数和函数指针类型的别名定义
typedef bool Func(const string &, const string &);
typedef decltype(lengthCompare) Func2;                  // same type. Func和Func2都是函数类型
 
typedef bool (*FuncP)(const string &, const string &); 
typedef decltype(lengthCompare) *FuncP2;                  // same type.  FuncP和FuncP2都是函数指针类型
 
void useBigger(const string &s1, const string &s2, Func f);
void useBigger(const string &s1, const string &s2, FuncP2 f); 

  

22.返回函数指针。返回类型为函数的不会被自动转换为函数指针。
using F = int(int*, int);              // F是函数类型
using PF = int(*) (int*, int);          // PF是指针类型
 
PF f1(int);                    // f1是函数,返回指向函数的指针类型
F* f1(int);                        // same
F f1(int);                    // error: F是函数类型,f1不能返回函数类型
 
int (*f1(int))(int*, int);          // same, f1(int)是函数 -> (*f1(int))函数调用结果可以解引用,是指针 -> 指针指向的类型 int (int*, int),是函数
auto f1(int) -> int(*)(int*, int);    // same
 
23. 作为函数参数的时候,函数名->(隐式地转换为)函数指针,数组名->(隐式地转换为)指向数组首元素的指针。
在decltype(),sizeof(),作为函数返回类型时不会自动转换成指针类型。数组和函数都不能作为函数的返回类型,若要返回数组或者函数,则一定要显示声明为指针类型。使用decltype()的时候也要显示声明为指针类型。
 

【C++ Primer Chapter 6 总结】函数

标签:列表   数列   plain   函数重载   返回   转换   隐式转换   ptr   constexpr   

原文地址:https://www.cnblogs.com/tristatl/p/14825556.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!