拷贝构造(详解)
一、拷贝构造函数
拷贝构造函数,就像他的名字一样,使来拷贝的,他的作用是把一个已经存在的对象进行拷贝后,用拷贝来的值进行给其他对象赋值和作为返回值和参数等。
一、拷贝构造函数调用时机
拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:拷贝构造的参数是引用类型
- 通过使用另一个同类型的对象来初始化新创建的对象。
- 复制对象把它作为参数传递给函数。
- 复制对象,并从函数返回这个对象。
下面我们来看一个拷贝构造函数的例子:
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class person {
public:
int age;
person() {
cout << "调用无参构造" << endl;
}
person(int age) {
this->age = age;
cout << "调用有参构造" << endl;
}
person(const person&other) {
cout << "调用拷贝构造" << endl;
this->age = other.age;
}
~person() {
cout << "调用析构函数" << endl;
}
};
void fun(person other) {
//参数以值的形式传递的时后掉用拷贝构造,不能是引用
}
person fun() {
person p;
return p;
}
void t1() {
person p;
person p1 = p;//用已经存在的对象初始化新对象隐式调用
person p2;
p2 = p;//不调用拷贝构造,这是赋值过程
}
void t2() {
person p;
fun(p);
}
void t3() {
fun();
}
int main() {
t3();
return 0;
}
二、深拷贝浅拷贝
说到拷贝构造函数就不得不提到深拷贝浅拷贝的概念
深拷贝:对对象进行全面的复制,重新的创建堆区内存,把原对象中的数据复制到新地址中。
浅拷贝:简单的赋值过程,只是将内存的地址赋值给另一个变量,不重新申请内存空间,这样就出现了一个问题,就是在释放内存时会出现同一块内存被释放两次的情况。
地址存储变量1=地址1123 | 析构将内存归还操作系统 |
内存1123 | 内存1123被释放 |
地址存储变量2=地址1123 | 此对象析构函数也要调释放内存1123但是此内存已经归还操作系统找不到了,报错 |
下面我们来看深拷贝和浅拷贝的例子:
浅拷贝
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class person {
public:
int age;
int* p;
person() {
cout << "调用无参构造" << endl;
age = 0;
p = nullptr;
}
person(int age) {
this->age = age;
this->p = new int[age];
for (int i = 0;i < age;i++) {
p[i] = i;
}
cout << "调用有参构造" << endl;
}
person(const person&other) {
cout << "调用拷贝构造" << endl;
this->age = other.age;
this->p = other.p;//浅拷贝;两个对象中的成员指针变量指向同一块地址
//此代码运行会有错误,析构函数会非法访问
}
~person() {
cout << "调用析构函数" << endl;
}
};
void fun(person p) {
//参数以值的形式传递的时后掉用拷贝构造,不能是引用
}
person fun() {
person p;
return p;
}
void t1() {
person p;
person p1 = p;//隐式调用
person p2;
p2 = p;//不调用拷贝构造,这是赋值过程
}
void t2() {
person p;
fun(p);//实参初始化形参调用
}
void t3() {
fun();
}
int main() {
t3();
return 0;
}
深拷贝
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class person {
public:
int age;
int* p;
person() {
cout << "调用无参构造" << endl;
age = 0;
p = nullptr;
}
person(int age) {
this->age = age;
this->p = new int[age];
for (int i = 0;i < age;i++) {
p[i] = i;
}
cout << "调用有参构造" << endl;
}
person(const person&other) {
cout << "调用拷贝构造" << endl;
this->age = other.age;
//深拷贝:指向的内存地址不同但是内容大小相同
this->p = new int[age];//大小一样
for (int i = 0;i < age;i++) {//内容一样
this->p[i] = other.p[i];
}
}
~person() {
cout << "调用析构函数" << endl;
}
};
void fun(person p) {
//参数以值的形式传递的时后掉用拷贝构造,不能是引用
}
person fun() {
person p;
return p;
}
void t1() {
person p;
person p1 = p;//隐式调用
person p2;
p2 = p;//不调用拷贝构造,这是赋值过程
}
void t2() {
person p;
fun(p);//实参初始化形参调用
}
void t3() {
fun();
}
int main() {
t3();
return 0;
}