C++ Primer 第 5 版 第 6 章习题答案

文章目录

  • 6.1
  • 6.2
  • 6.3
  • 6.4
  • 6.5
  • 6.6
  • 6.7
  • 6.8
  • 6.10
  • 6.11
  • 6.12
  • 6.13
  • 6.14
  • 6.15
  • 6.16
  • 6.17
  • 6.18
  • 6.19
  • 6.20
  • 6.21
  • 6.22
  • 6.23
  • 6.24
  • 6.25
  • 6.26
  • 6.27
  • 6.28
  • 6.29
  • 6.30
  • 6.31
  • 6.32
  • 6.33
  • 6.34
  • 6.35
  • 6.36
  • 6.37
  • 6.38
  • 6.39
  • 6.40
  • 6.41
  • 6.42
  • 6.43
  • 6.44
  • 6.45
  • 6.46
  • 6.47
  • 6.48
  • 6.49
  • 6.50
  • 6.51
  • 6.52
  • 6.53
  • 6.54
  • 6.55
  • 6.56

6.1

形参出现在函数定义的地方,形参列表可以包含 0 个、1 个或多个形参,多个形参之间以逗号分隔。形参规定了一个函数所接受数据的类型和数量。

实参出现在函数调用的地方,实参的数量与形参一样多。实参的主要作用是初始化形参,并且这种初始化过程是一一对应的,即第一个实参初始化第一个形参、第二个实参初始化第二个形参,以此类推。实参的类型必须与对应的形参类型匹配。

6.2

(a)是错误的,因为函数体返回的结果类型是 string,而函数的返回值类型是 int,二者不一致且不能自动转换
(b)是错误的,因为函数缺少返回值类型
(c)是错误的,同一个函数如果含有多个形参,则这些形参的名字不能重复;另外,函数体左侧的花括号丢失了
(d)是错误的,因为函数体必须放在一对花括号内。

6.3

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

6.4

#include <iostream>
using namespace std;
int fact(int n){int sum{1};while (n>1){sum*=n;--n;}
}
int main() {int n;cout<<"请输入一个数字:";cin>>n;cout<< n<<"的阶乘是:" <<fact(n) <<endl;return 0;
}

6.5

#include <iostream>
using namespace std;unsigned m_abs(int n){if(n>=0)return n;elsereturn -n;
}
int main() {int n;cout<<"请输入一个数字:";cin>>n;cout<< n<<"的绝对值是:" <<m_abs(n) <<endl;return 0;
}

6.6

形参和定义在函数体内部的变量统称为局部变量,它们对函数而言是局部的,仅在函数的作用域内可见。函数体内的局部变量又分为普通局部变量和静态局部变量,对于形参和普通局部变量来说,当函数的控制路径经过变量定义语句时创建该对象,当到达定义所在的块末尾时销毁它。我们把只存在于块执行期间的对象称为自动对象。这几个概念的区别是:

形参是一种自动对象,函数开始时为形参申请内存空间,我们用调用函数时提供的实参初始化形参对应的自动对象。
普通变量对应的自动对象也容易理解,我们在定义该变量的语句处创建自动对象,如果定义语句提供了初始值,则用该值初始化;否则,执行默认初始化。当该变量所在的块结束后,变量失效。
局部静态变量比较特殊,它的生命周期贯穿函数调用及之后的时间。局部静态变量对应的对象称为局部静态对象,它的生命周期从定义语句处开始,直到程序结束才终止。

#include <iostream>
using namespace std;// 该函数同时使用了形参、普通局部变量和静态局部变量
double myADD(double val1, double val2) {    // val1 和 val2 是形参double result = val1 + val2;    // result 是普通局部变量static unsigned iCnt = 0;       // iCnt 是静态局部变量++iCnt;cout << "该函数已经累计执行了 " << iCnt << " 次" << endl;return result;
}int main() {double num1, num2;cout << "请输入两个数:";while (cin >> num1 >> num2) {cout << num1 << " 与 " << num2 << " 的求和结果是:"<< myADD(num1, num2) << endl;cout << "请输入两个数:";}return 0;
}

6.7

