zoukankan      html  css  js  c++  java
  • 容器元素的深拷贝和浅拷贝问题

    STL容器所提供的都是值(value)寓意,而非引用(reference)寓意,也就是说当我们给容器中插入元素的时候容器内部实施了拷贝动作,将我们要插入的元素再另行拷贝一份放入到容器中,而不是将原数据元素直接放进容器中,也就说我们提供的元素必须能够被拷贝 .

    看下面的代码:

    //容器元素的深拷贝和浅拷贝问题
    #include "pch.h"
    #include <iostream>
    #include <vector>
    #include <cstdlib>
    using namespace std;
    
    class CDemo
    {
    public:
    	CDemo() :str(NULL) {}
    	~CDemo()
    	{
    		if (str)
    		{
    			delete[] str;
    		}
    		
    	}
    	char* str;  //指针,容易带来浅拷贝的问题
    };
    
    int main()
    {
    	CDemo d1;
    	d1.str = new char[32];
    	strcpy_s(d1.str,strlen("trend micro") + 1,"trend micro");
    
    	vector<CDemo>* a1 = new vector<CDemo>;
    	a1->push_back(d1);  //只是简单的值拷贝
    	delete a1;  //同一块内存析构了两次
    	return 0;
    }
    
    

    这个程序在退出的时候会出现问题,重复delete同一片内存,程序崩溃。
    将析构函数修改如下,可以更加清楚的看到问题所在:

    	~CDemo()
    	{
    		if (str)
    		{
    			static int i = 0;
    			cout << "&CDemo" << i++ << "=" << (int*)this << ",str = " << (int *)str << endl;
    			delete[] str;
    		}
    		
    	}
    


    也就是说,发生了CDemo类的两次析构,并且两次析构str所指向的同一内存地址空间(两次str的值相同)。
    问题出在哪里?
    有人认为vector对象指针能够自动析构,所以不需要调用delete a1,否则会造成两次析构对象。这种理解是不准确的,任何对象如果是通过new操作符申请了空间,必须显示的调用delete来销毁这个对象,所以delete a1这条语句是没有错误的。
    错误在于:
    在执行

    a1->push_back(d1);  //只是简单的值拷贝
    

    这条语句时,会调用CDemo的拷贝构造函数,虽然CDemo类中没有定义拷贝构造函数,但是编译器会为CDemo类构建一个默认的拷贝构造函数(浅拷贝),正是这里出了问题,a1中的所有CDemo元素的str成员变量没有初始化,只有一个四字节(32位机)指针空间。

    a1->push_back(d1);  //只是简单的值拷贝
    

    这句话执行完之后,a1里的CDemo元素与d1是不同的对象,但是a1里的CDemo元素的str与d1.str指向的是同一块内存
    局部变量“CDemo d1;”在main函数退出时,自动释放所占内存空间,前面已经调用过delete a1,已经把d1.str释放了,main函数退出时,又要释放掉已经释放掉的d1.str内存空间,所以程序最后崩溃。
    解决办法:
    给CDemo类添加一个拷贝构造函数即可

    	CDemo(const CDemo &cd)
    	{
    		this->str = new char[strlen(cd.str) + 1];
    		strcpy_s(str,strlen(cd.str) + 1,cd.str);
    	}
    

    另:最好再重载一个 = 运算符
    参考资料
    《程序员面试宝典》(第四版)

  • 相关阅读:
    点击空白处回收键盘
    数据处理文件读取---预习 1.30
    界面通信之属性传值、代理传值
    UITableView的添加、删除、移动操作
    加载plist文件数据的方法
    UITableViewCell的重用机制
    自定义cell自适应高度
    关于Xcode7更新之后使用 SDWebImage 图片加载不出来
    简述frame、bounds、center
    layoutSubviews方法需要被调用的情况有哪些
  • 原文地址:https://www.cnblogs.com/Manual-Linux/p/11087903.html
Copyright © 2011-2022 走看看