5.1 构造函数与析构函数
答:______________
✅ 查看答案与解析
答案 对
解析:C++ 默认应该在栈上建对象:Point p{1.0, 2.0}; 没有任何运行时代价,也不需要 new。Java 的 new 习惯要改过来。
答:______________
✅ 查看答案与解析
答案 对
解析:析构函数由编译器自动调用(栈对象出作用域、delete 堆对象、临时对象结束),不能抛异常,否则程序终止。
构造函数体里赋值
初始化列表里
声明之后随便哪里
不能初始化
答:______________
✅ 查看答案与解析
答案 B
解析:const 成员、引用成员、没有默认构造函数的类类型成员,必须在初始化列表里初始化;写在函数体里是赋值,对它们不可能。
class Buffer {
std::vector<int> data_;
std::string name_;
public:
Buffer() : name_("buf"), data_(10, 0) { } // 实际初始化顺序按声明顺序!
✅ 查看答案与解析
答案 把初始化列表顺序改成和声明顺序一致:
解析:成员初始化顺序由声明顺序决定,和列表书写顺序无关。编译器有 -Wreorder 专门提醒这件事。
Buffer() : data_(10, 0), name_("buf") { }提示:dist 用 std::sqrt(x*x + y*y),需要 #include <cmath>;dist 加 const 修饰。
✅ 查看答案与解析
答案 参考答案:
解析:struct 默认公有成员,适合数据打包;const 成员函数承诺不修改对象。
#include <iostream>
#include <cmath>
struct Point {
double x = 0.0;
double y = 0.0;
double dist() const { return std::sqrt(x * x + y * y); }
};
int main() {
Point p{3.0, 4.0};
std::cout << p.dist() << '\n'; // 5
return 0;
}5.2 拷贝控制
答:______________
✅ 查看答案与解析
答案 对
解析:零法则:先用会管理资源的成员,能不写裸指针就不写,大部分内存管理问题自然消失。
答:______________
✅ 查看答案与解析
答案 对
解析:这就是浅拷贝问题。这种类需要自己写深拷贝:拷贝构造、拷贝赋值、析构(以及移动构造、移动赋值)——即五法则。
移动构造
拷贝构造
默认构造
拷贝赋值
答:______________
✅ 查看答案与解析
答案 B
解析:用已存在的 a 初始化新对象 b,调用拷贝构造。IntArray c = std::move(a); 才调用移动构造。
class IntArray {
public:
IntArray(std::size_t n) : size_(n), data_(new int[n]{}) { }
~IntArray() { delete[] data_; }
// 缺拷贝构造、拷贝赋值、移动构造、移动赋值
private:
std::size_t size_;
int* data_;
};
✅ 查看答案与解析
答案 补上五法则的其余四个函数(拷贝构造做深拷贝、拷贝赋值处理自赋值、移动构造/移动赋值窃取资源),或者把 data_ 换成 std::vector<int>。
解析:如果一个类需要自己写析构,那它通常也需要拷贝构造、拷贝赋值、移动构造、移动赋值。最省事:不写裸指针。
提示:静态成员变量要在类外定义一次:int Counter::instances = 0;(或 C++17 用 inline static)。
✅ 查看答案与解析
答案 参考答案:
解析:静态成员属于类、所有对象共享;静态成员函数用 ClassName:: 访问。
#include <iostream>
class Counter {
public:
Counter() { ++instances; }
~Counter() { --instances; }
static int count() { return instances; }
private:
static int instances;
};
int Counter::instances = 0;
int main() {
Counter a, b, c;
std::cout << Counter::count() << '\n'; // 3
{ Counter d; }
std::cout << Counter::count() << '\n'; // 3(d 已析构)
return 0;
}5.3 运算符重载与继承
答:______________
✅ 查看答案与解析
答案 对
解析:严格弱序:相等必须返回 false。写成 <= 或 >= 会让 sort 走进未定义行为,典型症状是段错误或元素丢失。
答:______________
✅ 查看答案与解析
答案 对
解析:否则 Shape* p = new Circle(); delete p; 只调用 Shape 的析构,Circle 的资源就泄漏了。
正常多态调用
对象切片:Circle 被切成 Shape,多态信息丢失
编译错误
运行时报错
答:______________
✅ 查看答案与解析
答案 B
解析:按值传递基类会发生对象切片,多态信息全部丢失。多态必须通过指针或引用使用。
class Shape {
public:
virtual double area() const = 0;
};
class Circle : public Shape {
public:
double area() { return 3.14 * r_ * r_; } // 少了 const!
private:
double r_;
};
✅ 查看答案与解析
答案 加 const 和 override:
解析:签名不完全一致(少 const)就不是覆盖,而是新增了一个隐藏函数。override 关键字能帮编译器检查出来。
double area() const override { return 3.14 * r_ * r_; }提示:std::sort 需要 operator< 或自定义比较器。
✅ 查看答案与解析
答案 参考答案:
解析:operator< 返回 score > o.score 实现降序;记住严格弱序要求。
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
struct Student {
std::string name;
int score;
bool operator<(const Student& o) const { return score > o.score; }
};
int main() {
std::vector<Student> v{{"Ann", 90}, {"Bob", 95}, {"Cid", 88}};
std::sort(v.begin(), v.end());
for (const auto& s : v) { std::cout << s.name << ' ' << s.score << '\n'; }
return 0;
}
// 输出:Bob 95 / Ann 90 / Cid 88