C++中的移动构造函数及move语句示例详解
什么是移动构造函数?
移动构造函数是C++11中新增的一种特殊的构造函数,用于在对象的移动语义下构造新对象。在C++中,移动构造函数的函数名为“移动构造函数”,使用特定的语法和方法来定义。对象在移动语义下被移动时,移动构造函数会被自动调用,其中源对象的数据块会被转移,并被用于新的对象的构造中。
移动构造函数通常用于具有大量内存使用的对象,如字符串、容器等。通过移动构造函数,避免不必要的内存拷贝操作,提高程序性能。
移动构造函数的格式如下:
class ClassName {
public:
ClassName(ClassName&&); // 移动构造函数
};
其中 ClassName&&
表示右值引用,用于接收源对象。在移动构造函数中,需要利用其他函数如 std::move()
来实现移动语义下的对象转移。
什么是move语句?
move语句是C++11中新增的标准库函数,在实现移动语义下的对象转移时非常有用。move语句本质上是一种类型转换操作,用于将左值类型的对象转换为右值引用类型的对象,从而实现移动语义下的对象转移。move语句的格式如下:
std::move(x);
其中 x
表示左值对象, std::move()
表示将 x
转换为右值引用类型的对象。注意,调用 std::move()
函数后,原对象的值可能会被修改或破坏。
示例1:移动构造函数使用
下面是一个字符串类 String
的示例,其中定义了移动构造函数:
#include <iostream>
#include <string.h>
class String {
private:
char* m_data;
int m_length;
public:
String(const char* data) {
m_length = strlen(data);
m_data = new char[m_length + 1];
strcpy(m_data, data);
}
// 移动构造函数
String(String&& other) : m_data(nullptr), m_length(0) {
std::cout << "Move constructor is called!" << std::endl;
m_data = other.m_data;
m_length = other.m_length;
other.m_data = nullptr;
other.m_length = 0;
}
~String() {
delete[] m_data;
}
const char* GetData() const {
return m_data;
}
};
int main() {
String str1("Hello, world!");
String str2(std::move(str1)); // 使用移动构造函数
std::cout << "str1 data: " << str1.GetData() << std::endl; // 输出为空指针
std::cout << "str2 data: " << str2.GetData() << std::endl; // 输出 "Hello, world!"
return 0;
}
在上面的示例中,我们定义了一个字符串类 String
,其中定义了一个移动构造函数。在 main()
函数中,我们创建了 str1
和 str2
两个字符串对象,然后使用 std::move()
函数来将 str1
转换为右值引用,并将其作为参数传递给 str2
的构造函数。在这个过程中,移动构造函数被自动调用,完成了源对象到新对象的数据转移。
需要注意的是,在移动构造函数中,源对象的数据被转移到了新对象中,并且源对象的指针被置为 nullptr
。这是为了防止源对象被误用。因此,在 main()
函数中,输出 str1
的数据时,输出为空指针。而输出 str2
的数据时,输出的是源对象的数据,即 "Hello, world!"。
示例2:move语句的使用
下面是一个容器类模板 Array
的示例,其中使用了 std::move()
函数:
#include <iostream>
#include <utility>
template <typename T>
class Array {
private:
T* m_data;
size_t m_size;
public:
explicit Array(size_t size) : m_data(new T[size]), m_size(size) {}
Array(const Array& other) : m_data(new T[other.m_size]), m_size(other.m_size) {
for (size_t i = 0; i < m_size; i++) {
m_data[i] = other.m_data[i];
}
}
Array(Array&& other) : m_data(nullptr), m_size(0) {
std::cout << "Move constructor is called!" << std::endl;
m_data = other.m_data;
m_size = other.m_size;
other.m_data = nullptr;
other.m_size = 0;
}
~Array() {
delete[] m_data;
}
T& operator[](size_t index) {
return m_data[index];
}
const T& operator[](size_t index) const {
return m_data[index];
}
size_t Size() const {
return m_size;
}
};
int main() {
Array<int> arr1(10);
for (size_t i = 0; i < arr1.Size(); i++) {
arr1[i] = i;
}
Array<int> arr2(std::move(arr1)); // 使用std::move()
std::cout << "arr1 size: " << arr1.Size() << std::endl; // 输出 0
std::cout << "arr2 size: " << arr2.Size() << std::endl; // 输出 10
for (size_t i = 0; i < arr2.Size(); i++) {
std::cout << arr2[i] << " ";
}
std::cout << std::endl;
return 0;
}
在上面的示例中,我们定义了一个容器类模板 Array
,其中包含了一个移动构造函数。在 main()
函数中,我们创建了 arr1
和 arr2
两个 Array
类型的对象,然后使用 std::move()
函数将 arr1
转换为右值引用,并将其作为参数传递给 arr2
的构造函数。
需要注意的是,在 Array
类型的移动构造函数中,我们使用了 std::move()
函数来将源对象的 m_data
指针转换为右值引用类型。如此一来,源对象的 m_data
指针就被移动到了新对象中,避免了不必要的内存拷贝操作。
在 main()
函数中,输出 arr1
和 arr2
的大小可以看到,移动构造函数实现了源对象到新对象的数据转移,同时避免了不必要的内存拷贝操作。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++中的移动构造函数及move语句示例详解 - Python技术站