#include <iostream>using namespace std;unsigned func(){static int n{0};return n++;
}int main() {for (int i = 0; i < 10; ++i) {cout<< func()<<"次" <<endl;}return 0;
}

6.8

#ifndef CHAPTER6
#define CHAPTER6int fact(int n);
unsigned m_abs(int n);#endif

6.10

#include <iostream>using namespace std;void swap(int *p1, int *p2) {int tmp = *p1;*p1 = *p2;*p2 = tmp;
}int main() {int a=1,b=2;cout<<"a="<<a<<" "<<"b="<<b <<endl;swap(&a,&b);cout<<"a="<<a<<" "<<"b="<<b <<endl;return 0;
}

6.11

#include <iostream>using namespace std;void reset(int &n) {n = 50;
}int main() {int n = 100;cout << "调用函数之前n的值为" << n << endl;reset(n);cout << "调用函数之后n的值为" << n << endl;return 0;
}

6.12

#include <iostream>using namespace std;void swap(int &p1, int &p2) {int tmp = p1;p1 = p2;p2 = tmp;
}int main() {int a=1,b=2;cout<<"a="<<a<<" "<<"b="<<b <<endl;swap(a,b);cout<<"a="<<a<<" "<<"b="<<b <<endl;return 0;
}

与使用指针相比,使用引用交换变量的内容从形式上看更简单一些,并且无须额外声明指针变量,也避免了拷贝指针的值。

6.13

void f(T) 的形参采用的是传值方式,也就是说,实参的值被拷贝给形参,形参和实参是两个相互独立的变量,在函数 f 内部对形参所做的任何改动都不会影响实参的值。

void f(&T) 的形参采用的是传引用方式,此时形参是对应的实参的别名,形参绑定到初始化它的对象。如果我们改变了形参的值,也就是改变了对应实参的值。

6.14

基于对引用传递优势的分析,我们可以举出几个适合使用引用类型形参的例子:

当函数的目的是交换两个参数的内容时应该使用引用类型的形参;
当参数是 string 对象时,为了避免拷贝很长的字符串,应该使用引用类型。
在其他情况下可以使用值传递的方式,而无须使用引用传递,例如求整数的绝对值或者阶乘的程序。

6.15

ind_char 函数的三个参数的类型设定与该函数的处理逻辑密切相关,原因分别如下:

对于待查找的字符串 s 来说,为了避免拷贝长字符串,使用引用类型;同时我们只执行查找操作,无须改变字符串的内容,所以将其声明为常量引用。
对于待查找的字符 c 来说,它的类型是 char,只占 1 字节,拷贝的代价很低,而且我们无须操作实参在内存中实际存储的内容,只把它的值拷贝给形参即可,所以不需要使用引用类型。
对于字符出现的次数 occurs 来说,因为需要把函数内对实参值的更改反映在函数外部,所以必须将其定义成引用类型;但是不能把它定义成常量引用,否则就不能改变所引的内容了。

6.16

一是容易给使用者一种误导,即程序允许修改变量 s 的内容;二是限制了该函数所能接受的参数类型,我们无法把 const 对象、字面值常量或者需要进行类型转换的对象传递给普通的引用形参

6.17

#include <iostream>
#include<string>
using namespace std;
bool isICapital(const string&s){for(auto c:s){if (c>='A'&&c<='Z')return true;}return false;
}
void change(string&s){for(auto &c:s){if (c>='A'&&c<='Z')c+=32;}
}
int main() {string s ="AcasdAZ";change(s);cout<< s <<endl;cout<< isICapital(s) <<endl;return 0;
}

第一个函数的任务是判断 string 对象中是否含有大写字母,无须修改参数的内容,因此将其设为常量引用类型。第二个函数需要修改参数的内容,所以应该将其设定为非常量引用类型。

6.18

bool compare(const matrix &, const matrix &);
vector<int>::iterator change_val(int, vector<int>::iterator);

6.19

(a)是非法的,函数的声明只包含一个参数,而函数的调用提供了两个参数,因此无法编译通过。

(b)是合法的,字面值常量可以作为常量引用形参的值,字符 a 作为 char 类型形参的值也是可以的。

