构造函数是用来初始化对象的成员变量的特殊函数。当创建类的新对象时,构造函数会被自动调用。构造函数的名称与类名相同,并且没有返回类型。一个类可以有多个构造函数,这被称为构造函数的重载。析构函数是当对象的生命周期结束时自动调用的特殊函数,用于执行清理操作,如释放资源、内存等。析构函数的名称由波浪号(~)后跟类名组成,并且没有参数和返回类型。
#include <iostream>
class SimpleClass {
private:
int number; // 数据成员
public:
// 默认构造函数
SimpleClass() : number(0) { // 初始化为0
std::cout << "Default constructor called for object at [" << this << "], number = " << number << std::endl;
}
// 参数化构造函数
SimpleClass(int num) : number(num) { // 初始化为传入的值
std::cout << "Parameterized constructor called for object at [" << this << "], number = " << number << std::endl;
}
// 拷贝构造函数
SimpleClass(const SimpleClass& other) : number(other.number) { // 通过复制来初始化
std::cout << "Copy constructor called for object at [" << this << "], number = " << number << std::endl;
}
// 移动构造函数
SimpleClass(SimpleClass&& other) noexcept : number(other.number) { // 通过移动来初始化
other.number = 0; // 移动后,将源对象的数据成员设置为默认值
std::cout << "Move constructor called for object at [" << this << "], number = " << number << std::endl;
}
// 析构函数
~SimpleClass() {
std::cout << "Destructor called for object at [" << this << "], number was " << number << std::endl; // 使用this指针
}
};
int main() {
std::cout << "Creating object with default constructor:" << std::endl;
SimpleClass obj1;
std::cout << "\nCreating object with parameterized constructor:" << std::endl;
SimpleClass obj2(42);
std::cout << "\nCreating object with copy constructor:" << std::endl;
SimpleClass obj3 = obj2;
std::cout << "\nCreating object with move constructor:" << std::endl;
SimpleClass obj4 = std::move(obj2); // obj2的内容现在已经移动到obj4,obj2不应再被使用
std::cout << "\nExiting main function, objects will be destroyed in reverse order of creation." << std::endl;
return 0; // 对象会按照创建的相反顺序被销毁: obj4, obj3, obj2, obj1
}
输出结果:
Creating object with default constructor:
Default constructor called for object at [0x61ff0c], number = 0
Creating object with parameterized constructor:
Parameterized constructor called for object at [0x61ff08], number = 42
Creating object with copy constructor:
Copy constructor called for object at [0x61ff04], number = 42
Creating object with move constructor:
Move constructor called for object at [0x61ff00], number = 42
Exiting main function, objects will be destroyed in reverse order of creation.
Destructor called for object at [0x61ff00], number was 42
Destructor called for object at [0x61ff04], number was 42
Destructor called for object at [0x61ff08], number was 0
Destructor called for object at [0x61ff0c], number was 0
在上方的代码中,SimpleClass 类包含了一个整型成员 number 和四种构造函数以及一个析构函数:
在 main 函数中,创建了四个 SimpleClass 类型的对象,每个对象都使用不同的构造函数。随后,在程序退出时,这些对象按照创建的相反顺序被销毁,析构函数被调用,并打印出相关信息。
注意,由于 obj2 的内容被移动到了 obj4,所以 obj2 的 number 成员在析构时是0。
#include <iostream>
#include <chrono>
class Vector {
private:
int* data;
size_t size;
public:
Vector(size_t n) : size(n) {
data = new int[size];
for (size_t i = 0; i < size; ++i) {
data[i] = i;
}
}
// 拷贝构造函数
Vector(const Vector& other) : size(other.size) {
data = new int[size];
for (size_t i = 0; i < size; ++i) {
data[i] = other.data[i];
}
}
// 移动构造函数
Vector(Vector&& other) noexcept : data(other.data), size(other.size) {
other.data = nullptr;
other.size = 0;
}
~Vector() {
delete[] data;
}
};
int main() {
Vector v1(1000000);
// 使用拷贝构造函数
auto startCopy = std::chrono::high_resolution_clock::now();
Vector v2 = v1;
auto endCopy = std::chrono::high_resolution_clock::now();
// 使用移动构造函数
auto startMove = std::chrono::high_resolution_clock::now();
Vector v3 = std::move(v1);
auto endMove = std::chrono::high_resolution_clock::now();
auto durationCopy = std::chrono::duration_cast<std::chrono::microseconds>(endCopy - startCopy).count();
auto durationMove = std::chrono::duration_cast<std::chrono::microseconds>(endMove - startMove).count();
std::cout << "Time taken by copy constructor: " << durationCopy << " microseconds" << std::endl;
std::cout << "Time taken by move constructor: " << durationMove << " microseconds" << std::endl;
return 0;
}
输出结果:
Time taken by copy constructor: 1651 microseconds
Time taken by move constructor: 0 microseconds
在上方的main函数中,首先创建了一个大型Vector对象v1,然后分别使用拷贝构造函数和移动构造函数创建了两个新对象v2和v3。使用了std::chrono库来测量拷贝和移动操作所需的时间。由于移动构造函数避免了数据的复制,所以它的执行时间远远少于拷贝构造函数。
输出结果显示,拷贝构造函数用时1651微秒,而移动构造函数几乎不需要时间(0微秒),展示了移动语义在处理大型对象时的性能优势。