P184
练习6.1
对于实参和形参的区别,可以简单的理解为:
形参:函数定义的时的参数—也就是无赋值的变量(作用是说明参数的类型)
实参:调用函数时使用的参数—也就是有赋值的变量(函数实际操作的对象)
练习6.2
- 返回类型不匹配;
- 函数没有表明返回类型
- 两个v1,参数应不同
- 需要使用花括号
练习6.3
#include <iostream>
using namespace std;
int fact(int n)
{
int ret = 0;
for (int i = 1; i <= n; ++i)
{
ret += i;
}
return ret;
}
int main()
{
cout << fact(10) << endl;
return 0;
}
练习6.4
#include <iostream>
using namespace std;
int fact(int n)
{
int multi = n;
while (--n)
{
multi*= n;
}
return multi;
}
int main()
{
int a;
cout << "请输入一个数字:" << endl;
cin >> a;
if (a > 0)
{
cout << a << "的阶乘为:" << fact(a) << endl;
}
else {
cout << "无" << endl;
}
return 0;
}
练习6.5
#include <iostream>
#include<string>
using namespace std;
int fact(int n)
{
n = abs(n);
return n;
}
int main()
{
int a;
cout << "请输入一个数字:"<< endl;
cin >> a;
cout <<"|"<< a << "| =" << fact(a) << endl;
return 0;
}
P185
练习6.6
形参是局部变量的一种。
形参和函数体内部定义的变量统称为局部变量。
局部静态变量的生命周期贯穿函数调用及之后的时间。
#include<iostream>
using namespace std;
// example
size_t count_add(int n) // n is a parameter and local variable.
{
static size_t ctr = 0; // ctr is a static variable.
ctr += n;
return ctr;
}
int main()
{
for (size_t i = 0; i != 10; ++i) // i is a local variable.
cout << count_add(i) << endl;
return 0;
}
练习6.7
#include<iostream>
using namespace std;
int hanshu()
{
static int a = 0;
return a++;
}
int main()
{
for (int i = 0; i < 2;++i)
cout << hanshu() << endl;
return 0;
}
P186
联习6.8
#pragma once
#include <iostream>
using namespace std;
int fact(int n);
P187
练习6.9
//Chapter6.h
#ifndef _6_9_h
#define _6_9_h
int func();
#endif
//fact.cc
#include "6_9.h"
int func()
{
static int x;
return ++x;
}
//factMain.cc
#include <iostream>
#include "6_9.h"
int main()
{
std::cout << func() << std::endl;
return 0;
}
P188
练习6.10
#include <iostream>
using namespace std;
void func(int *x, int *y)
{
int p = *x;
*x = *y;
*y = p;
}
int main()
{
int n = 10, m = 20;
func(&n, &m);
cout << n << " " << m << endl;
return 0;
}
P190
练习6.11
#include <iostream>
using namespace std;
void reset(int &x)
{
x = 0;
}
int main()
{
int x = 30;
reset(x);
cout << x << endl;
return 0;
}
练习6.12
#include <iostream>
using namespace std;
void func(int& x, int& y)
{
int p = x;
x = y;
y = p;
}
int main()
{
int n = 10, m = 20;
func(n, m);
cout << n << " " << m << endl;
return 0;
}
引用更易于使用:
- 传参时无需加取地址符&,方便阅读;
- 被调用函数内部修改参数值无需解引用;
- 引用效率更高;
练习6.13
一个是值传递,一个是引用传递。
练习6.14
- 返回多个值使用引用类型;
- 参数数据类型很大时需要使用引用类型;
- 只改变实参的值而不改变形参的值时不能使用引用类型;
练习6.15
- const string &s 避免拷贝且不用改变s的值,故是常量引用;
- char c 不需要改变c的值且char类型占空间更小,故最好不用引用;
- string::sizetype &occurs 需要改变occurs的值,故是普通引用;
- 若s是普通引用:有可能改变其值,若实参定义为常量则无法传递;
- occurs为常量引用:若改变其值会报错;
P192
练习6.16
// 1.给调用者造成可以修改实参的误导
//2.不能传常量
//改善:加 const
bool is_empty(const string &s) { return s.empty(); }
练习6.17
#include <iostream>
#include <string>
using namespace std;
bool my_isupper(const string& s)
{
for (const auto& c : s)
{
if (isupper(c))
{
cout << "is upper" << endl;
return true;
}
}
cout << "is not upper" << endl;
return false;
}
void my_toupper(string& s)
{
for (auto& c : s)
{
c=toupper(c);
}
cout << s << endl;
}
int main()
{
string s("aA bB cC");
my_isupper(s);
my_toupper(s);
return 0;
}
P193
练习6.18
bool compare(const matrix&, const matrix&);
vector<int>::iterator change_val(int, vector<int>::iterator);
练习6.19
- a 形参个数不匹配;
- b合法 常量引用传递 值传递;
- c 合法 值传递;
- d vec 不是 vector<int> 时不合法;
练习6.20
不需改变实参的值时,应设为为常量引用;实参为常量时,应设为常量引用;
若实参为常量会报错;
练习6.21
#include <iostream>
#include <string>
using namespace std;
int compare(int a, const int* b)
{
if (a > *b)
return a;
else
return *b;
}
int main()
{
int a = 1;
int b = 2;
cout<<compare(a, &b)<<endl;
return 0;
}
6.22
#include <iostream>
#include <string>
using namespace std;
void change(int* pa, int* pb)
{
int temp;
temp = *pa;
*pa = *pb;
*pb = temp;
}
int main()
{
int a = 1;
int b = 2;
change(&a, &b);
cout << "a = " << a << " b = " << b << endl;
return 0;
}
6.23
#include <iostream>
#include <string>
using namespace std;
void print(const int *beg,const int *end)
{
while (beg != end)
{
cout << *beg++ << endl;
}
}
void print(const int& i)
{
cout << i << endl;
}
int main()
{
int i = 0;
int j[2] = { 0,1 };
print(i);
print(begin(j), end(j));
return 0;
}
6.24
当数组作为实参的时候,会被自动转换为指向首元素的指针。因此函数形参接受的是一个指针。如果要让这个代码成功运行,可以将实参改为数组的引用
void print(const int (&ia)[10])
{
for (size_t i = 0; i != 10; ++i)
cout << ia[i] << endl;
}
6.25
#include <iostream>
#include <string>
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 <iostream>
#include <string>
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 <iostream>
#include <string>
using namespace std;
int Sum(initializer_list<int> il)
{
int sum = 0;
for (const auto& i : il)
sum += i;
return sum;
}
int main()
{
cout << Sum({1,2,3}) << endl;
return 0;
}
6.28
const std::string&
6.29
应该,因为initializer_list中的对象都是常量。
6.30
6.31
返回的引用时局部对象的引用,返回的常量引用是局部常量对象的引用时。
6.32
合法,将数组元素赋值为对应的下标。
6.33
#include <iostream>
#include <vector>
using namespace std;
void print(vector<int>::const_iterator beg, vector<int>::const_iterator end)
{
if (beg!= end)
{
cout << *beg << " ";
print(++beg, end);
}
else
{
cout << endl;
return;
}
}
int main()
{
vector<int> ivec = { 1,2,3 };
print(ivec.begin(), ivec.end());
return 0;
}
6.34
如果实参为大于等于0,函数将会多乘以一个1。
6.35
val--
会返回未修改的val
内容,使程序陷入无限循环。
6.37
string(&func())[10];
6.38
using arrT=string[10];
arrT &func();
auto func()->string(&)[10];
string str[10];
decltype(str) &func();
using最好,易读。
6.39
a)合法,但是重复声明;
b)非法,返回值类型不同;
c)合法。
6.40
a)合法;
b)非法,前面的形参有默认值,后面所有的形参都要有默认值;
6.41
a)非法,形参ht无默认值,需要传参;
b)合法;
c)合法,但初衷不符,形参wd被实参‘*’转为int赋值;
6.42
#include <iostream>
#include <string>
using std::string;
string make_plural(size_t ctr, const string& word, const string& ending = "s")
{
return (ctr > 1) ? word + ending : word;
}
int main()
{
std::cout << make_plural(1, "success", "es") << std::endl;
std::cout << make_plural(1, "failure") << std::endl;
std::cout << make_plural(2, "success", "es") << std::endl;
std::cout << make_plural(2, "failure") << std::endl;
}
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函数的返回值类型及所有形参都应是字面值类型;
6.47
#include <iostream>
#include <vector>
//#define NDEBUG
using namespace std;
void print(vector<int>::const_iterator beg, vector<int>::const_iterator end)
{
#ifndef NDEBUG
cout << "vector size: " << end - beg <<" func :"<< __func__ << " file :" << __FILE__ << " line :"
<< __LINE__ << " time :" << __TIME__ << " date :" << __DATE__ << endl;
#endif
if (beg != end)
{
cout << *beg << " ";
print(++beg, end);
}
else
{
cout << endl;
return;
}
}
int main()
{
vector<int> ivec = { 1,2,3 };
print(ivec.begin(), ivec.end());
return 0;
}
6.48
循环含义:当输入的string等于sought时,停止循环。
assert(cin)用在这里语法正确,但不太合理;
此处while循环后,若标准输入流中不为0则程序继续,而此处while循环保证了标准输入流中不为0;
在windows下输出在调试窗口输入ctrl+z,可触发assert(cin)使程序终止,但ctrl+z本身就可以终止程序。
6.49
候选函数:本次调用对应的重载函数集中的函数,与被调用函数同名,声明在调用点可见;
可行函数:候选函数中选出能被这组实参调用的函数,形参数量与本次调用提供的实参数量相等,每个实参的类型与对应的形参类型相同。
6.50
a) 不合法,有二义性;
b) void f(int);
c) void f(int,int);
d) void f(double,double=3.14);
6.51
略。
6.52
a) 等级3,类型提升;
b) 等级4,算术类型转换;
6.53
a) 合法;
b) 合法;
c) 合法,顶层const,声明重复(可以重复声明,不可重复定义)。
6.54
int fun(int, int);
vector<decltype(fun)*> vfun;
6.55 & 6.56
#include <iostream>
#include <vector>
using namespace std;
int fun(int, int);
vector<decltype(fun)*> vfun;
int f_add(int a, int b)
{
return a + b;
}
int f_sub(int a, int b)
{
return a - b;
}
int f_multib(int a, int b)
{
return a * b;
}
int f_divis(int a, int b)
{
if (b)
return a / b;
else
return 0;
}
int main()
{
vfun.push_back(f_add);
vfun.push_back(f_sub);
vfun.push_back(f_multib);
vfun.push_back(f_divis);
for (const auto& i : vfun)
cout << i(3, 2) << endl;
return 0;
}