(c)是合法的,66 虽然是 int 类型,但是在调用时自动转换为 double 类型。

(d)是合法的,vec.begin() 和 vec.end() 的类型都是形参所需的 vector::iterator ,第三个实参 3.8 可以自动转换为形参所需的 int 类型。

6.20

当函数对参数所做的操作不同时,应该选择适当的参数类型。如果需要修改参数的内容,则将其设置为普通引用类型;否则,如果不需要对参数内容做任何更改,最好设为常量引用类型。

6.21

#include <iostream>
#include<string>using std::cout,std::endl,std::string;inline int comp(const int x,const int *p){return (x>*p)?x:(*p);
}int main() {int x = 50;int y = 500;int *p = &x;cout<< comp(y,p) <<endl;return 0;
}

6.22

第一个函数以值传递的方式使用指针,所有改变都局限于函数内部,当函数执行完毕后即不会改变指针本身的值,也不会改变指针所指的内容。

第二个函数同样以值传递的方式使用指针,但是函数内部通过解引用的方式直接访问内存并修改了指针所指的内容。

第三个函数的参数形式是 int &* ,其含义是(从右向左理解),该参数是一个引用,引用的对象是内存中的一个 int 指针,使用这种方式可以把指针当成对象,交换指针本身的值。需要注意的是,最后一个函数既然交换了指针,当然解引用该指针所得的结果也会相应发生改变。

#include <iostream>
using namespace std;// 该函数既不交换指针,也不交换指针所指的内容
void SwapPointer1(int *p, int *q) {int *temp = p;p = q;q = temp;cout << "p 的值是:" << p << ",q 的值是:" << q << endl;
}// 该函数交换指针所指的内容
void SwapPointer2(int *p, int *q) {int temp = *p;*p = *q;*q = temp;cout << "p 的值是:" << p << ",q 的值是:" << q << endl;
}// 该函数交换指针本身的值,即交换指针所指的内存地址
void SwapPointer3(int *&p, int *&q) {int *temp = p;p = q;q = temp;cout << "p 的值是:" << p << ",q 的值是:" << q << endl;
}int main() {int a = 5, b = 10;int *r = &a, *s = &b;cout << "交换前:" << endl;cout << "r 的值是:" << r << ",s 的值是:" << s << endl;cout << "r 所指的值是:" << *r << ",s 所指的值是:" << *s << endl;SwapPointer1(r, s);cout << "交换后:" << endl;cout << "r 的值是:" << r << ",s 的值是:" << s << endl;cout << "r 所指的值是:" << *r << ",s 所指的值是:" << *s << endl;cout << endl;a = 5, b = 10;r = &a, s = &b;cout << "交换前:" << endl;cout << "r 的值是:" << r << ",s 的值是:" << s << endl;cout << "r 所指的值是:" << *r << ",s 所指的值是:" << *s << endl;SwapPointer2(r, s);cout << "交换后:" << endl;cout << "r 的值是:" << r << ",s 的值是:" << s << endl;cout << "r 所指的值是:" << *r << ",s 所指的值是:" << *s << endl;cout << endl;a = 5, b = 10;r = &a, s = &b;cout << "交换前:" << endl;cout << "r 的值是:" << r << ",s 的值是:" << s << endl;cout << "r 所指的值是:" << *r << ",s 所指的值是:" << *s << endl;SwapPointer3(r, s);cout << "交换后:" << endl;cout << "r 的值是:" << r << ",s 的值是:" << s << endl;cout << "r 所指的值是:" << *r << ",s 所指的值是:" << *s << endl;return 0;
}

6.23

#include <iostream>
using std::cout,std::endl,std::string;void print(const int x){cout<< x <<endl;
}void print(const int*x,const size_t len){for (int i = 0; i < len; ++i)cout<< *(x+i) <<" ";cout<<endl;}
int main() {int i = 0,j[2]={0,1};print(i);print(j,2);return 0;
}

6.24

上述 print 函数的定义存在一个潜在的风险,即虽然我们期望传入的数组维度是 10,但实际上任意维度的数组都可以传入。如果传入的数组维度较大,print 函数输出数组的前 10 个元素,不至于引发错误;相反,如果传入的数组维度不足 10,则 print 函数将强行输出一些未定义的值

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

