C++ Primer(第五版)第6章答案

第6章 函数


练习6.1

实参是函数调用的实际值,是形参的初始值

练习6.2

  • (a)返回类型不匹配
int f()
{
    int s;
    //...
    return s;
}
  • (b)无返回类型
void f2(int i) {/*...*/}
  • (c)形参不能同名
int clac(int v1,int v2) {/*...*/}
  • (d)函数体要用花括号括起来
double square(double x) {return x*x;}

练习6.3

#include 
using namespace std;
int fact(int val);
int main()
{
 cout << fact(5) << endl;
 return 0;
}
int fact(int val)
{
 int ret = 1;
 while (val > 1)
 {
  ret *= val--;
 }
 return ret;
}

练习6.4

#include 
using namespace std;
int fact(int val);
int main()
{
 cout << "Please enter a number: " << endl;
 int i = 0;
 cin >> i;
 cout << fact(i);
}
int fact(int val)
{
 int ret = 1;
 while (val > 1)
 {
  ret *= val--;
 }
 return ret;
}

练习6.5

#include 
using namespace std;
double myAbs(double val);
int main()
{
 cout << "Please enter a number: " << endl;
 double i = 0;
 cin >> i;
 cout << myAbs(i);
}
double myAbs(double val)
{
 if (val > 0)
  return val;
 else
  return - 1 * val;
}

练习6.6

形参定义在函数形参列表里面;局部变量定义在代码块里面;局部静态变量在程序的执行路径第一次经过对象定义语句时初始化,并且直到程序终止时才被销毁

#include 
#include 
using namespace std;
void fun(int val);
int main()
{
 fun(3);
 fun(8);
 fun(5);
 fun(7);
}
void fun(int val)
{
 static int p = 0;
 int ret = val;
 while (ret > 1)
 {
  cout << "*";
  --ret;
 }
 
 cout << " " << ++p <<" Times"<< endl;
}

练习6.7

#include 
using namespace std;
int pplus();
int main()
{
 cout << pplus() << endl;
 cout << pplus() << endl;
 cout << pplus() << endl;
}
int pplus()
{
 static int p = 0;
 return p++;
}

练习6.8

Chapter6.h文件

int fact(int val);
double myAbs(double val);

练习6.9

fact.cpp文件

#include "Chapter6.h"
int fact(int val)
{
 int ret = 1;
 while (val > 1)
 {
  ret *= val--;
 }
 return ret;
}

factMain.cpp文件

#include 
#include "Chapter6.h"
using namespace std;

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

练习6.10

#include 
using namespace std;
void mySwap(int* a, int* b);
int main()
{
 int i = 99, j = 1;
 cout << i << " " << j << endl;
 mySwap(&i, &j);
 cout << i << " " << j << endl;
 return 0;
}
void mySwap(int* a, int* b)
{
 int temp = 0;
 temp = *a;
 *a = *b;
 *b = temp;
}

练习6.11

#include 
using namespace std;
void reset(int& val);
int main()
{
 int i = 100;
 cout << i << endl;
 reset(i);
 cout << i;
 return 0;
}
void reset(int& val)
{
 val = 0;
}

练习6.12

#include 
using namespace std;
void swap(int& a, int& b);
int main()
{
 int i = 999, j = 888;
 cout << i << " " << j << endl;
 swap(i, j);
 cout << i << " " << j << endl;
 return 0;
}
void swap(int& a, int& b)
{
 a = a + b;
 b = a - b;
 a = a - b;
}

引用更易于使用,更加简洁

练习6.13

  • void f(T)的参数通过值传递,在函数中 T 是实参的副本,改变T不会影响到原来的实参
  • void f(T&)的参数通过引用传递,在函数中的T是实参的引用,T的改变也就是实参的改变

练习6.14

交换两个整数的值时,形参应该是引用类型,当实参是右值时,形参不应该是引用类型

练习6.15

