• 第六章 函数


    6.1

    形参:与实参有联系的变量,可以是实参的拷贝、引用等。

    实参:传递给被调用函数的参数,让调用函数中的值可以给被调用函数使用

    6.4

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <iterator>
     5 #include <stdexcept>
     6 #include <string>
     7 #include <cstring>
     8 
     9 using std::cin;
    10 using std::cout;    
    11 using std::endl;
    12 using std::vector;
    13 using std::string;
    14 using std::runtime_error;
    15 
    16 int fact(int n)
    17 {
    18     if (n < 1)    return -1;
    19     int ans = 1;
    20     for (int i = n; i > 0; i--) {
    21         ans *= i;
    22     }
    23     return ans;
    24 }
    25 
    26 int main() 
    27 {
    28     int n;
    29     while(cin >> n) {
    30         cout << fact(n) << endl;
    31     } 
    32     return 0;
    33 }
    View Code

    6.5

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <iterator>
     5 #include <stdexcept>
     6 #include <string>
     7 #include <cstring>
     8 
     9 using std::cin;
    10 using std::cout;    
    11 using std::endl;
    12 using std::vector;
    13 using std::string;
    14 using std::runtime_error;
    15 
    16 int i_abs(int n)
    17 {
    18     return n > 0 ? n : -n;
    19 }
    20 
    21 int main() 
    22 {
    23     int a;
    24     while(cin >> a)
    25         cout << i_abs(a) << endl;
    26     return 0;
    27 }
    View Code

    6.6

    形参:生命周期和函数一样

    局部变量:生命周期自其定义语句开始至定义所在的块末尾

    局部静态变量:生命周期自其定义语句开始至程序结束

    6.7

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <iterator>
     5 #include <stdexcept>
     6 #include <string>
     7 #include <cstring>
     8 
     9 using std::cin;
    10 using std::cout;    
    11 using std::endl;
    12 using std::vector;
    13 using std::string;
    14 using std::runtime_error;
    15 
    16 int coco()
    17 {
    18     static int flag = 0;
    19     if (!flag)    return flag++;
    20     return 1;            //flag的值不是0时执行此语句 
    21 }
    22 
    23 int main() 
    24 {
    25     for (int i = 1; i <= 10; i++) 
    26         cout << coco() << endl;
    27     return 0;
    28 }
    View Code

    6.8

    1     int fact(int n);
    Chapter6.h

    6.9

     1 #include <iostream>
     2 #include "Chapter6.h"
     3 
     4 int fact(int n)
     5 {
     6     int ans = 1;
     7     for (int i = n; i != 0; i--)
     8         ans *= i;
     9     return ans;
    10 }
    fact.cpp
     1 #include <iostream>
     2 #include "fact.cpp"
     3 
     4 using std::cin;
     5 using std::cout;    
     6 using std::endl;
     7 
     8 int main() 
     9 {
    10     int n;
    11     while(cin >> n)
    12         cout << fact(n) << endl;
    13     return 0;
    14 }
    factMain.cpp

    6.10

     1 #include <iostream>
     2 #include <vector>
     3 #include <string>
     4 
     5 using std::cin;
     6 using std::cout;    
     7 using std::endl;
     8 using std::vector;
     9 using std::string;
    10 
    11 void swap(int *p1, int *p2)
    12 {
    13     int tmp;
    14     tmp = *p1;
    15     *p1 = *p2;            //改变P1所指对象的值 
    16     *p2 = tmp;
    17 }
    18 
    19 int main() 
    20 {
    21     int a, b;
    22     while (cin >> a >> b) {
    23         cout << "交换前:a = " << a << ", b = " << b << endl;
    24         swap(&a, &b); 
    25         cout << "交换后:a = " << a << ", b = " << b << endl;
    26     }
    27     return 0;
    28 }
    View Code

    6.12

     1 #include <iostream>
     2 #include <vector>
     3 #include <string>
     4 
     5 using std::cin;
     6 using std::cout;    
     7 using std::endl;
     8 using std::vector;
     9 using std::string;
    10 
    11 void swap(int &r1, int &r2)
    12 {
    13     int tmp;
    14     tmp = r1;
    15     r1 = r2;            //改变P1所绑定对象的值 
    16     r2 = tmp;
    17 }
    18 
    19 int main() 
    20 {
    21     int a, b;
    22     while (cin >> a >> b) {
    23         cout << "交换前:a = " << a << ", b = " << b << endl;
    24         swap(a, b); 
    25         cout << "交换后:a = " << a << ", b = " << b << endl;
    26     }
    27     return 0;
    28 }
    View Code

    6.13

    void f(T):传值

    void f(&T):穿引用

    6.15

    因为s字符串是不能被函数所修改的,所以是常量引用。c可能是一个临时变量,所以不需要使用引用类型,也无需函数加以修改其本身。如果令occurs为常量引用,则输出occurs为0(不能加以修改),而s可能会在程序中被修改。

    6.16

    形参被定义成普通的引用,在本题虽然不会引发错误,但这么做的局限性如下:我们不能把const对象、字面值或者需要类型转换的对象传递给这个形参。

    6.17

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <string>
     5 
     6 using std::cin;
     7 using std::cout;    
     8 using std::endl;
     9 using std::vector;
    10 using std::string;
    11 
    12 bool fun1(const string &s)
    13 {
    14     for (auto it = s.begin(); it != s.end(); it++) {
    15         if (isupper(*it)) {
    16             return true;        
    17         }
    18     }
    19     return false;
    20 }
    21 
    22 void fun2(string &s)
    23 {
    24     for (auto &i : s) 
    25         i = isupper(i) ? tolower(i) : i;
    26 }
    27 
    28 int main() 
    29 {
    30     string s1;
    31     cin >> s1;
    32     cout << s1 << endl;
    33     bool ownUpper = fun1(s1);
    34     fun2(s1);    
    35     if (ownUpper)    cout << "存在大写字母!
    ";
    36     else    cout << "没有大写字母!
    "; 
    37     cout << s1 << endl;
    38     return 0;
    39 }
    View Code

    使用的形参并不相同,对于fun1,我们不需要修改对象的值,所以可以使用常量引用;而对于fun2,我们需要修改对象的值,所以不能使用常量引用。

    6.18

    (a):bool compare(matrix &, matrix &);

    (b):vector<int>::iterator change_val(int, vector<int>::iterator);

    6.20

    引用形参什么时候是常量引用:首先函数内不要修改所引用对象的值时,其次我们希望能够使用const对象、字面值或需要类型转换的对象作为实参时。

    形参本应该是常量引用,而我们将其设为了普通引用:可能误导用户能够修改其中的值;还可能因为一些只能够用于常量引用的实参,从而导致编译器报错。

    6.22

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <string>
     5 
     6 using std::cin;
     7 using std::cout;    
     8 using std::endl;
     9 using std::vector;
    10 using std::string;
    11 
    12 void swap_point(int *&p, int *&q)        //这个形参类型可以的 
    13 {
    14     int *s = nullptr;
    15     s = p;
    16     p = q;
    17     q = s;
    18 }
    19 
    20 int main() 
    21 {
    22     int a = 3, b = 4;
    23     int *p1 = &a, *p2 = &b;
    24     cout << "交换指针的值之前:p1的值为" << p1 << ",p2的值为" << p2 << endl;
    25     swap_point(p1, p2);
    26     cout << "交换指针的值之后:p1的值为" << p1 << ",p2的值为" << p2 << endl;
    27     return 0;
    28 }
    View Code

    6.25

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <string>
     5 
     6 using std::cin;
     7 using std::cout;    
     8 using std::endl;
     9 using std::vector;
    10 using std::string;
    11  
    12   
    13 int main(int argc, char *argv[])    //形参argv是一个数组,它的元素是指向C风格字符串的指针  
    14 {  
    15     string ss;  
    16     for (int i = 1; i != argc; ++i) {  
    17         ss += argv[i];  
    18         ss += " ";  
    19     }  
    20     cout << ss <<endl;  
    21     return 0;  
    22 }  
    View Code

    注意:要让main函数接受参数,我们可以在linux命令行界面输入参数。

    6.26

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <string>
     5 
     6 using std::cin;
     7 using std::cout;    
     8 using std::endl;
     9 using std::vector;
    10 using std::string;
    11  
    12   
    13 int main(int argc, char *argv[])    //形参argv是一个数组,它的元素是指向C风格字符串的指针  
    14 {  
    15     for (int i = 1; i != argc; ++i) {  
    16         cout << argv[i] << endl;  
    17     }  
    18     return 0;  
    19 }  
    View Code

    6.27

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <string>
     5 #include <iterator>
     6 #include <initializer_list>
     7 
     8 using namespace std; 
     9 
    10 void print(initializer_list<int> a)
    11 {
    12     int ans = 0;
    13     for (auto i : a)
    14         ans += i;
    15     cout << ans << endl;
    16 }
    17   
    18 int main()
    19 {  
    20     print({1, 2, 3, 4 ,5});
    21     return 0;  
    22 }  
    View Code

    6.30

    int cmp(int a, int b)
    {
    	if (a == b)
    		return;	  //[Error] return-statement with no value, in function returning 'int' [-fpermissive]
    	if (a > b)
    		return 1;
    	if (a < b)
    		return 0;
    }

    报错信息:[Error] return-statement with no value, in function returning 'int' [-fpermissive] 

     

    6.31

    返回的引用无效:当返回局部对象的引用时

    返回常量的引用无效:当要给调用的结果赋值时,函数的返回类型只能是非常量引用

    6.32

    书中的代码:

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <string>
     5 #include <iterator>
     6 #include <initializer_list>
     7 
     8 using namespace std; 
     9 
    10 int &get(int *array, int index)
    11 {
    12     return array[index];
    13 }
    14   
    15 int main()
    16 {  
    17     int ia[10];
    18     for (int i = 0; i != 10; i++)
    19         get(ia, i) = i;
    20     return 0;  
    21 }  
    View Code

    我在编译器上跑了一下,得出的结果是合法的。

    但是我认为它那个get函数涉及“返回局部对象的引用”,所以我也写了一个合法的函数:

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <string>
     5 #include <iterator>
     6 #include <initializer_list>
     7 
     8 using namespace std; 
     9 
    10 int &get(int (&array)[10], int index)        //形参是数组的引用 
    11 {
    12     return array[index];
    13 }
    14   
    15 int main()
    16 {  
    17     int ia[10];
    18     for (int i = 0; i != 10; i++)
    19         get(ia, i) = i;
    20 //    for (auto i : ia)
    21 //        cout << i << " ";
    22 //    cout << endl;
    23     return 0;  
    24 }
    View Code

    6.33

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <string>
     5 #include <iterator>
     6 #include <initializer_list>
     7 
     8 using namespace std;
     9 
    10 vector<int> a = {0, 1, 2, 3, 4}; 
    11 
    12 void print(vector<int>::iterator iter)
    13 {
    14     if (iter != a.end()) {
    15         cout << *iter++ << endl;
    16         print(iter);
    17     }
    18     return;
    19 }
    20   
    21 int main()
    22 {  
    23     auto it = a.begin();
    24     print(it); 
    25 }  
    View Code

    6.34

    如果传入的实参是负数,那将陷入无限循环,直至程序栈空间被耗尽。

    6.35

    val--:会先将自减之前的值拷贝一个副本,然后进行自减运算,再将那个副本作为实参调用函数。

    结果:每次传的实参的值都是相同的,无限循环,且与初衷背离。

    6.36

    string (&func(形参))[10];

     

    6.37

    1 //类型别名 
    2 using arrS = string[10];
    3 arrS& func(形参);
    4 //尾置返回类型 
    5 auto func(形参) -> string(&)[10];
    6 //decltype关键字 
    7 string ss[10];
    8 decltype(ss) &func(形参); 
    View Code

    第二种方式比较好,既然是C++11的新标准,那么肯定有它创新的意义所在,简短方便。

    6.38

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <string>
     5 #include <iterator>
     6 #include <initializer_list>
     7 
     8 using namespace std; 
     9 
    10 int odd[] = {1, 3, 5, 7, 9};
    11 int even[] = {0, 2, 4, 6, 8};
    12 
    13 //返回数组的引用 
    14 decltype(odd) &arrPtr(int i)
    15 {
    16     return (i % 2) ? odd : even;
    17 } 
    18   
    19 int main()
    20 { 
    21     cout << arrPtr(3)[1] << endl;            //输出3 
    22     return 0;  
    23 }
    View Code

    6.39

    第二条声明语句的含义:

    (a):实参要有两个,每个实参的类型可以是常量整型、整型

    (b):无参数传递,返回类型为double

    (c):实参为double类型的指针,返回类型为指向int类型的指针

    其中有非法声明的组别是:(a)

    6.40

    (b)是错误的,因为一旦某个形参被赋予了默认值,它后面的所有形参都必须有默认值。

    6.41

    (a)非法,因为形参ht没有默认值,而(a)调用时却没有提供相应的实参

    (c)与初衷不符,因为传递的'*'是个char,而形参wd是int,所以'*'可以转换成形参中的wd的类型,而初衷是将'*'传递给形参bckgrnd。

    6.42

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <string>
     5 #include <iterator>
     6 #include <initializer_list>
     7 
     8 using namespace std; 
     9 
    10 string make_plural(size_t ctr, const string& word, const string& ending = "s")
    11 {
    12     return (ctr > 1) ? word+ending : word;  
    13 }  
    14 int main()  
    15 {     
    16     cout<<"两单词的单数形式:"<<make_plural(1,"success","es")<<"  "<<make_plural(1,"failure")<<endl;  
    17     cout<<"两单词的复数形式:"<<make_plural(2,"success","es")<<"  "<<make_plural(2,"failure")<<endl;  
    18     return 0; 
    19 }
    View Code 

    6.43

    (a):放在头文件中,因为它是内联函数

    (b):放在头文件中,函数声明最好放在头文件中

    6.44

    inline bool isShorter(const string &s1, const string &s2)
    {
    	return s1.size() < s2.size();
    }  

     

    6.46

    不能,尽管其形参是常量引用,但是const string并不是字面值类型。

    6.47

    打开调试器(即未定义NDEBUG):

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <string>
     5 #include <iterator>
     6 #include <initializer_list>
     7 #include <cassert>
     8 
     9 //#define NDEBUG
    10 
    11 using namespace std; 
    12 
    13 void print(vector<int> vec)
    14 {
    15     #ifndef NDEBUG
    16         cout << "vector size: " << vec.size() << endl;
    17     #endif
    18 //    assert (!vec.empty());
    19     if (vec.size() > 0) {
    20         cout << vec.back() << endl;
    21         vec.pop_back();
    22         print(vec);
    23     }
    24     else if(vec.size() == 0) {
    25         cout << "vector size is zero, no value." << endl;
    26     }
    27 }
    28 int main()  
    29 {     
    30     vector<int> a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    31     print(a); 
    32     return 0; 
    33 }
    View Code

    关闭调试器(即定义NDEBUG):

    #include <iostream>
    #include <vector>
    #include <cctype>
    #include <string>
    #include <iterator>
    #include <initializer_list>
    #include <cassert>
    
    #define NDEBUG            //定义NDEBUG 
    
    using namespace std; 
    
    void print(vector<int> vec)
    {
        #ifndef NDEBUG
            cout << "vector size: " << vec.size() << endl;
        #endif
    //    assert (!vec.empty());
        if (vec.size() > 0) {
            cout << vec.back() << endl;
            vec.pop_back();
            print(vec);
        }
        else if(vec.size() == 0) {
            cout << "vector size is zero, no value." << endl;
        }
    }
    int main()  
    {     
        vector<int> a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        print(a); 
        return 0; 
    }
    View Code

    补充:使用assert的代码(应仅用于验证不可能发生的事情,即检查不能发生的条件)

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <string>
     5 #include <iterator>
     6 #include <initializer_list>
     7 #include <cassert>
     8 
     9 #define NDEBUG            //定义NDEBUG 
    10 
    11 using namespace std; 
    12 
    13 void print(vector<int> vec)
    14 {
    15     #ifndef NDEBUG        //定义NDEBUG后,下面这条语句将被忽略 
    16         cout << "vector size: " << vec.size() << endl;
    17     #endif
    18     assert (!vec.empty());        //当vec为空时(即表达式为假),assert输出错误信息并终止程序的执行 
    19     cout << vec.back() << endl;
    20     vec.pop_back();
    21     print(vec);
    22 }
    23 int main()  
    24 {     
    25     vector<int> a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    26     print(a); 
    27     return 0; 
    28 }
    View Code

    注:我们上面的代码最后让“不能发生的条件”(即vec.empty==true)发生了,此时会终止程序的执行。

    6.48

    不合理,只要有输入,则assert一直为真,无意义。assert最好用于检查不能发生的条件。

    可以替换为:

        assert(s == sought);  

    6.49

    候选函数:一次调用对应的重载函数集中的函数,它①与被调用的函数同名,②声明在调用点可见

    可行函数:此时考察本次调用提供的实参,在候选函数中能被这组实参调用的函数

    6.50

    只有(a)不合法,因为该调用具有二义性。

    6.52

    (a):等级3,为通过类型提升实现的匹配

    (b):等级4,为通过算术类型转换实现的匹配

    6.53

    第二条语句产生的影响

    (a):实参若是常量,则调用第二条语句

    (b):同上

    (c):顶层const,函数调用时会忽略之,区别仅仅是调用第二个函数时不能写值

    所以非法的是(c)

    6.54

    int func(int, int ); 		//函数的声明 
    typedef decltype(func) *pfunc;	//pfunc为指向函数的指针 
    vector<pfunc> vec;  

    6.55

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <string>
     5 #include <iterator>
     6 #include <initializer_list>
     7 #include <cassert>
     8 
     9 using namespace std; 
    10 
    11 int fun1(int a, int b)
    12 {
    13     return a + b;
    14 } 
    15 
    16 int fun2(int a, int b)
    17 {
    18     return a - b;
    19 }
    20 
    21 int fun3(int a, int b)
    22 {
    23     return a * b;
    24 }
    25 
    26 int fun4(int a, int b)
    27 {
    28     return a / b;
    29 }
    30 
    31 int func(int, int );         //函数的声明 
    32 typedef decltype(func) *pfunc;    //pfunc为指向函数的指针 
    33 vector<pfunc> vec;
    34 
    35 int main()  
    36 {     
    37     vec.push_back(fun1);
    38     vec.push_back(fun2);
    39     vec.push_back(fun3);
    40     vec.push_back(fun4);
    41     cout << vec[1](3,2) << endl;    //3-2=1
    42     return 0; 
    43 }
    View Code

    6.56

     1 #include <iostream>
     2 #include <vector>
     3 #include <cctype>
     4 #include <string>
     5 #include <iterator>
     6 #include <initializer_list>
     7 #include <cassert>
     8 
     9 using namespace std; 
    10 
    11 int fun1(int a, int b)
    12 {
    13     return a + b;
    14 } 
    15 
    16 int fun2(int a, int b)
    17 {
    18     return a - b;
    19 }
    20 
    21 int fun3(int a, int b)
    22 {
    23     return a * b;
    24 }
    25 
    26 int fun4(int a, int b)
    27 {
    28     return a / b;
    29 }
    30 
    31 int func(int, int );         //函数的声明 
    32 typedef decltype(func) *pfunc;    //pfunc为指向函数的指针 
    33 vector<pfunc> vec;
    34 
    35 int main()  
    36 {     
    37     vec.push_back(fun1);
    38     vec.push_back(fun2);
    39     vec.push_back(fun3);
    40     vec.push_back(fun4);
    41     for (auto function : vec)
    42         cout << function(3, 2) << endl;
    43     return 0; 
    44 }
    View Code

     

     

  • 相关阅读:
    GitHub 源码,Framework 框架
    转int啥啥啥的
    查看apk签名 和 keystore 的信息
    一次apk打开时报内存溢出错误,故写下内存溢出的各种原因和解决方法
    客户端传值里面包含URL特殊字符的应对方法
    Linux全硬盘搜索文件名是xxxxx的命令
    pythonmysql运行报错解决过程中遇到的其中一个报错解决文章来源
    linux查看硬盘占用情况
    Linux使用nginx反向代理。可实现域名指向特定端口
    Linux下使用yum安装软件命令
  • 原文地址:https://www.cnblogs.com/xzxl/p/7658353.html
Copyright © 2020-2023  润新知