6.25

#include <iostream>
using namespace std;int main(int argc, char *argv[]) {string str;for (int i = 0; i != argc; ++i) {str += argv[i];}cout << str << endl;return 0;
}

在这里插入图片描述

6.26

#include <iostream>
using namespace std;int main(int argc, char *argv[]) {for (int i = 0; i != argc; ++i)cout<< "arg["<<i<<"]="<<argv[i] <<endl;return 0;
}

在这里插入图片描述

6.27

#include <iostream>
#include<initializer_list>
using namespace std;int sum(const initializer_list<int>i){int s{0};for (auto beg = i.begin(); beg!=i.end();++beg)s+=(*beg);return s;
}
int main() {cout<< sum({1,2,3})<<endl;cout<< sum({1,1,1,1,1})<<endl;return 0;
}

6.28

initializer_list 的所有元素类型都是 string,因此 const auto &elem : il 推断得到的 elem 的类型是 const string & 。使用引用是为了避免拷贝长字符串,把它定义为常量的原因是我们只需读取字符串的内容,不需要修改它(另外, initializer_list 列表中的元素原本属性就是 const,想修改也无法修改)

6.29

引用类型的优势主要是可以直接操作引用的对象以及避免拷贝较为复杂的类型对象和容器对象。因为 initializer_list 对象的元素永远是常量值,所以我们不可能通过设定引用类型来更改循环控制变量的内容。只有当 initializer_list 对象的元素类型是类类型或容器类型(比如 string)时,才有必要把范围 for 循环的循环控制变量设为引用类型。

6.30

#include <iostream>
using namespace std;// 因为含有不正确的返回值,所以这段代码无法通过编译
bool str_subrange(const string &str1, const string str2) {// 大小相同:此时用普通的相等性来判断结果作为返回值if (str1.size() == str2.size())return str1 == str2;        // 正确:== 运算符返回布尔值// 得到较短 string 对象大小auto size = (str1.size() < str2.size())? str1.size() : str2.size();// 检查两个 string 对象的对应字符是否相等,以较短的字符长度为限for (decltype(size) i = 0; i != size; ++i) {if (str1[i] != str2[i])return;                 // 错误 #1:没有返回值,编译器将报告这一错误}// 错误 #2:控制流可能尚未返回任何值就结束了函数的执行// 编译器可能检查不出这一错误
}int main(int argc, char **argv) {return 0;
}

6.31

如果引用所引的是函数开始之前就已经存在的对象,则返回该引用是有效的;如果引用所引的是函数的局部变量,则随着函数结束局部变量也失效了,此时返回的引用无效。

当不希望返回的对象被修改时,返回对常量的引用

6.32

该函数是合法的。get 函数接受一个整型指针,该指针实际指向一个整型数组的首元素,另外还接受一个整数表示数组中某个元素的索引值。它的返回值类型是整型引用,引用的对象是 array 数组的某个元素。当 get 函数执行完毕后,调用者得到实参数组 array 中索引为 index 的元素的引用。

6.33

#include <iostream>
#include <vector>
using namespace std;// 递归函数输出 vector<int> 的内容
void print(vector<int> vInt, unsigned index) {unsigned sz = vInt.size();if (!vInt.empty() && index < sz) {cout << vInt[index] << endl;print(vInt, index + 1);}
}int main() {vector<int> v = {1, 3, 5, 7, 9, 11, 13, 15};print(v, 0);return 0;
}

6.34

因为原文中递归函数的参数类型是 int,所以理论上用户传入 factorial 函数的参数可以是负数。按照原程序的逻辑,参数为负数时函数的返回值是 1.

如果修改递归函数的停止条件,则当参数的值为负时,会依次递归下去,执行连续乘法操作直至溢出。因此,不能把 if 语句的条件改成上述形式。

6.35

如果把 val - 1 改成 val-- ,则出现一种我们不期望看到的情况,即变量的递减操作与读取变量值的操作共存于同一条表达式中,这时有可能产生未定义的值

