C++ Primer 中文版(第 5 版)练习解答合集
自己写的解答,如有错误之处,烦请在评论区指正!
#include <iostream>
#include <initializer_list>
using namespace std;
int sum(initializer_list<int> list) {
int sum = 0;
for (auto it = list.begin(); it != list.end(); ++it)
sum += *it;
return sum;
}
int main() {
cout << sum({1,2,3,4,5}) << endl;
return 0;
}
const string&
类型- 应该声明成引用,避免拷贝。
- 略
- 返回局部对象的引用无效。返回属于局部对象的常量的引用无效。(总之,如果要返回引用,引用的对象应当在被调函数之前就存在,或者是静态全局变量)
- 合法。为
ia
中的元素分别赋值 0 ~ 9
#include <iostream>
#include <vector>
using namespace std;
void print(vector<int> &nums, int index) {
if (index == nums.size()) return;
cout << nums[index] << endl;
print(nums, index + 1);
}
int main() {
vector<int> nums = {1, 2, 3, 4, 5};
print(nums, 0);
return 0;
}
- 参数是正数的话比原来多递归一层并得到正确答案;参数是负数的话无限递归。
val--
返回的是递减前的值,如果一定要用递减的话,可以用--val
string (&func(void))[10];
- 当确定返回值类型和现有变量相同的时候我选
decltype
,否则选尾置返回类型。
// 类型别名:
typedef string arrT[10];
using attT = string[10]; // 和上一行等价
arrT& func(void);
// 尾置返回类型
auto func(void) -> string(&)[10]
// decltype 关键字
string whatever[10];
decltype(whatever) &func(void);
decltype(odd) &arrPtr(int i) {
return (i % 2) ? odd : even;
}
- a. 非法。顶层
const
是重复声明;
b. 非法。只有返回类型不同不足以实现重载;
c. 合法。 - a. 正确;
b. 错误。默认实参只能出现在后面,要么改变参数顺序,要么三个参数都写上默认实参。 - a. 非法,形参
ht
没有被初始化;
b. 合法。
c. 和初衷不符,'*'
被传递给形参wd
,并且发生了隐式的类型转换。
#include <iostream>
#include <string>
using namespace std;
string make_plural(size_t ctr, const string &word, const string &ending = "s") {
return (ctr > 1) ? word + ending : word;
}
int main() {
cout << make_plural(1, "success", "es") << endl;
cout << make_plural(1, "failure") << endl;
cout << make_plural(2, "success", "es") << endl;
cout << make_plural(2, "failure") << endl;
return 0;
}
- a. 内联函数的定义和声明都放在头文件中;
b. 声明一般放在头文件中。
inline bool isShorter(const string &s1, const string &s2) {
return s1.size() < s2.size();
}
- 简单且非递归的函数可以写成内联函数,一般较长的函数和递归函数不应该写成内联函数。(但是写了也没关系,这只是个请求,最终在实现上是不是内联还是编译器决定的)
- 不能。形参的类型
const string&
并不是字面值类型。 - 我写的递归函数中
vector
长度不发生变化,所以就每次递归显示当前的下标。
#include <iostream>
#include <vector>
using namespace std;
//#define NDEBUG
void print(vector<int> &nums, int index) {
#ifndef NDEBUG
cout << "index = " << index << endl;
#endif
if (index == nums.size()) return;
cout << nums[index] << endl;
print(nums, index + 1);
}
int main() {
vector<int> nums = {1, 2, 3, 4, 5};
print(nums, 0);
return 0;
}
- 循环的含义:不断地用字符串
s
接收输入数据,直到s == sought
或者cin
到达EOF
为止。
对assert
使用不合理,如果cin
到达EOF
的话程序就会在此处终止运行,应该用assert(s == sought || !cin)
更好 - 候选函数是一类函数的集合,这类函数具备两个特征:一是与被调用的函数同名,二是其声明在调用点可见;
可行函数也具有两个特征:一是其形参数量与本次调用提供的实参数量相等,二是每个实参的类型与对应的形参类型相同,或者能转换成形参的类型。 - a. 不合法。调用具有二义性;
b. 合法。void f(int);
是最佳匹配;
c. 合法。void f(int, int);
是最佳匹配;
d. 合法。void f(double, double = 3.14);
是最佳匹配;
#include <iostream>
using namespace std;
void f() {
cout << "I am f()" << endl;
}
void f(int) {
cout << "I am f(int)" << endl;
}
void f(int, int) {
cout << "I am f(int, int)" << endl;
}
void f(double, double = 3.14) {
cout << "I am f(double, double = 3.14)" << endl;
}
int main() {
// f(2.56, 42); // illegal
f(42);
f(42, 0);
f(2.56, 3.14);
return 0;
}
- a. 3. 通过类型提升实现的匹配;
b. 4. 通过算数类型转换实现的匹配。 - a. 合法,实现函数重载。(因为是底层
const
所以合法)
b. 合法,同上;
c. 非法,顶层const
的区别不足以实现函数重载。
#include <iostream>
#include <vector>
using namespace std;
int myAdd(int a, int b){
return a+b;
}
int mySub(int a, int b){
return a-b;
}
int myMul(int a, int b){
return a*b;
}
int myDiv(int a, int b){
return a/b;
}
int main(){
using p = int (*)(int a, int b);
vector<p> cal = {myAdd, mySub, myMul, myDiv};
int a = 2, b = 3;
for (auto f : cal)
cout << f(a,b) << endl;
return 0;
}
- 见 54
- 见 54