Shallow Copy and Deep Copy

ธนาธร ศรแสง 650710552

Shallow Copy คืออะไร?

การ Shallow Copy เป็นการสร้าง object ใหม่ แล้วคัดลอก field ที่เป็น value type (เช่น int, float, bool) จาก original object ไป object ใหม่และ ข้อมูลใน filed ของทั้งสอง object จะถูกเก็บไว้คนละตำแหน่งหน่วยความจำ แต่ถ้า field เป็น reference type (เช่น array, object, string) จะคัดลอกเฉพาะ reference ของ field เท่านั้น ทำให้ข้อมูลใน field นั้นของ object ทั้งสองชี้ไปที่ตำแหน่งหน่วยความจำเดียวกัน ซึ่งการที่ field ทั้งสองชี้ไปที่ตำแหน่งหน่วยความจำเดียวกัน ทำให้ถ้าข้อมูลของ field ใน object ใด object หนึ่งเปลี่ยน ข้อมูลใน field นั้นของอีก object ก็จะเปลี่ยนตาม จึงเกิดปัญหาเวลาต้องการเปลี่ยนค่าใน field ของ object เดียวแต่ ไม่อยากให้อีก object เปลี่ยนด้วย shallow Copy จึงเหมาะกับการใช้งานกับ object ที่มี field ที่เป็น value type หรือ คัดลอกไปแต่ไม่ได้เปลี่ยนค่าใน field ที่เป็น reference type

ตัวอย่างการ Shallow Copy

ในภาพนี้ได้ทำการ Shallow Copy สร้าง object G2 ขึ้นมาใหม่ แล้วคัดลอก field Global rank ที่เป็น value type จาก object G1 ไป object G2 คือ 548(int) และถูกเก็บไว้ในคนละตำแหน่งหน่วยความจำกับ object G1 แต่ field Desc ที่เป็น reference type (string) คัดลอกเฉพาะ reference ของ field Desc ซึ่งถูกเก็บไว้ในตำแหน่งหน่วยความจำเดียวกันกับ object G1

เปรียบการ Shallow Copy ในภาษาต่างๆ

C++

ใน C++ มี 2 วิธีในการทำ Shallow Copy คือ

1.Copy Constructor เป็นการคัดลอกที่จะอ้างอิงถึง object ของคลาสเดียวกันมาเป็น argument ของ constructor โดยจะต้องมีการสร้าง object ทั้งคู่มาก่อน แล้วนำ object หนึ่งในนั้นมาคัดลอกให้อีก object

2.Assigment Operator เป็นการนำ object มา assign ค่าให้อีก object โดยใช้เครื่องหมาย = โดยวิธีการนี้จะเป็นการคัดลอก object และสร้าง object ใหม่เลยโดยใส่ ชื่อ class ไว้ด้านหน้า เช่น Company* G2 = G1 (Company เป็น class ของ G1, G1 เป็น object ที่ถูกคัดลอก, G2 เป็น object ที่สร้างใหม่)

Java

ใน Java สามารถใช้ method clone() เพื่อทำ Shallow Copy ได้ โดยถ้าใช้ clone() มันจะสร้าง object ใหม่และคัดลอกค่าของ field ทั้งหมดไปยัง object ใหม่

Python

ใน Python การ assignment statements ไม่ได้ทำการคัดลอก object แต่จะสร้างการ binding ระหว่างตัวแปรกับ object ที่ต้องการ เมื่อเราใช้เครื่องหมาย = ตัวแปรใหม่ที่เราสร้างขึ้นจะชี้ไปยัง original object ซึ่งถ้าเราทำการเปลี่ยนค่าในตัวแปรใหม่ ตัวแปรเดิมก็จะเปลี่ยนตาม

ตัวอย่างโค้ดการ Shallow Copy

using System;

class Example
{
    public static void Main(string[] args)
    {
        Company G1 = new Company(548, "GeeksForGeeks");
        Company G2 = (Company)G1.Shallowcopy();
        Console.WriteLine("ก่อนเปลี่ยนค่าของ field Global rank กับ Desc : ");
        Console.WriteLine(G1.GlobalRank);
        Console.WriteLine(G2.GlobalRank);
        Console.WriteLine(G2.desc.CompanyName);
        Console.WriteLine(G1.desc.CompanyName);

        G2.GlobalRank = 59;
        G2.desc.CompanyName = "GFG";
        Console.WriteLine("หลังเปลี่ยนค่าของ field Global rank กับ Desc : ");
        Console.WriteLine(G1.GlobalRank);
        Console.WriteLine(G2.GlobalRank);
        Console.WriteLine(G2.desc.CompanyName);
        Console.WriteLine(G1.desc.CompanyName);
    }
}

class Company
{
    public int GlobalRank;
    public CompanyDescription desc;

    public Company(int gbRank, string c)
    {
        GlobalRank = gbRank;
        desc = new CompanyDescription(c);
    }

    public object Shallowcopy()
    {
        return this.MemberwiseClone();
    }
}

class CompanyDescription
{
    public string CompanyName;

    public CompanyDescription(string c)
    {
        CompanyName = c;
    }
}

Output

ก่อนเปลี่ยนค่าของ field Global rank กับ Desc : 
548
548
GeeksforGeeks
GeeksforGeeks

หลังเปลี่ยนค่าของ field Global rank กับ Desc :
548
59
GFG
GFG

Deep Copy คืออะไร?