6.36

要想使函数返回数组的引用并且该数组包含 10 个 string 对象,可以按照如下所示的形式声明函数:

string (&func())[10];

上述声明的含义是:func() 表示调用 func 函数无须任何实参,(&func()) 表示函数的返回结果是一个引用,(&func())[10] 表示引用的对象是一个维度为 10 的数组,string (&func())[10] 表示数组的元素是 string 对象。

6.37

typedef string arr[10];
arr &func();auto func() -> string (&)[10];string str[10];
decltype(str) &func();

6.38

int odd[] = {1, 3, 5, 7, 9};
int even[] = {0, 2, 4, 6, 8};
// 返回一个引用,该引用所引的对象是一个含有 5 个整数的数组。
decltype(odd) &arrPtr(int i) {return (i % 2) ? odd : even;		// 返回数组的引用。
}

6.39

(a)的第二个声明是非法的。它的意图是声明另外一个函数,该函数只接受整型常量作为实参,但是因为顶层 const 不影响传入函数的对象,所以一个拥有顶层 const 的形参无法与另一个没有顶层 const 的形参区分开来。

(b)的第二个声明是非法的。它的意图是通过函数的返回值区分两个同名的函数,但是这不可行,因为 C++ 规定重载函数必须在形参数量或形参类型上有所区别。如果两个同名函数的形参数量和类型都一样,那么即使返回类型不同也不行。

(c)的两个函数是重载关系,它们的形参类型有区别。

6.40

a、正确的
b、错误的,默认实参之后必须是默认实参

6.41

(a)是非法的,该函数有两个默认实参,但是总计有三个形参,其中第一个形参并未设定默认实参,所以要想调用该函数,至少需要提供一个实参。

(b)是合法的,本次调用提供了两个实参,第一个实参对应第一个形参 ht,第二个实参对应第二个形参 wd,其中 wd 的默认实参没有用到,第三个形参 bckgrnd 使用它的默认实参。

(c)在语法上是合法的,但是与程序的原意不符。从语法上来说,第一个实参对应第一个形参 ht,第二个实参的类型虽然是 char,但是它可以自动转换为第二个形参 wd 所需的 int 类型,所以编译时可以通过,但这显然违背了程序的原意,正常情况下,字符 * 应该被用来构成背景。

6.42

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

6.43

(a)应该放在头文件中。因为内联函数的定义对编译器而言必须是可见的,以便编译器能够在调用点内联展开该函数的代码,所以仅有函数的原型不够。并且,与一般的函数不同,内联函数有可能在程序中定义不止一次,此时必须保证在所有源文件中定义完全相同,把内联函数的定义放在头文件中可以确保这一点。

(b)是函数声明,应该放在头文件中。

6.44

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

6.45

简单的一句换可以改写为内联函数

6.46

显然 isShorter 函数不符合 constexpr 函数的要求,它虽然只有一条 return 语句,但是返回的结果调用了标准库 string 类的 size() 函数和 < 比较符,无法构成常量表达式,因此不能改写成 constexpr 函数。

6.47

#include <iostream>
#include <vector>
#define NDEBUG
using namespace std;// 递归函数输出 vector<int> 的内容
void print(vector<int> vInt, unsigned index) {unsigned sz = vInt.size();// 设置在此处输出调试信息#ifndef NDEBUGcout << "vector 对象的大小是:" << sz << endl;#endif // NDEBUGif (!vInt.empty() && index < sz) {cout << vInt[index] << endl;print(vInt,index + 1);}
}int main() {vector<int> v = {1, 3, 5, 7, 9, 11, 13, 15};print(v, 0);return 0;
}

6.48

该程序对 assert 的使用有不合理之处。在调试器打开的情况下,当用户输入字符串 s 并且 s 的内容与 sought 不相等时,执行循环体,否则继续执行 assert(cin); 语句。换句话说,程序执行到 assert 的原因可能有两个,一是用户终止了输入,二是用户输入的内容正好与 sought 的内容一样。如果用户尝试终止输入(事实上用户总有停止输入结束程序的时候),则 assert 的条件为假,输出错误信息,这与程序的原意是不相符的。

