C++构造函数与析构函数
构造函数和析构函数是C++类的特殊成员函数,负责对象的初始化和清理工作。理解它们的工作机制对于编写正确的C++代码至关重要。
默认构造函数在没有参数的情况下创建对象。
#include
#include
#include
class Person {
std::string name_;
int age_;
public:
Person() : name_("Unknown"), age_(0) {
std::cout << "Default constructor called\n";
}
Person(const std::string& name, int age) : name_(name), age_(age) {
std::cout << "Parameterized constructor called for " << name_ << "\n";
}
~Person() {
std::cout << "Destructor called for " << name_ << "\n";
}
void display() const {
std::cout << "Name: " << name_ << ", Age: " << age_ << "\n";
}
};
void constructor_basics() {
Person p1;
Person p2("Alice", 30);
p1.display();
p2.display();
}
成员初始化列表是初始化成员变量的首选方式,比在构造函数体内赋值更高效。
class Rectangle {
const int width_;
const int height_;
int& area_ref_;
int area_;
public:
Rectangle(int w, int h, int& ref)
: width_(w), height_(h), area_ref_(ref), area_(w * h) {
std::cout << "Rectangle constructed: " << width_ << "x" << height_ << "\n";
}
int area() const { return area_; }
};
void initializer_list_example() {
int external_area = 0;
Rectangle rect(10, 20, external_area);
std::cout << "Area: " << rect.area() << "\n";
}
委托构造函数允许一个构造函数调用同一个类的另一个构造函数。
class Point {
int x_, y_;
public:
Point() : Point(0, 0) {
std::cout << "Default constructor delegates\n";
}
Point(int x) : Point(x, 0) {
std::cout << "Single parameter constructor delegates\n";
}
Point(int x, int y) : x_(x), y_(y) {
std::cout << "Main constructor: (" << x_ << ", " << y_ << ")\n";
}
void display() const {
std::cout << "Point(" << x_ << ", " << y_ << ")\n";
}
};
void delegating_constructor() {
Point p1;
Point p2(5);
Point p3(3, 4);
}
拷贝构造函数用于从另一个对象创建新对象。
class Array {
int* data_;
size_t size_;
public:
explicit Array(size_t size) : data_(new int[size]), size_(size) {
std::cout << "Constructor: allocated " << size_ << " ints\n";
}
Array(const Array& other) : data_(new int[other.size_]), size_(other.size_) {
std::copy(other.data_, other.data_ + size_, data_);
std::cout << "Copy constructor: copied " << size_ << " ints\n";
}
~Array() {
delete[] data_;
std::cout << "Destructor: freed memory\n";
}
size_t size() const { return size_; }
};
void copy_constructor_example() {
Array arr1(10);
Array arr2 = arr1;
Array arr3(arr1);
}
移动构造函数通过转移资源所有权来避免不必要的拷贝。
class String {
char* data_;
size_t length_;
public:
String(const char* str = "") {
length_ = strlen(str);
data_ = new char[length_ + 1];
strcpy(data_, str);
std::cout << "Constructor: " << data_ << "\n";
}
String(const String& other) : length_(other.length_) {
data_ = new char[length_ + 1];
strcpy(data_, other.data_);
std::cout << "Copy constructor: " << data_ << "\n";
}
String(String&& other) noexcept : data_(other.data_), length_(other.length_) {
other.data_ = nullptr;
other.length_ = 0;
std::cout << "Move constructor\n";
}
~String() {
delete[] data_;
}
const char* c_str() const { return data_ ? data_ : ""; }
};
void move_constructor_example() {
String s1("Hello");
String s2 = std::move(s1);
String s3 = String("World");
}
explicit关键字防止隐式类型转换。
class Integer {
int value_;
public:
explicit Integer(int v) : value_(v) {}
int value() const { return value_; }
};
void explicit_constructor() {
Integer i1(42);
std::cout << "Value: " << i1.value() << "\n";
}
析构函数在对象生命周期结束时自动调用,用于释放资源。
class File {
FILE* file_;
std::string filename_;
public:
explicit File(const std::string& filename) : filename_(filename) {
file_ = fopen(filename.c_str(), "w");
if (file_) {
std::cout << "File opened: " << filename_ << "\n";
}
}
~File() {
if (file_) {
fclose(file_);
std::cout << "File closed: " << filename_ << "\n";
}
}
void write(const std::string& data) {
if (file_) {
fwrite(data.c_str(), 1, data.size(), file_);
}
}
File(const File&) = delete;
File& operator=(const File&) = delete;
};
void destructor_example() {
File file("test.txt");
file.write("Hello, World!\n");
}
虚析构函数确保通过基类指针删除派生类对象时正确调用派生类的析构函数。
class Base {
public:
Base() {
std::cout << "Base constructor\n";
}
virtual ~Base() {
std::cout << "Base destructor\n";
}
};
class Derived : public Base {
int* data_;
public:
Derived() : data_(new int[100]) {
std::cout << "Derived constructor\n";
}
~Derived() override {
delete[] data_;
std::cout << "Derived destructor\n";
}
};
void virtual_destructor_example() {
Base* ptr = new Derived();
delete ptr;
}
构造函数和析构函数的调用顺序遵循特定规则,理解这些规则对于避免资源泄漏很重要。
class Component {
std::string name_;
public:
explicit Component(const std::string& name) : name_(name) {
std::cout << "Component " << name_ << " constructed\n";
}
~Component() {
std::cout << "Component " << name_ << " destructed\n";
}
};
class System {
Component comp1_;
Component comp2_;
public:
System() : comp1_("A"), comp2_("B") {
std::cout << "System constructed\n";
}
~System() {
std::cout << "System destructed\n";
}
};
void construction_order() {
System sys;
}
构造函数和析构函数是RAII模式的基础,确保资源的正确管理。
C++构造函数与析构函数