C++ Primer 第六章答案

这个博客详细解答了C++ Primer第六章的多个练习,包括函数调用、参数传递、作用域、递归、引用、函数重载、内联函数、模板等内容,并通过实例演示了如何使用这些概念。

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

练习6.1
在函数调用,参数传递中,实参将内容复制给形参。
作用域:实参的作用域要大于形参,形参仅在被调用的函数中使用。

练习6.2
(a) int f() { // -> string f()
          string s;
          // ...
          return s;
    }
(b) void f2(int i) { /* ... */ }  
(c) int calc(int v1, int v2) { /* ... */ }
(d) double square (double x) { return x * x; }

练习6.3
#include <iostream>
#include <vector>

using namespace std;

int fact(int val)
{
    if (val == 1)
        return 1;
    else
        return val*fact(val-1);
}

int main() 
{
    int a = 3, b = 0;
    b = fact(a);
    cout << b << endl;
    system("pause");
    return 0;
}

练习6.4
#include <iostream>
#include <vector>

using namespace std;

int fact(int val)
{
    if (val == 1)
        return 1;
    else
        return val*fact(val-1);
}

int main() 
{
    int a = 0, b = 0;
    cout << "Please input number" << endl;
    cin >> a;
    b = fact(a);
    cout << b << endl;
    system("pause");
    return 0;
}

练习6.5
#include <iostream>
#include <vector>

using namespace std;

int abs(int val)
{
    return (val >= 0) ? val : -val;
}

int main() 
{
    int a = 0, b = 0;
    cout << "Please input number" << endl;
    cin >> a;
    b = abs(a);
    cout << b << endl;
    system("pause");
    return 0;
}

练习6.6
形参与普通的局部变量作用域等性质基本相同,唯一一点不同是形参的初始化
时是由实参赋值完成,而局部静态变量的作用域只存在于局部但生命
周期是在整个程序中都存在。
#include <iostream>
#include <vector>

using namespace std;

int static_test(int val)
{
    static int a = 0;
    a += val;
    return a;
}

int main() 
{
    int a = 0;
    cout << "Please input number" << endl;
    while(cin >> a) 
        cout <<  static_test(a) << endl;
    
    system("pause");
    return 0;
}

练习6.7
#include <iostream>
#include <vector>

using namespace std;

int test()
{
    static int a = 0;
    return a++;
}

int main() 
{
    cout << test() << endl;
    cout << test() << endl;
    cout << test() << endl;
    system("pause");
    return 0;
}

练习6.8
 "Chaper6.h"
#ifndef _CHAPER6_H_
#define _CHAPER6_H_

int fact(int val);

#endif

练习6.9

练习6.10
void exchange(int* a, int* b)
{
    int c;
    c = *a;
    *a = *b;
    *b = c;
}

练习6.11
void reset(int& i)
{
    i = 0;
}

练习6.12
引用好用,引用直接指向变量本身
void exchange(int& a, int& b)
{
    int c;
    c = a;
    a = b;
    b = c;
}

练习6.13
void f(T) 是将T类型实参变量内容传递给T类型形参变量
void f(T) 是将T类型形参引用绑定T类型实参变量

练习6.14
考点:引用是直接绑定变量本身,因此该改变引用就是改变了实参
变量,如果是要改变变量本身那就可以使用引用,仅是使用实参而不是
需要改变实参,坚决不可以使用引用。
eg:
int arry[5];
//实参传入 arry,sizeof(arry)
void arry_out(int *point, int number)
{
    for (int i = 0; i<number; i++)
    {
        cout << *(point++) << endl;
    }
}
此时并不可以使用引用。引用数组是非法的

练习6.15
(1)s是传入的字符串,类型是IN,防止被改变,occur是记录的次数,类型是OUT
他需要被改变将次数传出去。
(2)只需用到c的内容,没必要使用引用。
(3)s是普通引用可能被误当作左值改变,会出现不想要的结果。
(4)occur将无法改变,次数无法被传出去

练习6.16
没多大用,函数名字还不明确,编译不过去。

练习6.17
#include <iostream>
#include <string>
using namespace std;

