类的拷贝构造函数、赋值函数

    C++中,对于一个空的类,编译器一般默认它有4个成员函数:构造函数,拷贝构造函数、赋值函数和析构函数。
    构造函数的功能:在创建一个新的对象的时候给数据成员赋初值,即初始化对象。析构函数的功能:释放一个对象,在对象删除之前用它来做一些内存释放的清理工作。它们的典型应用:在构造函数中用new来为指针成员开辟一个独立的动态内存空间,而在析构函数中用delete来释放它。
    在C++中对一个对象的初始化可以是下面这样:
ClassName o1("object");//A:通过构造函数设定初始值
ClassName o3(o2);//B:通过指定的对象设定初始值
由上面的代码可以知道:B中将o2作为o3的初值,o3的初始化形式要调用相应的构造函数,但是此时找不到与之匹配的构造函数,因为ClassName类中没有哪个构造函数的形参是ClassName类的对象,由此引出ClassName所隐含的一个特殊的默认构造函数,其原型是:
ClassName(const ClassName &);
这种默认构造函数就称为默认的拷贝构造函数,仅仅拷贝了内存空间的内容,这种拷贝方式被称为浅拷贝。而对于数据成员有指针类型的类来说,默认的拷贝构造函数无法完成对其内容的拷贝,此时需要自己定义一个拷贝构造函数,然后在进行数值拷贝之前,必须为指针类型的数据成员重新开辟一个独立的内存空间,这种还需要另开辟新的内存空间的拷贝方式称为深拷贝。
  • 拷贝构造函数:其格式是带有参数的构造函数,实际上,拷贝操作的实质就是类的对象空间的引用,在C++的规定中就说拷贝构造函数的参数个数可以是1个或者多个,但是第一个参数必须是类的引用对象,参数的形式可以是类名 &对象名或者const 类名 &对象名的形式,这里的类名就是该拷贝构造函数所在的类的类名。

    一旦在类中定义了拷贝构造函数,那么隐式的默认拷贝构造函数就不再有效。

测试实例:

//MyString.h
#pragma once
#include <cstddef>//定义宏NULL的头文件
//#include <Object>
#include <iostream>
#include <string.h>

using namespace std;

class String {
public:
    String(const char *str = NULL);//普通构造函数
    String(const String &other);//拷贝构造函数
    ~String(void);//析构函数
    String & operator=(const String &other);//赋值函数
public:
    char *m_data;
};
//MyString.cpp
#pragma warning(disable:4996)//解决strcpy编译不通过问题
#include "MyString.h"
#include <string.h>
/*
 *普通构造函数
 *构造函数首先根据一个字符串常量创建一个String对象
 *这个构造函数首先分配了足够的内存,然后把这个字符串常量复制到这块内存
 */

String::String(const char *str) {
    if (str == NULL) {
        m_data = new char[1];
        *m_data = '\0';
    }
    else {
        int length = strlen(str);
        m_data = new char[length + 1];
        strcpy(m_data, str);
    }
}

/*
 *拷贝构造函数
 *所有需要分配系统资源的用户定义类型都需要一个拷贝构造函数
 *它可以在函数调用中以传值的方式传递一个String类型的参数
 *并且在一个函数以值的形式返回String对象时实现“返回时复制”
 */

String::String(const String &other) {
    int length = strlen(other.m_data);
    m_data = new char[length + 1];
    strcpy(m_data, other.m_data);
}

/*
 *定义析构函数是为了防止内存泄露,当一个String对象超出它的
 *作用域时,析构函数就会释放它所占用的内存
 */

String::~String(void) {
    delete[]m_data;//m_data是内部数据类型
}

/*
 *赋值函数实现字符串的传值活动
 */
String & String::operator=(const String &other) {
    if (this == &other)//检查自赋值
        return *this;
    delete[]m_data;
    int length = strlen(other.m_data);//分配新的内存资源并复制其内容
    m_data = new char[length + 1];
    strcpy(m_data, other.m_data);
    return *this;//返回本对象的引用
}
//main.cpp
#include "MyString.h"
#include <iostream>

using namespace std;

int main() {
    String MyString("My first String test!!!");
    String MyString2, MyString3 = MyString;
    MyString2 = MyString;
    cout << "MyString:" << MyString.m_data << endl<<
        "MyString2:" << MyString2.m_data <<endl<< 
        "MyString3:" << MyString3.m_data;
    system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值