การ Deep Copy เป็นการสร้าง object ใหม่ แล้วคัดลอก field ทั้ง value type และ reference type ไปไว้คนละตำแหน่งหน่วยความจำของ original object ในการใช้งานถ้าเราไม่ได้ต้องการเปลี่ยนค่าใน field ที่เป็น reference type ของ object ก็ไม่จำเป็นต้องใช้วิธี Deep Copy เนื่องจากซับซ้อนกว่าการใช้ Shallow Copy

ตัวอย่างการ Deep Copy

ในภาพนี้ได้ทำการ Deep Copy สร้าง object G2 ขึ้นมาใหม่ แล้วคัดลอก field Global rank ที่เป็น value type จาก object G1 ไป object G2 คือ 548( int ) และเก็บไว้คนละตำแหน่งหน่วยความจำกับ object G1 ในส่วนของ field Desc ที่เป็น reference type( string ) Desc ของ object G1 และ object G2 คือ GeeksforGeeks( string ) และเก็บข้อมูลไว้คนละตำแหน่งหน่วยความจำกับ object G1

เปรียบการ Deep Copy ในภาษาต่างๆ

C++

ใน C++ การ Deep Copy เป็นการคัดลอกที่ object ใหม่จะถูกสร้างโดยการคัดลอกข้อมูลของตัวแปรทั้งหมดจาก original object ไปยัง object ใหม่ และมีการ allocate memory ที่ใกล้เคียงกัน(ไม่ใช่ตำแหน่งเดียวกัน)ให้ object ใหม่ แต่มีค่าเดียวกัน

Java

ใน java class ที่เราต้องการทำ Deep Copy จะต้อง implement interface Cloneable เพื่อกำหนดว่า class นี้คัดลอกได้ ต้อง override method Clone() ของ class object เพื่อกำหนด method ที่เราต้องการให้คัดลอก objectในและ เมธอด clone() จะต้องมีทำการสร้าง object ใหม่ และคัดลอกค่าของข้อมูลจาก original object ไปยัง object ใหม่ทั้งหมด

Python

ใน Python การ Deep Copy เป็นการคัดลอกที่จะมีการสร้าง object ใหม่ขึ้นมาก่อน ซึ่งตำแหน่งหน่วยความจำต่างจาก original object แล้วคัดลอกข้อมูลจาก original object ไปที่ object ใหม่

ตัวอย่างโค้ดการ Deep Copy

using System;
class Example {
    public static void Main(string[] args)
    {
        Company G1 = new(548, "GeeksforGeeks");
        Company G2 = (Company)G1.DeepCopy();
        Console.WriteLine("ก่อนเปลี่ยนค่าของ field Global rank กับ Desc : ");
        Console.WriteLine(G1.GlobalRank);
        Console.WriteLine(G2.GlobalRank);
        Console.WriteLine(G1.desc.CompanyName);
        Console.WriteLine(G2.desc.CompanyName);
        G2.GlobalRank = 59;
        G2.desc.CompanyName = "GFG";
        Console.WriteLine("\nหลังเปลี่ยนค่าของ field Global rank กับ Desc : ");
        Console.WriteLine(G1.GlobalRank);
        Console.WriteLine(G2.GlobalRank);
        Console.WriteLine(G1.desc.CompanyName);
        Console.WriteLine(G2.desc.CompanyName);
    }
}
class Company {
    public int GlobalRank;
    public CompanyDescription desc;

    public Company(int gbRank, string c)
    {
        this.GlobalRank = gbRank;
        this.desc = new CompanyDescription(c);
    }
    public Company DeepCopy() {
        return new Company(this.GlobalRank, this.desc.CompanyName);
    }
}
class CompanyDescription {
    public string CompanyName;
    public CompanyDescription(string c) {
        this.CompanyName = c;
    }
}

Output

ก่อนเปลี่ยนค่าของ field Global rank กับ Desc : 
548
548
GeeksforGeeks
GeeksforGeeks

หลังเปลี่ยนค่าของ field Global rank กับ Desc :
548
59
GFG
GeeksforGeeks

Presentation

Video

Reference

What is the difference between a reference type and value type in c#?. (2011). StackOverflow.https://stackoverflow.com/questions/5057267/what-is-the-difference-between-a-reference-type-and-value-type-in-c

What is the difference between a deep copy and a shallow copy?. (2008). StackOverflow.https://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy

Shallow Copy and Deep Copy in C#. (2024). GeeksforGeeks.https://www.geeksforgeeks.org/shallow-copy-and-deep-copy-in-c-sharp/

copy in Python (Deep Copy and Shallow Copy). (2024). GeeksforGeeks.https://www.geeksforgeeks.org/copy-python-deep-copy-shallow-copy/

Default Assignment Operator and References in C++. (2021). GeeksforGeeks.https://www.geeksforgeeks.org/default-assignment-operator-and-references-in-cpp/

Shallow Copy and Deep Copy in C++. (2024). GeeksforGeeks.https://www.geeksforgeeks.org/shallow-copy-and-deep-copy-in-c/

Copy Constructor in C++. (2024). GeeksforGeeks.https://www.geeksforgeeks.org/copy-constructor-in-cpp/

copy in Python (Deep Copy and Shallow Copy). (2024). GeeksforGeeks.https://www.geeksforgeeks.org/copy-python-deep-copy-shallow-copy/

Deep, Shallow and Lazy Copy with Java Examples. (2022). GeeksforGeeks.https://www.geeksforgeeks.org/deep-shallow-lazy-copy-java-examples/

Last updated