当调试器关闭时,assert 什么也不做。

6.49

当程序中存在多个同名的重载函数时,编译器需要判断调用的是其中哪个函数,这时就有了候选函数和可行函数两个概念。

函数匹配的第一步是选定本次调用对应的重载函数集,集合中的函数称为候选函数。候选函数具备两个典型特征:一是与被调用的函数同名;二是其声明在调用点可见。

函数匹配的第二步是考查本次调用提供的实参,然后从候选函数中选出能被这组实参调用的函数,这些新选出的函数称为可行函数。可行函数也有两个特征:一是其形参数量与本次调用提供的实参数量相等;二是每个实参的类型与对应的形参类型相同或者能转换成形参的类型。

可行函数是指形参数量与本次调用提供的实参数量相等且每个实参的类型都与对应的形参类型相同或者能够转换成形参类型的函数。

最佳匹配是指该函数每个实参的匹配都不劣于其他可行函数需要的匹配且至少有一个实参的匹配优于其他可行函数提供的匹配。

6.50

f(2.56, 42) 的可行函数是 void f(int, int) 和 void f(double, double = 3.14)。但是最佳匹配不存在,因为这两个可行函数各有所长。对于这次调用来说,如果只考虑第一个实参 2.56,我们发现,void f(double, double = 3.14) 能够精确匹配,但是要匹配第二个参数,int 类型的实参 42 必须转换成 double 类型。如果考虑第二个实参 42,我们发现,void f(int, int) 能够精确匹配,但是要想调用 void f(int, int) 就必须把第一个 double 类型的实参 2.56 转换成 int 类型。最终的结果是这两个可行函数各自在一个实参上实现了更好的匹配,但是把它们比较起来无从判断孰优孰劣,因此编译器将因为这个调用具有二义性而拒绝其请求。

f(42) 的可行函数是 void f(int) 和 void f(double, double = 3.14),其中最佳匹配是 void f(int),因为参数无须做任何类型转换。

f(42, 0) 的可行函数是 void f(int, int) 和 void f(double, double = 3.14),其中最佳匹配是 void f(int, int),因为参数无须做任何类型转换。

f(2.56, 3.14) 的可行函数是 void f(int, int) 和 void f(double, double = 3.14),其中最佳匹配是 void f(double, double = 3.14),因为参数无须做任何类型转换。

6.51

#include <iostream>
void f();
void f(int);
void f(int, int);
void f(double, double);
using namespace std;int main() {// f(2.56, 42);f(42);f(42, 0);f(2.56, 3.14);return 0;
}void f() {cout << "f()" << endl;
}void f(int i) {cout << "f(int)" << endl;
}void f(int i, int j) {cout << "f(int, int)" << endl;
}void f(double d1, double d2 = 3.14) {cout << "f(double, double)" << endl;
}

6.52

(a)发生的参数类型转换是类型提升,字符型实参自动提升成整型。

(b)发生的参数类型转换是算术类型转换,双精度浮点型自动转换成整型。

6.53

(a)是合法的,两个函数的区别是它们的引用类型的形参是否引用了常量,属于底层 const,可以把两个函数区分开来。

(b)是合法的,两个函数的区别是它们的指针类型的形参是否指向了常量,属于底层 const,可以把两个函数区分开来。

(c)是非法的,两个函数的区别是它们的指针类型的形参本身是否是常量,属于顶层 const,根据本节介绍的匹配规则可知,向实参添加顶层 const 或者从实参中删除顶层 const 属于精确匹配,无法区分两个函数。

6.54

int func(int, int);
vector<decltype(func) *> vF;

6.55

#include <iostream>
#include <vector>
using namespace std;int func1(int a, int b) {return a + b;
}int func2(int a, int b) {return a - b;
}int func3(int a, int b) {return a * b;
}int func4(int a, int b) {return a / b;
}int main() {decltype(func1) *p1 = func1, *p2 = func2, *p3 = func3, *p4 = func4;vector<decltype(func1) *> vF = {p1, p2, p3, p4};return 0;
}

6.56

