从C C++的角度看PYTHON的深浅拷贝

原创如果有误请指出

今天看到python的列表深浅拷贝,不由得和C\C++进行了比较如下:

其实python中的深COPY和浅COPY和C\C++中是一样的,毕竟python底层是C/C++做的,这方面保留了
C\C++的原理,对于类或者结构体复制构造函数等号(=)操作符保留了浅COPY,当然我们可以自定义
这些函数。我们先从C++的简单的复制构造函数等号(=)操作符的例子开始

#include<iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;


class testcy
{

        private:
                char* a;
                unsigned int b;
        public:
                testcy(const char* inc)
                {

                        a = new char[strlen(inc)+1];
                        strcpy(a,inc);
                        b = 1;
                }       
                testcy()
                {

                        a= NULL;
                        b = 0;
                }
                testcy(const testcy &in) //浅copy 构造函数  
                {

                        this->a = in.a;
                        this->b = in.b;
                }
                testcy& operator=(const testcy& in)//浅=值操作符重载  
                {

                        this->a = in.a;
                        this->b = in.b;
                }

                void print()
                {

                        cout<<this->a<<"   ";
                        cout<<this->b<<endl;
                }

                void modify(const char* in,const int in2)
                {

                        if(strlen(a) < strlen(in))
                        {

                                cout<< "error:much lenth than point a char"<<endl;
                                exit(1);
                        }
                        else
                        {

                                for(int i=0;i<strlen(in);i++)
                                {

                                        *(a+i) = *(in+i);
                                }
                        }
                        b = in2;

                }

};


int main(void)
{

        testcy a("123123");
        testcy b = a;
        testcy c ;
        c = a;
    cout<<"source data:"<<endl;
        cout<<"string  int"<<endl;
        a.print();
        b.print();
        c.print();

        cout<<"after only change a:"<<endl;
        cout<<"string  int"<<endl;
        a.modify("asd",2);

        a.print();
        b.print();
        c.print();

}

非常简单就是为了演示浅COPY输出如下:

source data:
string  int
123123   1
123123   1
123123   1
after only change a:
string  int
asd123   2
asd123   1
asd123   1

我们可以看到在修改a的数据后b、c的数据string数据也更改了,但是简单类型int没有更改。那么我们用内存四区图来描述

123.jpg

图中a->a当然就是整形,但是a->b是指针其指针的值0XB0120存在栈中但是实际指向的数据存在堆中,
而变量b->b,c->b指向了同一块内存 导致一改全部都改了,但是a->a,b->a,c->a确实单独的在栈上了的
没影响。其实这里我们只要修改浅COPY为深COPY改变其实现即可比如

        testcy(const testcy &in) //深copy 构造函数  
        {

            this->a = new char[strlen(in.a)+1];
            strcpy(this->a,in.a);
            this->b = in.b;
        }

我们要做的不仅仅是要指针相等而是要将内存重新分配。注意本测试程序没有写析构函数。

下面我们来看看python的浅列表拷贝

import copy              
                                                        
a = ['t1','t2','t3','t4']
b = a                    
print("source data")     
print(a);                
print(b);                
                         
a[0] = 'gao'             
print("after change:")   
                         
print(a);                
print(b);  
source data              
['t1', 't2', 't3', 't4'] 
['t1', 't2', 't3', 't4'] 
after change:            
['gao', 't2', 't3', 't4']
['gao', 't2', 't3', 't4']

确实如此,修改了列表元素a[0]的值b列表也修改了,我们有了C++的那张图这个就很好理解了,他们是
指向同一块内存堆区。我们应该使用

a = ['t1','t2','t3','t4']
b = copy.deepcopy(a)

从这个方法的命名我们也可以看到这是深copy,其原理已经在C++代码进行了剖析
另外如下:

a = [['t1','t10'],'t2','t3','t4']
b = a.copy()                          
                                 
print("source data")             
print(a);                        
print(b);                        
                                 
a[0][0] = 'gao'                  
print("after change:")           
                                 
print(a);                        
print(b);
source data                       
[['t1', 't10'], 't2', 't3', 't4'] 
[['t1', 't10'], 't2', 't3', 't4'] 
after change:                     
[['gao', 't10'], 't2', 't3', 't4']
[['gao', 't10'], 't2', 't3', 't4']

a.copy()只是对第一层进行copy,第二层在python里面实现应该也是指针或者引用,一样的会出问题。
所以copy的时候我们尽量使用copy.deepcopy(a)来得到正确的数据当然根据实际需求定。
可以看到C/C++是理论基础,有了这些理论PYTHON中的很多现象很好理解。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容