s是常量引用是因为,string字符串可能很大,使用引用效率较高,而函数并不会改变s,故使用常量。c是普通char,是因为c可能会是一个右值,故不能是引用。occurs是普通引用是因为,函数要改变它,故用引用,也因此不能是常量。

练习6.16

常量字符串和字符串字面值无法作为该函数的实参,改为

bool is_empty(const string &s) {return s.empty();}

练习6.17

#include 
#include 
using namespace std;
bool isBig(const string &s);
string toSmall(string &s);
int main()
{
 if (isBig("huShun"))
 {
  cout << "yes" << endl;
 }
 else
 {
  cout << "no" << endl;
 }
 string s = "HUsHuN";
 cout << toSmall(s);
 return 0;
}
bool isBig(const string &s)
{
 for (char ch : s)
 {
  if (isupper(ch))
   return true;
 }
 return false;
}
string toSmall(string &s)
{
 for (char &ch : s)
 {
  ch = tolower(ch);
 }
 return s;
}

不一样,isBig不改变s,为常量引用,toSmall改变s,为普通引用

练习6.18

  • (a)bool compare(matrix&,matrix&);
  • (b)vector::iterator change_val(int,vector::iterator);

练习6.19

  • (a)非法,形参数量不匹配
  • (b)合法
  • (c)合法
  • (d)合法

练习6.20

应该尽量将引用形参设为常量引用,除非有明确的目的是为了改变这个引用变量。如果形参应该是常量引用,而我们将其设为了普通引用,那么常量实参将无法作用于普通引用形参

练习6.21

#include 
using namespace std;
int whoBig(const int i, const int *j);
int main()
{
 int a = 100, b = 108;
 cout << whoBig(a, &b);
 return 0;
}
int whoBig(const int i, const int *j)
{
 return i > *j ? i : *j;
}

应该是const int*

练习6.22

#include 
using namespace std;
void swapAdd(int *&p1, int *&p2);
int main()
{
 int i = 999, j = 0, *p1 = &i, *p2 = &j;
 cout << *p1 << " " << *p2 << endl;
 swapAdd(p1, p2);
 cout << *p1 << " " << *p2 << endl;
}
void swapAdd(int *&p1, int *&p2)
{
 int *temp = p1;
 p1 = p2;
 p2 = temp;
}

练习6.23

#include 
using namespace std;
void print(const int i);
void print(const int *arr, int i);
int main()
{
 int i = 0, j[8] = { 0,1,9,14,45 };
 print(i);
 cout << endl;
 print(j,8);
 return 0;
}
void print(const int i)
{
 cout << i;
}
void print(const int *arr, int i)
{
 for (int n = 0; n < i; ++n)
  cout << arr[n] << " ";
}

练习6.24

当数组作为实参的时候,会被自动转换为指向首元素的指针。因此函数形参接受的是一个指针。如果要让这个代码成功运行,可以将实参改为数组的引用

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

练习6.25

#include 
#include 

int main(int argc, char **argv)
{
 std::string str;
 for (int i = 1; i != argc; ++i)
  str += std::string(argv[i]) + " ";

 std::cout << str << std::endl;
 return 0;
}

练习6.26

#include 
#include 

int main(int argc, char **argv)
{
 std::string str;
 for (int i = 1; i != argc; ++i)
  str += std::string(argv[i]) + " ";

 std::cout << str << std::endl;
 return 0;
}

练习6.27

