C ++ Primer (第五版) 第六章习题练习

学习笔记所用
本文部分内容参考了:C++Primer第五版——习题答案+详解(完整版)
6.1
见形参和实参的区别是什么

1、函数定义方式不同
形参出现在函数定义中,在整个函数体内都可以使用, 离开该函数则不能使用。
实参出现在主调函数中,进入被调函数后,实参变量也不能使用。 
2、使用原理不同
函数的形参列于函数声明中,在函数定义的函数体内使用。当函数调用时,形参(任何种类的)是一类将被填充的空白或是占位符。
实参是用来填充形参的。当函数被调用时,形参列在函数名后面的括号里。执行函数调用时,实参被传递给形参。
3、传值调用和引用调用不同
传值调用和引用调用指的是用于参数传递过程中的一种机制。传值调用中,只使用了实参的值。传值调用机制里,形参是一个局部变量,其初始值为相应实参的值。在引用调用机制里,将实参的地址传递给形参,从表面上看是以实参变量取代形参,因此任何发生在形参上的改变实际上都发生在实参变量上。

6.2

a: 函数类型与return返回的参数类型不对应
b: 缺少函数类型
c: 形参名不能相同
d: 缺少花括号'{}'

6.3

#include 
using namespace std;

int fact(int n) {
    if (n <= 1) return 1;
    int x = 1;
    for (auto i = 2; i <= n; i++) {
        x *= i;
    }
    return x;
}

int main()
{
    cout << fact(5);
    return 1;
}

6.4

#include 
#include 
using namespace std;

int fact(int n) {
    if (n <= 1) return 1;
    int x = 1;
    for (auto i = 2; i <= n; i++) {
        x *= i;
    }
    return x;
}

int main()
{
    int sr;
    string s;
    do {
        cout << "请输入一个数: ";
        cin >> sr;
        cout << "阶乘为:" << fact(sr)<<endl;
        cout << "是否继续?继续请输入y" << endl;
        cin >> s;
    } while (s[0]=='y');
    return 1;
}

6.5

#include 
#include 
using namespace std;

int jdz(int n) {
    return (n>=0)?n:(-n);
}

int main()
{
    int sr=-5;
    cout << jdz(sr);
    return 1;
}

6.6
解释形参、局部变量和静态局部变量的差别

1)形参的作用域为整个函数体,而普通(非静态)局部变量和静态局部变量的作用域为:从定义处到包含该变量定义的块的结束处。
(2)形参由调用函数时所传递的实参初始化;而普通(非静态)局部变量和静态局部变量通常用初始化式进行初始化,且均在程序执行流程第一次经过该对象的定义语句时进行初始化。静态局部变量的初始化在整个程序执行过程中进行一次。
(3)形参和普通(非静态)局部变量均属自动变量,在每次调用函数时创建,并在函数结束时撤销;而静态局部变量的生命期却跨越了函数的多次调用,它在创建后直到程序结束时才撤销。

6.7

#include 
#include 
using namespace std;

int jdz() {
    static int i = -1;
	i++;
	if (i == 0) return 0;
	else return i;
}

int main()
{
	for (int i = 0; i < 10; i++)
	{
		cout << jdz() << endl;
	}
    return 1;
}

6.8

//头文件
#pragma once
#include 
#include 
using namespace std;
int fact(int n);
int jdz(int n);
//源文件
#include 
#include 
#include "Chapter6.h"
using namespace std;

int jdz() {
    static int i = -1;
	i++;
	if (i == 0) return 0;
	else return i;
}
int fact(int n) {
    if (n <= 1) return 1;
    int x = 1;
    for (auto i = 2; i <= n; i++) {
        x *= i;
    }
    return x;
}

int main()
{
    return 1;
}

6.10

#include 
#include 
using namespace std;

void jh(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}
int main()
{
    int a = 1, b = 2;
    cout << "a=" << a << "b=" << b << endl;
    jh(&a, &b);
    cout << "a=" << a << "b=" << b;
    return 1;
}

6.11

#include 
#include 
using namespace std;

void reset(int &a) {
    a = 0;
}
int main()
{
    int a = 1;
    reset(a);
    cout << a;
    return 1;
}

6.12

#include 
#include 
using namespace std;

void jh(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}
int main()
{
    int a = 1, b = 2;
    cout << "a=" << a << "b=" << b << endl;
    jh(a, b);
    cout << "a=" << a << "b=" << b;
    return 1;
}
//引用的方法更好:1.传入的实参不需要传入地址。2.在函数体修改时也不需要解引用。3.也更容易与不修改实参值区分开,需要修改就加引用,不需要就不加。

6.13

//第一个是值传递,在函数修改,实参不会改变。
//第二个是引用传递,在函数体修改,实参也会跟着改变。

6.14

实参如果是常量就不可以使用引用类型。
如果是变量,使用不使用引用,看目的是否要修改实参的值。

6.15

我们在函数体不想要修改s,所以s是常量引用,与之想法occurs是普通引用
s是引用类型是避免拷贝,occurs是为了修改实参
s如果是普通引用,没有问题
occurs是常量引用会发生错误,达不成目的。

6.16

