C++拷贝构造函数

利用new在堆区创建的对象,被复制时(按对象值传参),将复制对象的指针成员,但不复制指针成员指向的缓冲区

结果是两个对象指向同一块动态分配的内存,销毁其中一个对象时 - delete释放内存块,导致另一个对象存储的指针拷贝无效。

【编译器执行二进制复制:复制 整型、字符和原始指针 等POD数据,不复制 指针指向的内存单元】

 

没有原始指针成员的情况下,不需要编写拷贝构造函数。因为编译器添加的默认拷贝构造函数 将调用成员对象的拷贝构造函数。

拷贝构造函数:一个重载的构造函数,由编写类的程序员提供。当对象被复制时,编译器会调用拷贝构造函数。

拷贝构造函数接受一个 以引用方式传入的当前类的对象 作为参数,这个参数是 原对象的别名,使用它编写拷贝构造函数,确保对所有缓冲区进行深复制

【拷贝构造函数的参数 必须按引用传递,否则拷贝构造函数将不断调用自己(形参不断拷贝实参),直到耗尽系统的内存为止。】

//test.h

#include <iostream>
#include <stdlib.h>
#include <string>
#include <string.h>
using namespace std;

class MyString {
private:
	char* buffer;   //指针成员变量,都是它惹的祸~
public:
	MyString(const char* initString);
	MyString(const MyString& copySource);
	~MyString();
	int GetLen();
	const char* GetStr();
};

//test.cpp

#include "class_basic.h"

 MyString::MyString(const char* initString) {
	 buffer = NULL;
	 cout << "Default constructor:creating new MyString" << endl;
	if (initString != NULL) {
		buffer = new char[strlen(initString) + 1];
		strcpy(buffer, initString);
		cout << "buffer points to: 0x" << hex;
		cout << (unsigned int*)buffer << endl;
	}
}

 MyString::MyString(const MyString& copySource) {   
//调用拷贝构造函数时,形参copySource和传入的实参 指向同一块内存(引用属性),这里用buffer实现深拷贝
	 buffer = NULL;
	 cout << "Copy constructor: copying from MyString" << endl;
	 if (copySource.buffer != NULL) {
		 buffer = new char[strlen(copySource.buffer) + 1];
		 strcpy(buffer, copySource.buffer);
		 cout << "buffer points to:0x" << hex;
		 cout << (unsigned int*)buffer << endl;
	 }
}

MyString::~MyString() {
	cout << "Invoking destructor, clearing up" << endl;
	delete[] buffer;
}

int MyString::GetLen() {
	return strlen(buffer);
}

const char* MyString::GetStr() {
	return buffer;
}


//main.cpp

#include<string>
#include<iostream>
#include<stdlib.h>
#include<string>
#include "test.h"
using namespace std;

void UseMyString(MyString str) {   //按值传参
	cout << "String buffer in MyString is " << str.GetLen();
	cout << " character long" << endl;
	cout << "buffer contains: " << str.GetStr() << endl;
	return;
}


int main()
{
	MyString sayHello("Hello from String Class");
	UseMyString(sayHello);   //sayHello按值传递给形参str,调用拷贝构造函数
        system("pause");
        return 0;
}

//O: Default constructor:creating new MyString
//   buffer points to: 0x00FD6A58
//   Copy constructor: copying from MyString
//   buffer points to:0x00FE0828
//   String buffer in MyString is 17 character long
//   buffer contains: Hello from String Class
//   Invoking destructor, clearing up

如果UseMyString的参数是按引用传递,则不需要拷贝构造函数,因为引用传参时,函数里使用的就是sayHello对象自己,不需要额外开辟内存。退出UseMyString函数时,也不需要释放内存。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值