C++构造函数与析构函数
构造函数和析构函数是C++类中特殊的成员函数,用于对象的初始化和清理。
简单说,构造函数负责初始化类,析构函数负责销毁对象是的清理工作。
关键要点总结
构造函数特点:
- 与类同名,没有返回类型
- 可以重载,支持多个构造函数版本
- 自动调用,创建对象时自动执行
- 初始化列表:推荐使用,效率更高,可以初始化const成员和引用成员
- 特殊构造函数:
- 默认构造函数:无参数或所有参数有默认值
- 拷贝构造函数:
ClassName(const ClassName& other) - 移动构造函数(C++11):
ClassName(ClassName&& other) - 委托构造函数(C++11):一个构造函数可以调用另一个
析构函数特点:
- 名称格式:
~ClassName() - 没有参数,不能重载(每个类只有一个析构函数)
- 自动调用,对象销毁时自动执行
- 主要用途:释放动态分配的内存、关闭文件、释放网络连接等资源清理工作
- 调用时机:
- 局部对象:离开作用域时
- 动态分配对象:使用
delete时 - 全局/静态对象:程序结束时
重要原则:
- RAII原则:资源获取即初始化,通过构造函数获取资源,通过析构函数释放资源
- 三法则:如果需要自定义析构函数、拷贝构造函数或拷贝赋值运算符中的任何一个,通常需要同时定义这三个
- 五法则(C++11):增加了移动构造函数和移动赋值运算符的考虑
- 零法则:如果不需要管理资源,让编译器生成默认的特殊成员函数
掌握构造函数和析构函数是理解C++对象生命周期和资源管理的基础。
示例
构造函数在创建对象时自动调用,用于初始化对象的成员变量。
cpp
#include <iostream>
#include <string>
using namespace std;
// 1. 默认构造函数(无参数)
class Person {
private:
string name;
int age;
public:
// 默认构造函数
Person() {
name = "未知";
age = 0;
cout << "默认构造函数被调用" << endl;
}
// 2. 带参数的构造函数
Person(string n, int a) {
name = n;
age = a;
cout << "带参数构造函数被调用" << endl;
}
void display() {
cout << "姓名: " << name << ", 年龄: " << age << endl;
}
};
// 3. 使用初始化列表的构造函数
class Student {
private:
string name;
int score;
const int id; // 常量成员,必须在初始化列表中初始化
public:
// 初始化列表构造函数(效率更高)
Student(string n, int s, int i) : name(n), score(s), id(i) {
cout << "学生" << name << "被创建,ID: " << id << endl;
}
void show() {
cout << "学生" << name << ",分数: " << score << ",ID: " << id << endl;
}
};
int main() {
// 调用默认构造函数
Person p1;
p1.display();
// 调用带参数构造函数
Person p2("张三", 25);
p2.display();
// 调用初始化列表构造函数
Student s1("李四", 95, 1001);
s1.show();
return 0;
}cpp
#include <iostream>
#include <string>
using namespace std;
class Book {
private:
string title;
string author;
double price;
int* sales; // 动态分配的内存
public:
// 1. 构造函数重载
Book() : title("未命名"), author("未知"), price(0.0), sales(nullptr) {
cout << "默认构造函数" << endl;
}
Book(string t) : title(t), author("未知"), price(0.0), sales(nullptr) {
cout << "单参数构造函数" << endl;
}
Book(string t, string a, double p) : title(t), author(a), price(p) {
sales = new int[12]; // 为12个月的销量分配内存
for (int i = 0; i < 12; i++) sales[i] = 0;
cout << "三参数构造函数" << endl;
}
// 2. 拷贝构造函数(深拷贝)
Book(const Book& other) {
title = other.title;
author = other.author;
price = other.price;
// 深拷贝:为新对象分配独立的内存
if (other.sales != nullptr) {
sales = new int[12];
for (int i = 0; i < 12; i++) {
sales[i] = other.sales[i];
}
} else {
sales = nullptr;
}
cout << "拷贝构造函数被调用" << endl;
}
// 3. 移动构造函数(C++11)
Book(Book&& other) noexcept {
title = move(other.title);
author = move(other.author);
price = other.price;
sales = other.sales; // 转移资源所有权
other.sales = nullptr; // 源对象置空
other.price = 0.0;
cout << "移动构造函数被调用" << endl;
}
// 4. 委托构造函数(C++11)
Book(string t, string a) : Book(t, a, 0.0) {
// 委托给三参数构造函数
cout << "委托构造函数完成任务" << endl;
}
// 成员函数
void display() {
cout << "《" << title << "》作者:" << author
<< ",价格:" << price << "元" << endl;
}
// 设置销量
void setSales(int month, int count) {
if (sales != nullptr && month >= 1 && month <= 12) {
sales[month-1] = count;
}
}
// 析构函数声明(将在下一个代码块详细讲解)
~Book();
};
// 测试函数
void testBook() {
cout << "=== 创建book1 ===" << endl;
Book book1("C++ Primer", "Stanley Lippman", 99.9);
book1.setSales(1, 100);
book1.display();
cout << "\n=== 拷贝构造book2 ===" << endl;
Book book2 = book1; // 调用拷贝构造函数
book2.display();
cout << "\n=== 移动构造book3 ===" << endl;
Book book3 = move(book1); // 调用移动构造函数
book3.display();
cout << "\n=== 委托构造book4 ===" << endl;
Book book4("Effective C++", "Scott Meyers");
book4.display();
}
int main() {
testBook();
return 0;
}cpp
#include <iostream>
#include <string>
using namespace std;
// 析构函数(Destructor)
// 在对象销毁时自动调用,用于清理资源
class Book {
private:
string title;
string author;
double price;
int* sales; // 动态分配的内存
public:
// 构造函数
Book(string t, string a, double p) : title(t), author(a), price(p) {
sales = new int[12];
for (int i = 0; i < 12; i++) sales[i] = 0;
cout << "构造函数: " << title << endl;
}
// 拷贝构造函数
Book(const Book& other) {
title = other.title + "(副本)";
author = other.author;
price = other.price;
sales = new int[12];
for (int i = 0; i < 12; i++) sales[i] = other.sales[i];
cout << "拷贝构造: " << title << endl;
}
// 析构函数
~Book() {
cout << "析构函数: " << title;
// 释放动态分配的内存
if (sales != nullptr) {
delete[] sales;
sales = nullptr;
cout << " (内存已释放)" << endl;
} else {
cout << " (无动态内存)" << endl;
}
}
void display() {
cout << "《" << title << "》作者:" << author
<< ",价格:" << price << "元" << endl;
}
};
// 演示析构函数调用时机
class Resource {
private:
string name;
public:
Resource(string n) : name(n) {
cout << "资源" << name << "被创建" << endl;
}
~Resource() {
cout << "资源" << name << "被销毁" << endl;
}
};
class Container {
private:
Resource* res;
public:
Container(string name) {
res = new Resource(name);
cout << "容器被创建" << endl;
}
~Container() {
delete res; // 释放资源
cout << "容器被销毁" << endl;
}
};
// 演示局部对象、全局对象、动态分配对象的生命周期
void testLifecycle() {
cout << "\n=== 进入testLifecycle函数 ===" << endl;
// 1. 局部对象 - 函数结束时自动销毁
Book localBook("局部书", "局部作者", 50.0);
// 2. 动态分配的对象 - 需要手动delete才会调用析构函数
Book* dynamicBook = new Book("动态书", "动态作者", 60.0);
cout << "\n=== 创建块作用域对象 ===" << endl;
{
// 3. 块作用域对象 - 离开块时自动销毁
Book blockBook("块作用域书", "块作者", 70.0);
}
cout << "=== 离开块作用域 ===" << endl;
// 必须手动删除动态分配的对象
delete dynamicBook;
dynamicBook = nullptr;
cout << "=== 即将离开testLifecycle函数 ===" << endl;
// localBook的析构函数将在这里自动调用
}
// 全局对象 - 程序结束时销毁
Book globalBook("全局书", "全局作者", 80.0);
// 静态局部对象 - 程序结束时销毁
void testStatic() {
static Book staticBook("静态书", "静态作者", 90.0);
cout << "静态对象测试函数" << endl;
}
int main() {
cout << "=== 程序开始 ===" << endl;
testLifecycle();
cout << "\n=== 测试静态对象 ===" << endl;
testStatic();
testStatic(); // 第二次调用不会创建新对象
cout << "\n=== 测试容器类 ===" << endl;
Container container("我的资源");
cout << "\n=== main函数即将结束 ===" << endl;
// globalBook和staticBook的析构函数将在这里调用
return 0;
}