#include <iostream>
#include <vector>
using namespace std;int func1(int a, int b) {return a + b;
}int func2(int a, int b) {return a - b;
}int func3(int a, int b) {return a * b;
}int func4(int a, int b) {return a / b;
}void compute(int a, int b, int (*p)(int, int)) {cout << p(a, b) << endl;
}int main() {int i = 5, j = 10;decltype(func1) *p1 = func1, *p2 = func2, *p3 = func3, *p4 = func4;vector<decltype(func1) *> vF = {p1, p2, p3, p4};for (auto p : vF) {// 遍历 vector 中的每个元素,依次调用四则运算函数compute(i, j, p);}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/680792.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HCIA-HarmonyOS设备开发认证V2.0-3.2.轻量系统内核基础-软件定时器

目录 一、软件定时器基本概念二、软件定时器运行机制三、软件定时器状态四、软件定时器模式五、软件定时器开发流程六、软件定时器使用说明七、软件定时器接口八、代码分析&#xff08;待续...&#xff09;坚持就有收获 一、软件定时器基本概念 软件定时器&#xff0c;是基于系…

论文介绍 VolumeDiffusion

论文介绍 VolumeDiffusion: Flexible Text-to-3D Generation with Efficient Volumetric Encoder 关注微信公众号: DeepGo 源码地址&#xff1a; https://github.com/tzco/VolumeDiffusion 论文地址&#xff1a; https://arxiv.org/abs/2312.11459 VolumeDiffusion模型是一个从…

我们需要延迟满足吗?

延迟满足&#xff0c;可能是当代成功学和鸡汤里面&#xff0c;最常见的一个概念了。 很多人都会告诉你&#xff1a;要学会延迟满足&#xff0c;培养延迟满足能力&#xff0c;这样你才能成为一个脱离低级趣味的人&#xff0c;取得更高的成就。 他们同时还会把延迟满足跟「即时满…

读千脑智能笔记12_阻止人类灭绝

1. 阻止人类灭绝 1.1. 宇宙中唯一知道这些的物体&#xff0c;唯一知道宇宙存在的物体&#xff0c;是我们的大脑 1.2. 如果没有关于某个事物的知识&#xff0c;我们能说这个事物就一定存在吗&#xff1f; 1.2.1. 我们的大脑扮演着这样一个独特的角色&#xff0c;这很令人着迷…

Python算法题集_LRU 缓存

Python算法题集_LRU 缓存 题146&#xff1a;LRU 缓存1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【队列字典】2) 改进版一【有序字典】3) 改进版二【双向链表字典】 4. 最优算法 本文为Python算法题集之一的代码示例 题146&#xff1a;LRU …

小白速成法:剖析一个Android项目以快速上手

这是一个基于Tasmota的设备、用MQTT协议来通信控制的安卓应用程序。支持ON/OFF命令插座和基本的RGB LED控制。 源码点击此处 只需要关注SmartController-main\app\src的代码 项目解压之后如图 只需要关注“app”文件夹里的东西即可&#xff0c;“gradle”是配置文件&#xf…

MATLAB Coder从入门到放弃

一、MATLAB Coder入门 1 MATLAB Coder是什么 从 MATLAB 代码生成 C 和 C 代码 MATLAB Coder™ 可从 MATLAB 代码生成适用于各种硬件平台&#xff08;从桌面计算机系统到嵌入式硬件&#xff09;的 C 和 C 代码。它支持大多数 MATLAB 语言和广泛的工具箱。您可以将生成的代码作…

Android14音频进阶:MediaPlayerService如何启动AudioTrack 下篇(五十六)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

比较6*6范围内8个点425个结构的顺序

( A, B )---6*30*2---( 1, 0 )( 0, 1 ) 让网络的输入有6个节点&#xff0c;训练集AB各由6张二值化的图片组成&#xff0c;让A中有8个点&#xff0c;让B全是0&#xff0c;收敛误差7e-4&#xff0c;收敛199次&#xff0c;统计迭代次数平均值并排序。 假设这个6*6的结构的行和列都…

C++进阶(十六)特殊类设计

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、请设计一个类&#xff0c;不能被拷贝二、请设计一个类&#xff0c;只能在堆上创建对象三、…

力扣1122. 数组的相对排序(哈希表)

Problem: 1122. 数组的相对排序 文章目录 题目描述思路及解法复杂度Code 题目描述 思路及解法 1.利用arr2创建一个无序映射&#xff08;map集合&#xff09;&#xff0c;以其中的元素作为键&#xff0c;值默认设置为0&#xff1b; 2.扫描arr1数组统计arr2元素在其中的个数(将个…

单调队列优化DP问题

目录 1.滑动窗口 2.最大子序和 3.旅行问题 4.烽火传递 5.绿色通道 6.修剪草坪 7.理想的正方形 1.滑动窗口 154.给定一个大小为 n≤106 的数组。 有一个大小为 k 的滑动窗口&#xff0c;它从数组的最左边移动到最右边。 你只能在窗口中看到 k 个数字。 每次滑动窗口向…

游泳时可以听歌的耳机有哪些?戴游泳耳机有哪些好处?

游泳和跑步在某种程度上相似&#xff0c;特别是在短距离冲刺时&#xff0c;大脑似乎变得空白&#xff0c;而在中长距离的有氧运动中&#xff0c;身体感到疲劳&#xff0c;但大脑却异常清晰&#xff0c;时间却显得格外漫长。如何打发时间&#xff0c;让游泳锻炼变得不无聊&#…

力扣面试题 16.21. 交换和(哈希表)

Problem: 面试题 16.21. 交换和 文章目录 题目描述思路及解法复杂度Code 题目描述 思路及解法 1.分别求取array1与array2数组每一个元素的和&#xff08;sum1与sum2&#xff09;并同时将array2的元素存入一个set集合中&#xff1b; 2.如果sum1和sum2的和为奇数&#xff0c;则不…

使用 Windows 11/10 上的最佳 PDF 转 Word 转换器释放 PDF 的潜力

毫无疑问&#xff0c;PDF 是最好的文档格式之一&#xff0c;但就像其他格式一样&#xff0c;有时它们确实会带来一些限制。例如&#xff0c;在某些情况下&#xff0c;您可能想要将 PDF 转换为 Word。在这种情况下&#xff0c;您始终可以借助 PDF 到 Word 转换器的帮助。 为了说…

Java实现软件学院思政案例库系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统管理员2.2 普通教师 三、系统展示四、核心代码4.1 查询思政案例4.2 审核思政案例4.3 查询思政课程4.4 思政案例点赞4.5 新增思政案例评语 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的软件学…

谁再用Arrays.asList就开除谁

谁再用Arrays.asList就开除谁 hi&#xff0c;我是achang&#xff0c;今天说一个使用Arrays.asList后对应出现的一系列坑&#xff0c;因为他有那么多坑&#xff0c;所以会有开玩笑的说&#xff1a;谁再用Arrays.asList就开除谁 那Arrays.asList的作用很简单&#xff0c;就是把…

86.分布式锁理论分析

文章目录 前言一、为什么需要分布式锁&#xff1f;二、基于 Redis 分布式锁怎么实现&#xff1f;三、Redis 分布锁存在的问题3.1 死锁问题3.2 锁过期时间问题3.3 锁被别人释放问题 四、Redis 分布锁小结五、Redis 主从同步对分布式锁的影响六、Redlock 方案七、Redlock 的争论7…

autojs通过正则表达式获取带有数字的text内容

var ctextMatches(/\d/).findOne()console.log("当前金币"c.text()) // 获取当前金币UiSelector.textMatches(reg) reg {string} | {Regex} 要满足的正则表达式。 为当前选择器附加控件"text需要满足正则表达式reg"的条件。 有关正则表达式&#xff0c;可…

揭秘外观模式:简化复杂系统的关键设计策略

前言 外观模式&#xff08;Facade Pattern&#xff09;是一种结构型设计模式&#xff0c;它隐藏了系统的复杂性&#xff0c;并向客户端提供了一个可以访问系统的接口。这种类型的设计模式向现有的系统添加一个接口&#xff0c;来隐藏系统的复杂性。这种模式涉及到一个单一的类…