简言:
当我们在 C++ 中定义一个类时,我们需要考虑如何在实例化对象的时候对其进行初始化和释放资源。这时候,构造函数和析构函数就应运而生了。本文将为你介绍 C++ 中构造函数和析构函数的用法以及如何使用它们来初始化和释放对象。
构造函数
构造函数在类实例化对象时被调用,主要用于对对象进行初始化操作。在 C++ 中,一个类可以有多个构造函数,但是它们必须具有不同的参数列表。下面是一个简单的例子,它演示了如何在 C++ 中定义一个构造函数:
#include <iostream>
class A {
public:
A() {
std::cout << "MyClass object created." << std::endl;
}
};
int main() {
A Object;
return 0;
}
在这个例子中,我们定义了一个 A 类,并在其中添加了一个默认构造函数。在 main 函数中,我们实例化了一个 A对象 Object。当程序运行时,A 的构造函数会被调用,并在控制台输出 "MyClass object created."。
在 C++ 中,构造函数可以被重载。这意味着我们可以根据需要定义多个构造函数。例如,我们可以定义一个带参数的构造函数,用于在创建对象时传递参数。下面是一个带参数的构造函数的例子:
#include <iostream>
class MyClass {
public:
A(int value) {
std::cout << "MyClass object created with value " << value << "." << std::endl;
}
};
int main() {
A myObject(42);
return 0;
}
在这个例子中,我们定义了一个带有一个整数参数的构造函数。在 main 函数中,我们实例化了一个 A 对象 myObject,并传递了参数 42。当程序运行时,A 的带参数构造函数将被调用,并在控制台输出相应的消息。
析构函数:
析构函数在对象被销毁时被调用,主要用于释放对象占用的资源。与构造函数类似,一个类也可以拥有多个析构函数。在 C++ 中,析构函数的名称与类名相同,但前面有一个波浪线 (~)。下面是一个简单的例子,它演示了如何在 C++ 中定义一个析构函数:
#include <iostream>
class A {
public:
A() {
std::cout << "MyClass object created." << std::endl;
}
~A() {
std::cout << "MyClass object destroyed." << std::endl;
}
};
int main() {
A myObject;
return 0;
}
在这个例子中,我们在 A 中添加了一个析构函数,当 MyClass 对象被销毁时,析构函数将被自动调用。当程序运行时,A 的构造函数和析构函数都会被调用,并在控制台输出相应的消息。
构造函数和析构函数的顺序
在 C++ 中,构造函数和析构函数的顺序是有规则的。在一个类的对象被创建时,构造函数的顺序与成员声明的顺序一致,而析构函数的顺序则与构造函数相反。
拷贝构造函数
拷贝构造函数是一种特殊的构造函数,用于创建一个新对象,该对象与另一个对象具有相同的值。当我们使用一个对象初始化另一个对象时,拷贝构造函数将被调用。下面是一个简单的例子,它演示了如何在 C++ 中定义一个拷贝构造函数:
#include <iostream>
class MyClass {
public:
MyClass() {
std::cout << "MyClass object created." << std::endl;
}
MyClass(const MyClass& other) {
std::cout << "MyClass object created by copying." << std::endl;
}
};
int main() {
MyClass myObject1;
MyClass myObject2 = myObject1;
return 0;
}
在这个例子中,我们定义了一个 MyClass 类,并在其中添加了一个默认构造函数和一个拷贝构造函数。在 main 函数中,我们实例化了两个 MyClass 对象 myObject1
浅拷贝
浅拷贝(Shallow Copy)是指在拷贝对象时,只是复制了对象的指针,而没有复制指针所指向的内容。这意味着原始对象和新对象将共享相同的内存位置,如果其中一个对象修改了该共享内存中的内容,则另一个对象也会受到影响。
深拷贝(Deep Copy)是指在拷贝对象时,除了复制指针外,还复制了指针所指向的内容。这意味着原始对象和新对象将拥有它们自己的内存位置,彼此之间不会相互影响。
下面是一个例子,说明浅拷贝和深拷贝的区别:
#include <iostream>
class MyString {
private:
char* str;
public:
MyString(const char* s) {
int size = std::strlen(s) + 1;
str = new char[size];
std::strcpy(str, s);
}
~MyString() {
delete[] str;
}
MyString(const MyString& other) {
std::cout << "Shallow Copy Constructor Called" << std::endl;
str = other.str;
}
MyString& operator=(const MyString& other) {
std::cout << "Shallow Assignment Operator Called" << std::endl;
str = other.str;
return *this;
}
void print() {
std::cout << str << std::endl;
}
};
int main() {
MyString str1("Hello, world!");
// 浅拷贝
MyString str2 = str1;
std::cout << "String 2: ";
str2.print();
// 修改 str1
str1.print();
str1 = MyString("Goodbye!");
std::cout << "String 1: ";
str1.print();
std::cout << "String 2: ";
str2.print();
return 0;
}
在这个例子中,我们创建了一个名为MyString的类,它包含了一个char*类型的成员变量str,表示一个字符串。我们还实现了一个拷贝构造函数和一个赋值运算符,它们都进行了浅拷贝。
在main函数中,我们创建了一个名为str1的MyString对象,并将其内容设置为Hello, world!。然后,我们使用拷贝构造函数创建了一个名为str2的新对象,它是通过浅拷贝从str1创建的。
接下来,我们修改了str1的内容,将其设置为Goodbye!。然后我们打印str1和str2的内容,以查看它们的值是否相同。
在运行这个程序时,我们将看到以下输出:
Shallow Copy Constructor Called
String 2: Hello, world!
Hello,