传入的s是普通引用
优点:可以修改实参。
缺点:会限制函数所能接受的实参类型。完善方法:把他改为常量引用。

6.17

#include 
#include 
#include 
using namespace std;

bool pd(const string &s) {
    for (auto i : s) {
        if (i >= 'A' && i <= 'Z') return true;
    }
    return false;
}
void tolow(string &s) {
    int jl = 'A' - 'a';//求出来A到a的距离
    for (auto &i : s) {
        if (i >= 'A' && i <= 'Z') {
            i -= jl;
        }
    }
}
int main()
{
    string s="adASddsVDad";
    tolow(s);
    cout << s;
    return 1;
}

6.18

bool compare(const matrix m1,const matrix m2);
vector<int>::iterator change_val(int i,vector<int>::iterator i);

6.19

a: 不合法,参数数量不对应
b: 合法
c: 合法
d: 合法

6.20

不需要改变实参的值的时候应该是常量引用。
1:会给函数的调用者一个误导,认为函数可以修改它的实参的值。
2:会限制函数所能接受的实参类型。
3:在调用该函数的时候有可能发生错误。

6.21

#include 
using namespace std;


int bj(int a, int* b) {
    return(a > (*b)) ? a : (*b);
}
int main()
{
    int a = 1, b = 2;
    cout << bj(a, &b);
    return 1;
}

6.22

#include 
using namespace std;


void bj(int *(&a), int* (&b)){
    int* temp = a;
    a = b;
    b = temp;
}
int main()
{
    int a = 1, b = 2;
    int* pa = &a, * pb = &b;
    bj(pa, pb);
    cout << *pa << *pb;
    return 1;
}

6.23

void print(int .int [2]);

6.24

没有问题,循环输出长度为10的整形数组的值。

6.27

#include 
#include 
using namespace std;

void qh(initializer_list<int> a) {
    int sum = 0;
    for (auto i : a) {
        sum += i;
    }
    cout << sum;
}

int main(int argc, char** argv)//实参列表
{
    initializer_list<int> a = { 1,2,3 };
    qh(a);
    return 0;
}

6.28

string &

6.29

不需要,应为initializer_list对象中的元素永远是常量值,不能修改。

6.30

“str_subrange”: 函数必须返回值

6.31

返回的引用不是指向函数外的变量都无效。
返回的引用不是指向函数外的常量都无效。

6.32

没有问题,输出0,1,2,3,4

6.33

#include 
#include 
#include 
using namespace std;

int sv(vector<int>::iterator i, vector<int>::iterator e) {
    
    if (i != e) {
        cout << *i << " ";
        return sv(++i, e);//注意是++i,不是i++       
    }
    return 1;
}

int main(int argc, char** argv)//实参列表
{
    vector<int> a = {1,2,3,4,5};
    sv(a.begin(), a.end());
    return 0;
}

6.34

结果是0

6.35

会先传入val,就会死循环,要么改为--val要么就是val-1;

6.36

string(& fun(vector<string> s))[10];

6.37

//1
typedef string ssS[10];
ssS& func();
//2
auto func()->string(&)[10];
//3
string s[10];
decltype(s) & func();

6.38

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

6.39

a: 非法
b: 非法,除了返回类型都一样。
c: 合理

6.40

b,一个形参被赋予默认值后,它之后的形参都要被赋予默认值。

6.41

a: 非法,没有给ht实参,它没有默认值
b: 合法
c: 合法但是初衷不同,初衷是想把'*'赋值给bckgrnd,实际赋值给了wd

6.43-6.48
感觉自己是个菜鸡(逃),大佬写的很好,可以看一下。C++Primer第五版 第六章习题答案(41~50)
6.49

候选函数:本次调用对应的重载函数集中的函数。
特征:1. 与被调用的函数同名。2. 其声明在调用点可见

可行函数:从候选函数中选出能被这组实参调用的函数。
特征:1.形参数量与本次调用提供的实参数量相等。(含有默认形参,去掉默认形参对应相等也可以)
	 2.每个实参的类型与之对应的形参类型相同。

6.50

a: 不合法,存在二义性
b: 合法
c: 合法
d: 合法

6.51

#include 
#include
#include
using namespace std;

void f() {
	cout << "1" << endl;
}
void f(int) {
	cout << "2" << endl;
}
void f(int,int) {
	cout << "3" << endl;
}
void f(double,double=3.14) {
	cout << "4" << endl;
}

int main(int argc, char** argv)
{
	f();
	f(2);
	f(1, 3);
	f(2.1, 3.2);
	return 0;
}

6.52

a: 3 类型提升
b: 4 类型转换

6.54

#include 
#include
#include
using namespace std;

//1
int sy(int, int) {
	return 1;
}
typedef decltype(sy)* psy;

int main(int argc, char** argv)
{
	vector<psy> a;
 	return 0;
}

6.55-6.56

#include 
#include
#include
using namespace std;

//1
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; }
typedef int(*psy)(int a, int b);

int main(int argc, char** argv)
{
	vector<psy> a = { add,subtract,multiply,divide };
	for (auto i : a) {
		cout << i(4, 2) << endl;
	}
 	return 0;
}

你可能感兴趣的:(C++,Primer学习笔记)