C++ Copy Constructor (拷贝构造函数,复制构造函数)

1.什么是Copy Constructor?


Copy Constructor 是一个特殊的构造函数,一般只有一个参数,这个参数一般是用const修饰的,对自己类的一个引用(reference)。什么时候会用到Copy Constructor?

当我们定义一个对象时,它是由另外一个对象来初始化的时候就用到Copy Constructor了。还有就是在一个方法以值作为参数传进去或者一个方法中以值作为返回。

对于我这新手C++,Copy Constructor 用的比较少,真正用到了也不知道,因为一个类缺少 Copy Constructor 时,编译器会自动生成一个。


2.赶快来看一个Copy Constructor例子


2.1系统默认会提供一个Copy Constructor


class People{
private:
	int m_age;
public:
	People(int age):m_age(age){
		cout << "constructor" << endl;
	}

	~People(){
		cout << "destructor" << endl;
	}
	int getAge() const{
		return m_age;
	}
};

一个简单的类,叫People,只有一个属性age

People p1(18);
 cout << "p1's age " << p1.getAge() << endl;
 People p2(p1);
 cout << "p2's age " << p2.getAge() << endl;

当我们调用上面的代码时的输出结果就是:



代码工作非常符合我们预期,因为系统会提供一个Copy Constructor,对类里的属性进行简单的赋值工作。


2.2自定义的Copy Constructor


class People{
private:
 int m_age;
public:
 People(int age):m_age(age){
  cout << "constructor" << endl;
 }
    //copy constructor
 People(const People& p){
  cout << "copy constructor" << endl;
 }

 ~People(){
  cout << "destructor" << endl;
 }
 int getAge() const{
  return m_age;
 }
};
People p1(18);
 cout << "p1's age " << p1.getAge() << endl;
 People p2(p1);
 cout << "p2's age " << p2.getAge() << endl;


这次我们自定义了一个Copy Constructor

还是调用上次的代码,结果:



看,成功的调用了我们的copy constructor,因为我们的copy constructor 里什么也没做,所以p2的age就是一个未初始化的int值了。


2.3还有两种情况会触发调用Copy constructor


//作为一个值从函数中返回
People getPeople(){
	People p1(20);
	return p1;//会调用 copy constructor
}
//以值作为参数传入
void setPeople(People p1){//以值传入会调用 copy constructor
	//do nothing
}

void setPeople(People& p1){//以引用传入不会调用 copy constructor
	//do nothing
}

因为调用copy constructor的消耗比较大,所以一般都以引用方式作为函数参数。


3. copy constructor 与 assignment operator 的区别


我们忘记提到的是下面这种写法也会触发copy constructor:

People p1(18);
	cout << "p1's age " << p1.getAge() << endl;
	People p2 = p1;
	cout << "p2's age " << p2.getAge() << endl;

这种写法似乎跟赋值很像。

我们修改People的类,增加重载=操作符。

class People{
private:
	int m_age;
public:
	People(int age):m_age(age){
		cout << "constructor" << endl;
	}

	People(const People& p){
		cout << "copy constructor" << endl;
	}

	People& operator=(const People& p1){
  cout << "assignment operator" << endl;
  m_age = p1.getAge();
  return *this;
 }

	~People(){
		cout << "destructor" << endl;
	}
	int getAge() const{
		return m_age;
	}
};
//测试代码
People p1(18);
 cout << "p1's age " << p1.getAge() << endl;
 People p2 = p1;
 cout << "p2's age " << p2.getAge() << endl;
 p2 = p1;
cout << p2.getAge() << endl;



通过上面的输出结果我们发现:

= 什么时候会调用Copy Constructor呢?在初始化的时候,也就是第一个 People p2 = p1。因为Copy Constructor 是一种 Constructor,也是负责初始化的。

什么时候=是赋值呢?两个都已经初始化,再调用=就是赋值了。


4. 浅拷贝和深拷贝


我们上面的类People只有一个简单的属性age,还是int类型的,进行简单的赋值就是浅拷贝,但是People类将来会变的复杂起来,后面可能会增加指针类型的属性。那么就会涉及到深拷贝了。

我的理解就是:浅拷贝:两个变量进行浅拷贝时,它们指向同一个地址,它们的值相同。这样会有问题,当其中的一个析构了那个地址,另外一个也没有了,有时候会发生错误,但浅拷贝比较廉价。

深拷贝:两个变量进行深拷贝时,第二变量会重新申请一块区域来存放跟第一个变量指向地址的值。两个东西完全是独立的,只是值相同。消耗比较大,因为要重新申请空间。

关于Copy Constructor,就先这样吧。


5.禁用Copy Constructor


把Copy Constructor设置为private就行了。以我的水平,我还不知道什么情况要这样做 =。=

C++ Copy Constructor (拷贝构造函数,复制构造函数)


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在 C++ 中,拷贝构造函数Copy Constructor)是一种特殊的构造函数,用于创建一个新对象并将其初始化为同类的另一个对象的副本。拷贝构造函数的原型为: ``` class MyClass { public: MyClass(const MyClass& other); // 拷贝构造函数 // ... }; ``` 其中,`other` 是一个同类的对象,拷贝构造函数的作用是将 `other` 的数据成员复制到新创建的对象中。 拷贝构造函数可以通过以下方式进行调用: - 当一个对象用另一个对象进行初始化时,就会调用拷贝构造函数; - 当一个函数的参数是一个对象时,也会调用拷贝构造函数; - 当一个函数的返回值是一个对象时,也会调用拷贝构造函数。 需要注意的是,如果类中没有定义拷贝构造函数,编译器会自动生成一个默认的拷贝构造函数,它的行为是将一个对象的每个非静态成员变量复制到新对象中。但是,如果类中有指针成员变量或者资源管理的成员变量,需要手动定义拷贝构造函数,以确保正确的拷贝和释放资源。 下面是一个示例代码,演示了拷贝构造函数的用法: ```c++ #include <iostream> using namespace std; class MyClass { public: int value; MyClass() { // 默认构造函数 cout << "default constructor called" << endl; value = 0; } MyClass(int n) { // 带参数的构造函数 cout << "constructor with int called" << endl; value = n; } MyClass(const MyClass& other) { // 拷贝构造函数 cout << "copy constructor called" << endl; value = other.value; } }; void func(MyClass obj) { // 参数是对象,会调用拷贝构造函数 cout << "value in func: " << obj.value << endl; } MyClass returnObj() { // 返回值是对象,会调用拷贝构造函数 MyClass obj(100); return obj; } int main() { MyClass a(10); // 带参数的构造函数 MyClass b(a); // 拷贝构造函数 MyClass c = b; // 拷贝构造函数 func(c); // 拷贝构造函数 MyClass d = returnObj(); // 拷贝构造函数 return 0; } ``` 在上面的代码中,当我们定义对象 `a` 时,使用了带参数的构造函数;当我们定义对象 `b` 和 `c` 时,使用了拷贝构造函数;当我们调用函数 `func` 时,函数参数是一个对象,会调用拷贝构造函数;当我们调用函数 `returnObj` 时,返回值是一个对象,也会调用拷贝构造函数
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值