C++中的拷贝构造详解
什么是拷贝构造函数
拷贝构造函数是C++类中的一种构造函数,用于创建对象的副本。当原对象被传递给一个函数或以值的方式返回时,拷贝构造函数被调用来创建一个新的对象,该新对象是原对象的一个完全拷贝。拷贝构造函数的原型通常是:ClassName(const ClassName& obj);
。
在某些情况下,编译器会自动生成拷贝构造函数。但在定义类时,我们也可以写自己的拷贝构造函数来控制如何创建新对象的副本。
拷贝构造函数的语法
拷贝构造函数的声明和定义都有一些要求:
ClassName(const ClassName& obj) {
// 拷贝构造函数的实现
}
- 拷贝构造函数应采用传参方式而不是返回类型方式。
- 参数应为常量引用。在C++中,引用通常是比复制对象更好的方式,而常量引用可以避免误修改原始对象的风险。
- 拷贝构造函数的实现方法通常是将源对象的数据成员一一复制到新的对象中。
拷贝构造函数的使用
下面是一个简单类的定义,其中包含自己的拷贝构造函数:
class Person {
public:
int age;
double height;
// 拷贝构造函数
Person(const Person &p) {
age = p.age;
height = p.height;
}
// 构造函数
Person(int a, double h) {
age = a;
height = h;
}
};
现在我们可以创建一个对象并将其拷贝到新对象中,使用代码如下:
int main() {
Person p1(20, 1.8);
Person p2 = p1;
}
这里我们创建了一个p1对象,然后将该对象拷贝到p2中。这将调用拷贝构造函数,为p2创建一个新的、完全相同的Person对象。
拷贝构造函数的使用示例
以下示例展示了如何使用拷贝构造函数来创建对象的深拷贝和浅拷贝。
浅拷贝
在这个示例中,Person
类中的str
成员是一个指针,指向存储在堆内存中的字符串。由于默认的拷贝构造函数实现只会复制指针本身,因此在执行浅拷贝时,它们所指的内存地址是相同的,这可能导致内存泄漏和其他问题。
#include <iostream>
#include <cstring>
class Person {
public:
char* str;
int age;
Person():str(nullptr), age(0) {}
Person(const char* s, int a):str(nullptr), age(a) {
if (s) {
str = new char[strlen(s) + 1];
strcpy(str, s);
}
}
~Person() {
delete [] str;
}
void print() {
std::cout<<"age: "<< age<< " str: "<< str<<std::endl;
}
};
int main() {
Person p1("Mike", 18);
Person p2 = p1; //浅拷贝
p1.print();
p2.print();
return 0;
}
输出结果:
age: 18 str: Mike
age: 18 str: Mike
注意到,在浅拷贝示例中,两个Person对象的str
成员的地址是相同的,这可能导致内存泄漏和其他问题。
深拷贝
为了解决上述问题,需要自定义拷贝构造函数,实现成员变量的深拷贝。
#include <iostream>
#include <cstring>
class Person {
public:
char* str;
int age;
Person():str(nullptr), age(0) {}
Person(const char* s, int a):str(nullptr), age(a) {
if (s) {
str = new char[strlen(s) + 1];
strcpy(str, s);
}
}
// 拷贝构造函数: 深拷贝成员变量
Person(const Person& other):str(nullptr), age(other.age) {
if (other.str) {
str = new char[strlen(other.str) + 1];
strcpy(str, other.str);
}
}
~Person() {
delete [] str;
}
void print() {
std::cout<<"age: "<< age<< " str: "<< str<<std::endl;
}
};
int main() {
Person p1("Mike", 18);
Person p2 = p1; // 深拷贝
p1.print();
p2.print();
return 0;
}
输出结果:
age: 18 str: Mike
age: 18 str: Mike
注意到,在深拷贝示例中,两个Person对象的str
成员的地址是不同的,它们指向不同的内存地址,也不存在内存泄漏和其他问题。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++中的拷贝构造详解 - Python技术站