bool is_supper(string s)
{
    size_t i = 0;
    while (i < s.size())
    {
        if(isupper(s[i++]))
        {
            return 1;
        }
    }
    return 0;
}

void exchangeUpToLow(string& s)
{
    size_t i = 0;
    while (i < s.size())
    {
        if (islower(s[i]))
        {
            s[i] = toupper(s[i]);
        }
        i++;
    }
}


int main() 
{
    string s = { "a,B,c,d,e,f" };
    cout << is_supper(s) << endl;
    exchangeUpToLow(s);
    cout << s << endl;

    system("pause");
    return 0;
}

练习6.18
(a)
bool compare(const matrix &m1, const matrix &m2);
(b)
vector<int>::iterator change_val(int, vector<int>::iterator);

练习6.19
(a)不合法

练习6.20
在我们不想要改变实参而而本身的时候,设置为const类型引用形参

练习6.21
int filterMax(int a, int* b)
{
    if (a > *b)return a;
    else return *b;
}
指针只能是int* 型的。

练习6.22
#include <iostream>
using namespace std;

void ezchangPoint(int**point_a, int**point_b)
{
    int* c;
    c = *point_a;
    *point_a = *point_b;
    *point_b = c;
}
void ezchangPoint(int* &point_a, int* &point_b)
{
    int* c;
    c = point_a;
    point_a = point_b;
    point_b = c;
}

int main() 
{
    int value1 = 1, value2 = 2;
    int *point1 = &value1, *point2 = &value2;
    ezchangPoint(&point1, &point2);
    ezchangPoint(point1, point2);
    cout << *point1 << " " << *point2 << endl;
    system("pause");
    return 0;
}

练习6.23
#include <iostream>
using namespace std;

void print(int* const pi)
{
    if (pi) 
        cout << *pi << endl;
}

void print(const char* p)
{
    if (p)
        while (*p) cout << *p++;
    cout << endl;
}

void print(const int* beg, const int* end)
{
    while (beg != end) 
        cout << *beg++ << " ";
    cout << endl;
}

void print(const int ia[], size_t size)
{
    for (size_t i = 0; i != size; ++i)
        cout << ia[i] << " ";
    cout << endl;
}

void print(const int(&arr)[2])
{
    for (auto i : arr) 
        cout << i << " ";
    cout << endl;
}

int main() 
{
    int i = 0;
    int j[2] = { 0,1 };
    print(&i);
    print(const_cast<const int (&)[2]> (j));
    system("pause");
    return 0;
}

练习6.24
在函数传参时,数组会退化成指针 const int ia[10],实际上是const int*ia。
因此在参数错误时会造成意想不到的结果。因此改参数为int(&ia)[10]

练习6.25 - 26
#include <iostream>
#include <string>
using namespace std;


int main(int argc, char** argv)
{
    std::string str;
    for (int i = 1; i != argc; ++i) {
        str += argv[i];
        str += " ";
    }
    std::cout << str << std::endl;
    system("pause");
    return 0;
}
本程序不在vs上运行,vs不会向程序传入参数,main函数的第一个
参数argc代表argv的成员个数。
例如:
打开电脑cmd,将可执行文件拖向cmd窗口,再输入 we are good guys.
此时第一个参数是5.第二个参数如下:
argv[0]: 程序路径名
argv[1]:we
argv[2]:are
argv[3]:good
argv[4]:guys.

6.27
initializer_list和vector一样也是一种模板类型,但是initializer_list的
元素永远是常量值,无法改变
#include <iostream>
using namespace std;

void sum(initializer_list<int> il)
{
    int sum = 0;
    for (const auto i: il)
    {
        sum += i;
    }
    cout <<"The sum of num is "<< sum << endl;
}

int main()
{
    sum({ 1, 2, 3});
    system("pause");
    return 0;
}

练习6.28
string&

练习6.29
不应该,initializer_list的元素不可改变

练习6.30

练习6.31
引用的是局部变量

练习6.32
合法

练习6.33
#include <iostream>
#include <vector>

using namespace std;

