练习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,÷};
练习6.56
for (auto f : vec)
std::cout << f(2, 2) << std::endl;