【45】C++中的复制与拷贝构造函数

本文探讨了C++中string类浅拷贝和深拷贝的区别,通过示例展示了如何避免内存泄漏,以及何时选择深拷贝以确保对象独立性。重点介绍了浅拷贝的不足和深拷贝的实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【45】C++的复制与拷贝构造函数

示例:string类的浅拷贝

#include <iostream>
#include <string>

class String
{
private:
    char* m_Buffer;
    unsigned int m_Size;
public:
    String(const char* string)
    {
        m_Size = strlen(string);
        m_Buffer = new char[m_Size + 1];
        memcpy(m_Buffer, string, m_Size + 1); //memcpy(m_Buffer, string, m_Size);
        // m_Buffer[m_Size] = '\0';
    }
    
    ~String()
    {
        delete[] m_Buffer;
    }
    friend std::ostream& operator<<(std::ostream& stream, const string& string);
};

std::ostream& operator<<(std::ostream& stream, const string& string)
{
    stream << string.m_Buffer;
    return stream;
}

int main()
{
    String string = "Cherno";
    String second = string;
    std::cout << string << second << std::endl;
    return 0;
}

该程序运行完后,编译器会抛出异常(系统崩溃),这是由于second只是简单地复制了string的指针,即second与string都指向了同一个内存空间,当程序结束后,析构函数调用了两次,即释放了两次内存,这正是系统报错的原因。

在一般情况下,如果我们用旧对象复制构造生成新对象,C++会自动调用默认构造函数,执行浅拷贝操作 (简单地复制对象的内容)。

我们想要实现的是string和second各自都有内存空间,并且指向各自的内存空间,而不是指向同一段内存空间。

示例:string类的深拷贝

#include <iostream>
#include <string>

class String
{
private:
    char* m_Buffer;
    unsigned int m_Size;
public:
    String(const char* string)
    {
        m_Size = strlen(string);
        m_Buffer = new char[m_Size + 1];
        memcpy(m_Buffer, string, m_Size + 1); //memcpy(m_Buffer, string, m_Size);
        // m_Buffer[m_Size] = '\0';
    }
    
    String(const String& other)
        : m_Size(other.m_Size)
    {
        m_Buffer = new char[m_Size + 1];
        memcpy(m_Buffer, other.m_Buffer, m_Size);
    }
    
    ~String()
    {
        delete[] m_Buffer;
    }
    
    char& operator[](unsigned int index)
    {
        return m_Buffer[index];
    }
    
    friend std::ostream& operator<<(std::ostream& stream, const string& string);
};

std::ostream& operator<<(std::ostream& stream, const string& string)
{
    stream << string.m_Buffer;
    return stream;
}

int main()
{
    String string = "Cherno";
    String second = string;
    second[2] = 'a';
    std::cout << string << std::endl; // Cherno
    std::cout << second << std::endl; // Charno
    return 0;
}

以上就是string类的深拷贝函数,当我们修改second的第二个字符时,我们会发现string并没有也进行修改,它们指向不同的内存空间。

另外,当我们要使用类来当做函数的形参时,首先要考虑在函数体是否要修改对象,如果不修改,一定要在对象的类型参数前加上const,而且要加上&(引用),来避免调用拷贝构造函数造成不必要的内存开销与时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Balaaam

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值