using Iter = vector<int>::iterator;

void print(Iter beg, Iter end)
{
    if (beg != end)
    {
        cout << *beg << endl;
        print(std::next(beg), end);
    }
}

int main(int argc, char** argv)
{
    vector<int> it(10, 1);
    print(it.begin(), it.end());
    system("pause");
    return 0;
}

练习6.34
递归调用将会多一次,但是结果不变。

练习6.35
使用val--,将会影响到val的值,而不会影响传入的值。
假设val = 3,val--传入的值是3,而不是2.并且会影响后val的值。

练习6.36
string (&fun(void))[10];

练习6.37
using arry_string = string(&)[10];
string arry[10];
arry_string fun(void);
auto fun(void) -> string(&)[10];
decltype((arry)) fun(void);

练习6.38
decltype((odd)) arrPtr(int i)
{
          return (i % 2) ? odd : even;
}

练习6.39
a,b不合法,int和double可以发生转换,因此无法重载匹配
c合法,不存在int*到double*的转换。

练习6.40
(a)合法
(b)wd、bckgrnd没有默认实参。
注:一旦形参出现默认实参,那么它后面的形参都需要默认实参

练习6.41
(a)不合法,无参数传入
(b)合法
(c)合法
注:函数参数的省略,按照函数参数顺序省略。
例如:
void test(int th,char* a = " ",int b = 9,int c = 8){}
test(1,2);//我只想给th和b传入形参
该做法错误,2会被分配给int* a.

练习6.42
应该是给第三个形参赋默认实参。。。
该题略

练习6.43
(a)放源文件,(b)放头文件

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

练习6.45
内联函数会在编译时期展开,目的是快速执行。该函数作为
类成员函数或者其他的常用函数,要求是代码量尽量少,但
会被大量调用。

练习6.46
不行,constexpr函数的形参和返回值必须是字面值类型。
constexpr()被隐式制定为内联函数

练习6.47
#include <iostream>
#include <vector>

using namespace std;


#define NDEBUG

void printVec(vector<int>& vec)
{
#ifndef NDEBUG
    cout << "vector size: " << vec.size() << endl;
#endif
    if (!vec.empty()) {
        auto tmp = vec.back();
        vec.pop_back();
        printVec(vec);
        cout << tmp << " ";
    }
}

int main(int argc, char** argv)
{
    vector<int> vec{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    printVec(vec);
    system("pause");
    return 0;
}

练习6.48
这样assert可能不会被触发

练习6.49
候选函数是符合本次调用的对应重载函数集
可行函数函数是符合筛选条件的候选函数,

练习6.50
(a)不合法,没有符合的函数
(b)符合void f(int)
(c)符合void f(int,int)
(d)符合match void f(double, double = 3.14).

练习6.51
void f()
{
    cout << "f()" << endl;
}

void f(int)
{
    cout << "f(int)" << endl;
}

void f(int, int)
{
    cout << "f(int, int)" << endl;
}

void f(double, double)
{
    cout << "f(double, double)" << endl;
}

练习6.52
(a)char提升为int,
(b)算术类型转换

练习6.53
(a)(b)合法
(c)不合法,顶层const无法传给形参,表达的意义都是char*

练习6.54
int func(int a, int b);

using pFunc1 = decltype(func) *;
typedef decltype(func) *pFunc2;
using pFunc3 = int (*)(int a, int b);
using pFunc4 = int(int a, int b);
typedef int(*)(int a, int b) pFunc5 ;
using pFunc6 = decltype(func);

std::vector<pFunc1> vec1;
std::vector<pFunc2> vec2;
std::vector<pFunc3> vec3;
std::vector<pFunc4*> vec4;
std::vector<pFunc5> vec5;
std::vector<pFunc6*> vec6;

练习6.55
int add(int a,int b) {return a+b;}
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int divide(int a, int b) { return b != 0 ? a / b : 0; }

using pFunc = decltype(func) *;
std::vector<pFunc*> vec = {&add,&subtract,&multiply,&divide};

练习6.56
for (auto f : vec)
          std::cout << f(2, 2) << std::endl;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值