#include 
using namespace std;
int  sum(initializer_list il);
int main()
{
 cout << sum({ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
 return 0;
}
int sum(initializer_list il)
{
 int sum = 0;
 for (auto beg = il.begin(); beg != il.end(); ++beg)
  sum += *beg;
 return sum;
}

练习6.28

const string&

练习6.29

应该使用常量引用类型。initializer_list对象中的元素都是常量,我们无法修改initializer_list对象中的元素的值

练习6.30

编译器错误信息:
ex6_30

练习6.31

当返回局部变量的引用时无效。当我们希望返回的对象被修改时,返回常量的引用无效。

练习6.32

合法,get函数返回数组各元素的引用

练习6.33

#include 
#include 
using namespace std;
typedef vector::const_iterator itc;
void print(itc first,itc last);
int main()
{
 vector ivec = { 0,9,8 };
 print(ivec.cbegin(),ivec.cend());
 return 0;
}
void print(itc first, itc last)
{
 if (first == last)
  return;
 cout << *first << " ";
 print(++first, last);
}

练习6.34

如果val小于0,则递归调用永远不会结束

练习6.35

val–返回改变前的值的副本,即一直传入相同的值来调用函数,函数永不结束

练习6.36

string (&func())[10];

练习6.37

  • 类型别名:using str_arr=string[10];str_arr& func();
  • 尾置返回类型:auto func()->string(&)[10];
  • decltype关键字:string s[10];decltype(s)& func();

尾置返回类型更好,更简洁明了

练习6.38

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

练习6.39

  • (a)非法,顶层const无法区分形参
  • (b)非法,不允许两个函数除返回类型外其他所有的要素都相同
  • (c)合法,接受一个double型指针,返回一个double型指针

练习6.40

  • (a)合法
  • (b)非法,一旦某个形参被赋予了默认值,它后面的所有形参都必须有默认值

练习6.41

  • (a)非法,ht需要实参
  • (b)合法
  • (c)合法,但有违初衷,'*'会转换为int型赋给wd

练习6.42

#include 
#include 
using namespace std;
string make_plural(int ctr, const string &word, const string &ending = "s")
{
 return (ctr > 1) ? word + ending : word;
}
int main()
{
 cout<< make_plural(1, "success", "es") << " "
  << make_plural(1, "failure") << endl;
 cout<< make_plural(2, "success", "es") << " "
  << make_plural(2, "failure") << endl;
 return 0;
}

练习6.43

  • (a)头文件,这是一个内联函数的定义
  • (b)头文件,这是一个函数声明

练习6.44

inline bool is_shorter(const string &lft, const string &rht) 
{
  return lft.size() < rht.size();
}

练习6.45

一般来说,内联机制用于优化规模小、流程直接、频繁调用的函数

练习6.46

不能。constexpr函数的返回值类型及所有形参都得是字面值类型

练习6.47

#include 
#include 
using namespace std;
using Iter = vector::const_iterator;

#define NDEBUG

void print(Iter first, Iter last)
{
#ifndef NDEBUG
 cout << "vector size: " << last - first << endl;
#endif
 if (first == last)
  return;
 cout << *first << " ";
 print(++first, last);

}

int main()
{
 vector vec{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 print(vec.cbegin(), vec.cend());
 return 0;
}

练习6.48

不合理

练习6.49

候选函数:与被调用函数同名,其声明在调用点可见
可行函数:其形参数目与本次调用提供的实参数量相等,每个实参的类型与对应的形参类型相同,或者能转换成形参的类型

练习6.50

首先对这四个函数编号依次为1,2,3,4号

  • (a)3号和4号,非法,二义性
  • (b)2号和4号,合法,2号最匹配
  • (c)3号和4号,合法,3号最匹配
  • (d)3号和4号,合法,4号最匹配

练习6.51

#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()
{
 f(2.56, 42);
 f(42);
 f(42, 0);
 f(2.56, 3.14);
 return 0;
}

练习6.52

  • (a)类型提升
  • (b)算术类型转换

练习6.53

  • (a)合法
  • (b)合法
  • (c)非法,实参类型会忽略顶层const

练习6.54

int fun(int,int);
vector v;

练习6.55

#include 
#include 

using namespace std;

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; }

int main()
{
 int func(int, int);
 vector v;
 v.push_back(add);
 v.push_back(subtract);
 v.push_back(multiply);
 v.push_back(divide);

 for (auto i : v)
 {
  cout << i(6, 2) << " "; // 8, 4, 12, 3
 }
 cout << endl;
 return 0;
}

练习6.56

8, 4, 12, 3

你可能感兴趣的:(C++,Primer(第五版)答案,c++,算法,开发语言)