C++中浅复制及其存在的问题

C++中浅复制及其存在的问题

之前的示例程序中 MyString 类包含一个指针成员 buffer,它指向动态分配的内存(这些内存是在构造函数中使用 new 分配的,并在析构函数中使用 delete[]进行释放)。复制这个类的对象时,将复制其指针成员,但不复制指针指向的缓冲区,其结果是两个对象指向同一块动态分配的内存。销毁其中一个对象时, delete[]释放这个内存块,导致另一个对象存储的指针拷贝无效。这种复制被称为浅复制,会威胁程序的稳定性,如以下示例程序所示:

#include 
#include 
using namespace std;

class MyString
{
private:
    char* buffer;

public:
    MyString(const char* initString) // Constructor
    {
        buffer = NULL;
        if(initString != NULL)
        {
            buffer = new char [strlen(initString) + 1];
            strcpy(buffer, initString);
        }
    }

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

    int GetLength() 
    { return strlen(buffer); }

    const char* GetString()
    { return buffer; }
};

void UseMyString(MyString str)
{
    cout << "String buffer in MyString is " << str.GetLength();
    cout << " characters long" << endl;

    cout << "buffer contains: " << str.GetString() << endl;
    return;
}

int main()
{
    MyString sayHello("Hello from String Class");
    UseMyString(sayHello); 

    return 0;
}

输出:

String buffer in MyString is 23 characters long
buffer contains: Hello from String Class
Invoking destructor, clearing up
Invoking destructor, clearing up

分析:

在之前的程序中运行正常的 MyString 类, 为何会导致现在这个程序崩溃呢?相比于以前的程序,现在这个程序唯一不同的地方在于,在 main( )中,将使用 MyString 对象 sayHello 的工作交给了函数UseMyString(),如第 44 行所示。在 main( )中将工作交给这个函数的结果是,对象 sayHello 被复制到形参 str,并在 UseMyString( )中使用它。编译器之所以进行复制,是因为函数 UseMyString( )的参数 str 被声明为按值(而不是按引用)传递。对于整型、字符和原始指针等 POD 数据,编译器执行二进制复制,因此 sayHello.buffer 包含的指针值被复制到 str 中,即 sayHello.buffer 和 str.buffer 指向同一个内存单元,如图 9.3 所示。
二进制复制不复制指向的内存单元,这导致两个 MyString 对象指向同一个内存单元。函数UseMyString( )返回时,变量 str 不再在作用域内,因此被销毁。为此,将调用 MyString 类的析构函数,而该析构函数使用 delete[]释放分配给 buffer 的内存(如程序清单 9.8 的第 22 行所示)。这将导致 main( ) 中的对象 sayHello 指向的内存无效,而等 main( )执行完毕时, sayHello 将不再在作用域内,进而被销
毁。但这次第 22 行对不再有效的内存地址调用 delete(销毁 str 时释放了该内存,导致它无效)。正是这种重复调用 delete 导致了程序崩溃。

该文章会更新,欢迎大家批评指正。

推荐一个零声学院的C++服务器开发课程,个人觉得老师讲得不错,
分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容
点击立即学习:C/C++后台高级服务器课程

你可能感兴趣的:(C++编程基础,c++)