题目中所使用的类#
为了提高可读性, 部分地方采用了 C++20 的语法进行初始化, 见下文.
1ctor: 非拷贝构造时输出的字符
2copy_ctor: 拷贝构造时输出的字符
3copy_assign: 拷贝赋值时输出的字符
4dtor: 析构时输出的字符
class Noisy
#
它将会在 非拷贝构造、 被用于拷贝构造、 被用于拷贝赋值 或 析构 时输出对应的字符.
例如,
构造析构#
int main() {
// 构造时输出 0, 被用于拷贝构造时输出 1, 被用于拷贝赋值时输出 2, 析构时输出 3, 其余情况不输出
Noisy c1{
Info{.ctor = "0", .copy_ctor = "1", .copy_assign = "2", .dtor = "3"}};
// 构造时输出 4, 析构时输出 5, 其余情况不输出
Noisy c2{Info{.ctor = "4", .dtor = "5"}};
}
// 最终输出
// 0: c1 构造
// 4: c2 构造
// 5: c2 析构
// 3: c1 析构
拷贝构造#
int main() {
// 构造时输出 0, 被用于拷贝构造时输出 1, 被用于拷贝赋值时输出 2, 析构时输出 3, 其余情况不输出
Noisy c1{
Info{.ctor = "0", .copy_ctor = "1", .copy_assign = "2", .dtor = "3"}};
// 拷贝构造输出 1, 并且之后 c2.info == c1.info
// 即此后构造时输出 0, 被用于拷贝构造时输出 1, 被用于拷贝赋值时输出 2, 析构时输出 3, 其余情况不输出
Noisy c2{c1};
}
// 最终输出
// 0: c1 构造
// 1: Noisy c2{c1}
// 3: c2 析构
// 3: c1 析构
拷贝赋值#
int main() {
// 构造时输出 0, 被用于拷贝构造时输出 1, 被用于拷贝赋值时输出 2, 析构时输出 3, 其余情况不输出
Noisy c1{
Info{.ctor = "0", .copy_ctor = "1", .copy_assign = "2", .dtor = "3"}};
// 构造时输出 4, 被用于拷贝构造时输出 5, 被用于拷贝赋值时输出 6, 析构时输出 7, 其余情况不输出
Noisy c2{
Info{.ctor = "4", .copy_ctor = "5", .copy_assign = "6", .dtor = "7"}};
// 输出 2, 并且之后 c2.info == c1.info
// 即此后构造时输出 0, 被用于拷贝构造时输出 1, 被用于拷贝赋值时输出 2, 析构时输出 3, 其余情况不输出
c2 = c1;
}
// 最终输出
// 0: c1 构造
// 4: c2 构造
// 2: c2 = c1;
// 3: c2 析构
// 3: c1 析构
class Derived_noisy : public Noisy
#
继承自 Noisy
.
遵循继承的逻辑,
构造/赋值时先构造/赋值
Noisy
, 再构造/赋值Derived_noisy
.析构时先析构
Derived_noisy
, 再析构Noisy
.拷贝时发生切片, 只拷贝静态类型部分, 这部分内容可参考 虚函数调用的感性理解.
1int main() {
2 // 构造时输出 03, 正常被用于拷贝时输出 14, 析构时输出 52, 其余情况不输出
3 Derived_noisy c1{Info{.ctor = "0", .copy_ctor = "1", .dtor = "2"},
4 Derived_info{.ctor = "3", .copy_ctor = "4", .dtor = "5"}};
5
6 // 拷贝时发生切片, 仅拷贝了此处的静态类型, 即 `Noisy` 部分
7 // 最终仅得到 Info{.ctor = "0", .copy_ctor = "1", .dtor = "2"} 部分
8 // 输出 1, 并且之后 c2.info == c1.info
9 // 即此后构造时输出 0, 被用于拷贝构造时输出 1, 析构时输出 2, 其余情况不输出
10 Noisy c2 = c1;
11}
12// 最终输出
13// 0: c1 Noisy 部分构造
14// 3: c1 Derived_noisy 部分构造
15// 1: Noisy c2 = c1; 发生切片, 仅拷贝 Noisy 部分
16// 2: c2 析构
17// 5: c1 Derived_noisy 部分析构
18// 2: c1 Noisy 部分析构