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

来源:互联网 发布:淘宝古着店灵异经过 编辑:程序博客网 时间:2024/06/05 15:29
    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
原创粉丝点击