C++中的复制操作包含深复制和浅复制两种方式。简单来说,浅复制只复制指针而不复制指针指向的内存空间,而深复制会复制指针和指针指向的内存空间。
一般情况下,我们需要使用深复制,以避免浅复制造成指针指向错误的情况。
深复制的实现方式
在C++中,可以通过使用拷贝构造函数和赋值操作符实现深复制。
拷贝构造函数
拷贝构造函数是一种特殊的构造函数,用于在创建对象时,用已存在的对象来初始化新创建的对象。在深复制时,需要在新的对象中重新分配空间,将原始对象的值复制到新的对象中。
以下是一个使用拷贝构造函数实现深复制的示例代码:
#include <iostream>
class MyString{
private:
char *str;
int len;
public:
MyString(const char *s){
len = strlen(s);
str = new char[len+1];
strcpy(str, s);
}
// 拷贝构造函数
MyString(const MyString &src){
len = src.len;
str = new char[len+1];
strcpy(str, src.str);
}
~MyString(){
delete[] str;
}
char* getString(){
return str;
}
};
int main(){
MyString str1("Hello World!");
std::cout << "str1: " << str1.getString() << std::endl;
MyString str2 = str1; // 拷贝构造函数
std::cout << "str2: " << str2.getString() << std::endl;
return 0;
}
在以上示例中,我们通过拷贝构造函数实现了深复制。我们创建了一个MyString
对象str1
,并将其值设置为"Hello World!"
。接着,我们通过MyString str2 = str1;
语句创建了另一个MyString
对象str2
。C++编译器默认调用拷贝构造函数来进行对象的拷贝操作。在拷贝构造函数中,我们重新分配了内存空间,并将原始对象的值复制到了新的对象中。
赋值操作符
C++中的赋值操作符用于将一个对象的值赋给另一个对象。在深复制时,我们需要在新的对象中重新分配空间,并将原始对象的值复制到新的对象中。为了实现深复制,我们需要自定义赋值操作符,而不是仅仅使用编译器默认的赋值操作符。
以下是一个使用自定义赋值操作符实现深复制的示例代码:
#include <iostream>
class MyString{
private:
char *str;
int len;
public:
MyString(const char *s){
len = strlen(s);
str = new char[len+1];
strcpy(str, s);
}
MyString &operator=(const MyString &src){
if (this == &src) // 检查自我赋值情况
return *this;
delete [] str; // 释放原有内存
len = src.len;
str = new char [len+1];
strcpy(str, src.str);
return *this; // 返回对象的引用
}
~MyString(){
delete[] str;
}
char* getString(){
return str;
}
};
int main(){
MyString str1("Hello World!");
std::cout << "str1: " << str1.getString() << std::endl;
MyString str2("Goodbye World!");
std::cout << "str2: " << str2.getString() << std::endl;
str2 = str1; // 赋值操作符
std::cout << "str2: " << str2.getString() << std::endl;
return 0;
}
在以上示例中,我们定义了一个MyString
类的赋值操作符,用于实现深复制。该赋值操作符使用了与拷贝构造函数相同的实现方式,重新分配了内存空间,并将原始对象的值复制到新的对象中。和拷贝构造函数一样,我们不能忘记在对象生命周期结束时释放所占用的内存,否则可能会导致内存泄漏或其他不可预测的行为。
浅复制的实现方式
浅复制只复制指针,而不复制指针所指向的内存空间。由于浅复制没有重新分配内存,当原始对象和新对象都指向同一块内存空间时,就可能出现指向错误的情况。通常情况下,我们不想使用浅复制。然而,在某些情况下,浅复制可以作为一种优化手段来使用,例如,当我们操作大型数据类型时,使用浅复制可以减少操作的开销。
以下是一个使用浅复制实现的示例代码:
#include <iostream>
class MyIntArray{
private:
int *array;
int size;
public:
MyIntArray(int s=0): size(s){
array = new int[size];
}
MyIntArray(const MyIntArray &src){
size = src.size;
array = src.array; // 浅复制
}
~MyIntArray(){
delete [] array;
}
int& operator[](int i){
return array[i];
}
};
int main(){
MyIntArray arr1(5);
arr1[0] = 1;
arr1[1] = 2;
arr1[2] = 3;
arr1[3] = 4;
arr1[4] = 5;
MyIntArray arr2 = arr1; // 浅复制
arr2[4] = 10;
std::cout << "arr1[4]: " << arr1[4] << std::endl;
std::cout << "arr2[4]: " << arr2[4] << std::endl;
return 0;
}
在以上示例中,我们定义了一个MyIntArray
类,该类包含一个整型数组和大小。我们在构造函数中分配了内存空间来存储整型数组。在拷贝构造函数中,我们使用了浅复制来实现复制对象的操作。在上面示例中,我们创建了一个MyIntArray
对象arr1
,将其大小设置为5,并分配内存空间来存储5个整数。接着,我们将arr1
的前四个元素分别设置为"1"、"2"、"3"、"4",最后一个元素设置为"5"。之后,我们创建了另一个MyIntArray
对象arr2
,将其初始化为arr1
的一个副本。当我们修改arr2
的最后一个元素时,arr1
的最后一个元素也会被修改。这是因为浅复制只复制了指针,arr1
和arr2
指向的是同一块内存空间。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++深复制和浅复制讲解 - Python技术站