Sự khác biệt giữa một bản sao sâu và một bản sao nông là gì?


754

Sự khác biệt giữa một bản sao sâu và một bản sao nông là gì?


6
Nó đi theo công nghệ nào?
Suresh Varma

42
@SureshVarma, đó là một khái niệm lập trình!
Manish Shrivastava

Câu trả lời:


760

Các bản sao nông trùng lặp ít nhất có thể. Một bản sao nông của một bộ sưu tập là một bản sao của cấu trúc bộ sưu tập, không phải là các yếu tố. Với một bản sao nông, hai bộ sưu tập hiện chia sẻ các yếu tố riêng lẻ.

Bản sao sâu sắc trùng lặp mọi thứ. Một bản sao sâu của một bộ sưu tập là hai bộ sưu tập với tất cả các yếu tố trong bộ sưu tập ban đầu được nhân đôi.


Có thể triển khai .NET MemberwiseClone () thực hiện nhiều hơn việc sao chép nông theo nghĩa thông thường
Lu55

5
Hãy nhớ rằng cũng có các bản sao hỗn hợp (không chỉ là bản sao lười biếng ), bản sao này chỉ là một phần của nó ( đây là một ví dụ )! ;)
cregox

Vì vậy, một bản sao nông của X có thể thay đổi các phần tử trong X nhưng một bản sao sâu không thể?
trừng phạt

1
cấu trúc bộ sưu tập là gì?
Mật ong

1
@Honey Bộ sưu tập có thể là cấu trúc dữ liệu đa dạng lưu trữ nhiều mục dữ liệu. Trong python, chúng tôi có tuple, danh sách, từ điển, vv
Murphy

851

Bề rộng vs Độ sâu; nghĩ về một cây tham chiếu với đối tượng của bạn là nút gốc.

Nông cạn:

Trước khi sao chép Sao chép nông Nông xong

Các biến A và B đề cập đến các vùng nhớ khác nhau, khi B được gán cho A, hai biến tham chiếu đến cùng một vùng nhớ. Những sửa đổi sau này đối với nội dung của một trong hai được phản ánh ngay lập tức trong nội dung của cái khác, khi chúng chia sẻ nội dung.

Sâu:

Trước khi sao chép Sao chép sâu Thực hiện sâu

Các biến A và B đề cập đến các vùng nhớ khác nhau, khi B được gán cho A các giá trị trong vùng nhớ mà điểm A được sao chép vào vùng nhớ mà B trỏ tới. Những sửa đổi sau này đối với nội dung của duy nhất là duy nhất đối với A hoặc B; nội dung không được chia sẻ.


32
Đây là bài viết trên wikipedia mà hình minh họa này xuất phát trong trường hợp nó không có ý nghĩa ngoài ngữ cảnh đối với bạn en.wikipedia.org/wiki/Object_copy#Shallow_copy
corbin

4
Trong trường hợp sao chép nông nếu chúng tôi thực hiện bất kỳ thay đổi nào trong mảng B sẽ được phản ánh trong mảng A vì cả A & B đều trỏ đến cùng một vị trí bộ nhớ?
tek3

3
Trong một dòng duy nhất bản sao của nó bằng cách tham chiếu so với sao chép theo giá trị. Không chắc câu trả lời có đúng không!
Mannu

2
hình ảnh được lấy trực tiếp từ wikipedia mà không cần trích dẫn
jasonleonhard

9
@jasonleonhard Vì vậy, 9 năm trước tôi chỉ đưa url vào hình ảnh vì việc nhúng hình ảnh không được hỗ trợ. Do đó, URL trích dẫn nguồn của nó. Cộng đồng sau đó đã tạo các URL thành các hình ảnh nhúng mà không cần chỉnh sửa một số loại trích dẫn trên đó. Nhận xét hàng đầu 4 tuổi cũng chỉ ra những gì bạn chỉ ra. Có một cái nhìn: stackoverflow.com/posts/184780/revutions Tại sao không tự mình chỉnh sửa một câu trích dẫn? Tôi có thể không có mặt vào lần tới khi ai đó có chút phàn nàn về phong cách viết 10 tuổi của tôi.
dlamblin

156

Nói tóm lại, nó phụ thuộc vào những điểm nào. Trong một bản sao nông, đối tượng B trỏ đến vị trí của đối tượng A trong bộ nhớ. Trong bản sao sâu, tất cả mọi thứ trong vị trí bộ nhớ của đối tượng A được sao chép vào vị trí bộ nhớ của đối tượng B.

Bài viết wiki này có một sơ đồ tuyệt vời.

http://en.wikipedia.org/wiki/Object_copy


114

Hãy thử xem xét hình ảnh sau đây

nhập mô tả hình ảnh ở đây

Ví dụ: Object.MemberwiseClone tạo một liên kết sao chép nông

và sử dụng giao diện IClonizable, bạn có thể nhận được bản sao sâu như được mô tả ở đây


28
Một bưc tranh đang gia ngan lơi noi.
Levi Fuller

6
Oh boy, đến đây để tìm hiểu ý nghĩa. Đây là câu trả lời duy nhất có ích.
Karan Singh

1
Đây là cách đơn giản nhất và chỉ hiển thị những gì cần thiết.
hina10531

1
minh họa tốt nhất
Muhammad Nayab

69

Đặc biệt dành cho nhà phát triển iOS:

Nếu Blà một bản sao cạn của A, sau đó cho dữ liệu nguyên thủy nó giống như B = [A assign];và cho các đối tượng nó giống như B = [A retain];

B và A trỏ đến cùng một vị trí bộ nhớ

Nếu Blà một bản sao sâu của A, thì nó giống nhưB = [A copy];

B và A trỏ đến các vị trí bộ nhớ khác nhau

Địa chỉ bộ nhớ B giống như của A

B có cùng nội dung với A


8
"Địa chỉ bộ nhớ B giống như của A" - Sao rồi?

2
Trong Deep Copy, "địa chỉ bộ nhớ B KHÔNG giống với A"
ismail baig

60

Bản sao nông: Sao chép các giá trị thành viên từ đối tượng này sang đối tượng khác.

Deep Copy: Sao chép các giá trị thành viên từ đối tượng này sang đối tượng khác.
                     Bất kỳ đối tượng con trỏ được sao chép và Deep Copied.

Thí dụ:

class String
{
     int   size;
     char* data;
};

String  s1("Ace");   // s1.size = 3 s1.data=0x0000F000

String  s2 = shallowCopy(s1);
 // s2.size =3 s2.data = 0X0000F000
String  s3 = deepCopy(s1);
 // s3.size =3 s3.data = 0x0000F00F
 //                      (With Ace copied to this location.)

47

Tôi chưa thấy câu trả lời ngắn gọn, dễ hiểu ở đây - vì vậy tôi sẽ thử.

Với một bản sao nông, bất kỳ đối tượng nào được trỏ đến bởi nguồn cũng được trỏ đến bởi đích (để không có đối tượng được tham chiếu nào được sao chép).

Với một bản sao sâu, bất kỳ đối tượng nào được trỏ đến bởi nguồn được sao chép và bản sao được trỏ đến đích (vì vậy bây giờ sẽ có 2 đối tượng được tham chiếu). Điều này đệ quy xuống cây đối tượng.



36

{Tưởng tượng hai đối tượng: A và B cùng loại _t (liên quan đến C ++) và bạn đang nghĩ về việc sao chép nông / sâu từ A sang B}

Shallow Copy: Đơn giản chỉ cần tạo một bản sao của tham chiếu đến A thành B. Hãy nghĩ về nó như một bản sao của Địa chỉ A. Vì vậy, địa chỉ của A và B sẽ giống nhau, tức là chúng sẽ được trỏ đến cùng một vị trí bộ nhớ, tức là nội dung dữ liệu.

Sao chép sâu: Đơn giản chỉ cần tạo một bản sao của tất cả các thành viên của A, phân bổ bộ nhớ ở một vị trí khác cho B và sau đó gán các thành viên được sao chép cho B để đạt được bản sao sâu. Theo cách này, nếu A trở thành B không tồn tại thì vẫn còn hiệu lực trong bộ nhớ. Thuật ngữ chính xác để sử dụng sẽ là nhân bản, trong đó bạn biết rằng cả hai đều hoàn toàn giống nhau, nhưng khác nhau (nghĩa là được lưu trữ dưới dạng hai thực thể khác nhau trong không gian bộ nhớ). Bạn cũng có thể cung cấp trình bao bọc nhân bản của mình, nơi bạn có thể quyết định thông qua danh sách bao gồm / loại trừ những thuộc tính sẽ chọn trong khi sao chép sâu. Đây là một thực tế khá phổ biến khi bạn tạo API.

Bạn có thể chọn thực hiện Sao chép nông CHỈ_IF bạn hiểu các cổ phần liên quan. Khi bạn có số lượng lớn các con trỏ để xử lý trong C ++ hoặc C, thực hiện một bản sao nông của một đối tượng là THỰC SỰ là một ý tưởng tồi.

EXAMPLE_OF_DEEP COPY_ Một ví dụ là, khi bạn đang cố gắng xử lý hình ảnh và nhận dạng đối tượng, bạn cần che dấu "Chuyển động không liên quan và lặp lại" ra khỏi khu vực xử lý của mình. Nếu bạn đang sử dụng con trỏ hình ảnh, thì bạn có thể có thông số kỹ thuật để lưu những hình ảnh mặt nạ đó. NGAY BÂY GIỜ ... nếu bạn thực hiện một bản sao nông của hình ảnh, khi các tham chiếu con trỏ bị GỬI từ ngăn xếp, bạn đã mất tham chiếu và bản sao của nó tức là sẽ có lỗi thời gian vi phạm truy cập tại một số điểm. Trong trường hợp này, những gì bạn cần là một bản sao sâu sắc của hình ảnh của bạn bằng cách CLONING nó. Bằng cách này, bạn có thể lấy lại mặt nạ trong trường hợp bạn cần chúng trong tương lai.

EXAMPLE_OF_SHALLOW_COPY Tôi không phải là người cực kỳ am hiểu so với người dùng trong StackOverflow vì vậy hãy thoải mái xóa phần này và đưa ra một ví dụ tốt nếu bạn có thể làm rõ. Nhưng tôi thực sự nghĩ rằng không nên sao chép nông nếu bạn biết rằng chương trình của bạn sẽ chạy trong một khoảng thời gian vô tận, tức là hoạt động "đẩy" liên tục qua ngăn xếp với các lệnh gọi hàm. Nếu bạn đang trình diễn một cái gì đó cho một người nghiệp dư hoặc người mới (ví dụ: công cụ hướng dẫn C / C ++) thì có lẽ không sao. Nhưng nếu bạn đang chạy một ứng dụng như hệ thống giám sát và phát hiện hoặc Hệ thống theo dõi Sonar, bạn không được phép sao chép nông cạn các đối tượng xung quanh vì nó sẽ giết chương trình của bạn sớm hay muộn.


32
char * Source = "Hello, world.";

char * ShallowCopy = Source;    

char * DeepCopy = new char(strlen(Source)+1);
strcpy(DeepCopy,Source);        

'ShallowCopy' trỏ đến cùng một vị trí trong bộ nhớ như 'Nguồn'. 'DeepCopy' trỏ đến một vị trí khác trong bộ nhớ, nhưng nội dung giống nhau.


22

Bản sao nông là gì?

Bản sao nông là một bản sao khôn ngoan của một đối tượng. Một đối tượng mới được tạo có một bản sao chính xác của các giá trị trong đối tượng ban đầu. Nếu bất kỳ trường nào của đối tượng là tham chiếu đến các đối tượng khác, chỉ có các địa chỉ tham chiếu được sao chép tức là chỉ có địa chỉ bộ nhớ được sao chép.Bản sao nông

Trong hình này, các MainObject1trường field1có kiểu int và ContainObject1kiểu ContainObject. Khi bạn thực hiện một bản sao nông MainObject1, MainObject2được tạo bằng cách field2chứa giá trị được sao chép của field1và vẫn trỏ đến ContainObject1chính nó. Lưu ý rằng vì field1thuộc loại nguyên thủy, giá trị của nó được sao chép vào field2nhưng vì ContainedObject1là một đối tượng nên MainObject2vẫn trỏ đến ContainObject1. Vì vậy, bất kỳ thay đổi được thực hiện ContainObject1trong MainObject1sẽ được phản ánh trong MainObject2.

Bây giờ nếu đây là bản sao nông, hãy xem bản sao sâu?

Bản sao sâu là gì?

Một bản sao sâu sao chép tất cả các trường và tạo các bản sao của bộ nhớ được phân bổ động được chỉ ra bởi các trường. Một bản sao sâu xảy ra khi một đối tượng được sao chép cùng với các đối tượng mà nó đề cập đến. Sao chép sâu

Trong hình này, MainObject1 có các trường field1kiểu int và ContainObject1kiểu ContainObject. Khi bạn thực hiện một bản sao sâu MainObject1, MainObject2được tạo bằng cách field2chứa giá trị được sao chép của field1ContainObject2chứa giá trị được sao chép của ContainObject1. Lưu ý bất kỳ thay đổi được thực hiện ContainObject1trong MainObject1sẽ không phản ánh trong MainObject2.

bài báo hay


Đó không phải là lỗi của bạn mặc dù ví dụ này đề cập đến vấn đề field3mà khi cố gắng hiểu một vấn đề sâu sắc như vấn đề đó, thì số 3 trong ví dụ đó đang diễn ra ở ContainObject2 đâu?
Robb_2015

16

Trong lập trình hướng đối tượng, một kiểu bao gồm một tập hợp các trường thành viên. Các trường này có thể được lưu trữ theo giá trị hoặc theo tham chiếu (nghĩa là một con trỏ tới một giá trị).

Trong một bản sao nông, một thể hiện mới của loại được tạo và các giá trị được sao chép vào thể hiện mới. Các con trỏ tham chiếu cũng được sao chép giống như các giá trị. Do đó, các tham chiếu được trỏ đến các đối tượng ban đầu. Mọi thay đổi đối với các thành viên được lưu trữ bằng tham chiếu sẽ xuất hiện trong cả bản gốc và bản sao, vì không có bản sao nào được tạo từ đối tượng được tham chiếu.

Trong một bản sao sâu, các trường được lưu trữ theo giá trị được sao chép như trước, nhưng các con trỏ tới các đối tượng được lưu trữ bởi tham chiếu không được sao chép. Thay vào đó, một bản sao sâu được tạo từ đối tượng được tham chiếu và một con trỏ tới đối tượng mới được lưu trữ. Mọi thay đổi được thực hiện cho các đối tượng được tham chiếu đó sẽ không ảnh hưởng đến các bản sao khác của đối tượng.


12

'ShallowCopy' trỏ đến cùng một vị trí trong bộ nhớ như 'Nguồn'. 'DeepCopy' trỏ đến một vị trí khác trong bộ nhớ, nhưng nội dung giống nhau.


Điều này hơi sai lệch. Cả một bản sao nông và sâu sẽ sao chép đối tượng vào một vị trí mới trong bộ nhớ, sâu cũng sẽ sao chép các đối tượng con trong khi nông sẽ chỉ có các đối tượng mới đề cập đến trẻ em cũ. Thật khó để đọc mà không đề cập đến đối tượng ban đầu.
Bill K

10

Nhân bản nông:
Định nghĩa: "Một bản sao nông của một đối tượng sao chép đối tượng 'chính', nhưng không sao chép các đối tượng bên trong." Khi một đối tượng tùy chỉnh (ví dụ: Nhân viên) chỉ nguyên thủy, biến kiểu chuỗi thì bạn sử dụng Nhân bản nông.

Employee e = new Employee(2, "john cena");
Employee e2=e.clone();

Bạn quay lại super.clone();trong phương thức clone () bị ghi đè và công việc của bạn đã kết thúc.

Bản sao sâu :
Định nghĩa: "Không giống như bản sao nông, bản sao sâu là bản sao hoàn toàn độc lập của một đối tượng."
Có nghĩa là khi một đối tượng Nhân viên giữ một đối tượng tùy chỉnh khác:

Employee e = new Employee(2, "john cena", new Address(12, "West Newbury", "Massachusetts");

Sau đó, bạn phải viết mã để sao chép đối tượng 'Địa chỉ' cũng như trong phương thức clone () bị ghi đè. Mặt khác, đối tượng Địa chỉ sẽ không được sao chép và nó gây ra lỗi khi bạn thay đổi giá trị của Địa chỉ trong đối tượng Nhân viên nhân bản, điều này cũng phản ánh đối tượng gốc.


8
var source = { firstName="Jane", lastname="Jones" };
var shallow = ShallowCopyOf(source);
var deep = DeepCopyOf(source);
source.lastName = "Smith";
WriteLine(source.lastName); // prints Smith
WriteLine(shallow.lastName); // prints Smith
WriteLine(deep.lastName); // prints Jones

Đó không phải là một ví dụ tốt. Các bản sao nông hầu hết được sử dụng để sao chép nhanh các đối tượng, không sao chép dữ liệu, nhưng một khi các đối tượng cần sửa đổi dữ liệu chia sẻ, một bản sao sâu của nó sẽ được lấy. Ví dụ của bạn có thể sẽ gây nhầm lẫn cho người mới bắt đầu.
CMircea

điều này chỉ hoạt động trong các ngôn ngữ sử dụng con trỏ để biểu diễn các chuỗi. Điểm mà DHA đang cố gắng thực hiện là bản sao nông chỉ sao chép con trỏ vào nội dung gốc (số ít) giống hệt nhau, trong khi bản sao sâu cũng nhân bản nội dung được tham chiếu của con trỏ. Cả hai phương pháp sao chép nội dung bề mặt. Nếu ngôn ngữ lưu trữ các chuỗi dưới dạng nội dung theo nghĩa đen, ví dụ bên trong tiêu đề WAV, ví dụ này sẽ không hoạt động. Lưu ý điều này có lẽ quá cầu kỳ đối với hầu hết các vấn đề thực tế không phải là bí truyền.
DragonLord

8

Sao chép sâu

Một bản sao sâu sao chép tất cả các trường và tạo các bản sao của bộ nhớ được phân bổ động được chỉ ra bởi các trường. Một bản sao sâu xảy ra khi một đối tượng được sao chép cùng với các đối tượng mà nó đề cập đến.

Bản sao nông

Bản sao nông là một bản sao khôn ngoan của một đối tượng. Một đối tượng mới được tạo có một bản sao chính xác của các giá trị trong đối tượng ban đầu. Nếu bất kỳ trường nào của đối tượng là tham chiếu đến các đối tượng khác, thì chỉ các địa chỉ tham chiếu được sao chép tức là chỉ có địa chỉ bộ nhớ được sao chép.


Đáng buồn là liên kết đó không còn hoạt động nữa - bây giờ nó chỉ đến một bài viết từ tháng 2 năm 2019 liên quan đến thiết kế web (trừ khi tác giả có khả năng thấu thị?).
PhilPhil

7

Shallow Copy - Biến tham chiếu bên trong các đối tượng gốc và sao chép nông có tham chiếu đến đối tượng chung .

Deep Copy - Biến tham chiếu bên trong các đối tượng gốc và sao chép sâu có tham chiếu đến các đối tượng khác nhau .

clone luôn luôn sao chép nông.

public class Language implements Cloneable{

    String name;
    public Language(String name){
        this.name=name;
    }

    public String getName() {
        return name;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

lớp chính đang theo-

public static void main(String args[]) throws ClassNotFoundException, CloneNotSupportedException{

      ArrayList<Language> list=new ArrayList<Language>();
      list.add(new Language("C"));
      list.add(new Language("JAVA"));

      ArrayList<Language> shallow=(ArrayList<Language>) list.clone();
      //We used here clone since this always shallow copied.

      System.out.println(list==shallow);

      for(int i=0;i<list.size();i++)
      System.out.println(list.get(i)==shallow.get(i));//true

      ArrayList<Language> deep=new ArrayList<Language>();
      for(Language language:list){
          deep.add((Language) language.clone());
      }
      System.out.println(list==deep);
      for(int i=0;i<list.size();i++)
          System.out.println(list.get(i)==deep.get(i));//false

} 

OutPut ở trên sẽ-

sai đúng đúng

sai sai sai

Bất kỳ thay đổi nào được thực hiện trong đối tượng gốc sẽ phản ánh trong đối tượng nông không ở đối tượng sâu.

  list.get(0).name="ViSuaLBaSiC";
  System.out.println(shallow.get(0).getName()+"  "+deep.get(0).getName());

OutPut- ViSuaLBaSiC C


7

Tôi muốn đưa ra ví dụ hơn là định nghĩa chính thức.

var originalObject = { 
    a : 1, 
    b : 2, 
    c : 3,
};

Mã này hiển thị một bản sao nông :

var copyObject1 = originalObject;

console.log(copyObject1.a);         // it will print 1 
console.log(originalObject.a);       // it will also print 1 
copyObject1.a = 4; 
console.log(copyObject1.a);           //now it will print 4 
console.log(originalObject.a);       // now it will also print 4

var copyObject2 = Object.assign({}, originalObject);

console.log(copyObject2.a);        // it will print 1 
console.log(originalObject.a);      // it will also print 1 
copyObject2.a = 4; 
console.log(copyObject2.a);        // now it will print 4 
console.log(originalObject.a);      // now it will print 1

Mã này hiển thị một bản sao sâu :

var copyObject2 = Object.assign({}, originalObject);

console.log(copyObject2.a);        // it will print 1 
console.log(originalObject.a);      // it will also print 1 
copyObject2.a = 4; 
console.log(copyObject2.a);        // now it will print 4 
console.log(originalObject.a);      // !! now it will print 1 !!

Tôi đang nhận được1 1 4 4 4 4 4 4
Suresh Prajapati

trong bản sao sâu, làm copyObject.a = 8 và sau đó kiểm tra. hy vọng bạn sẽ nhận được câu trả lời thích hợp.
Vivek Mehta

5
struct sample
{
    char * ptr;
}
void shallowcpy(sample & dest, sample & src)
{
    dest.ptr=src.ptr;
}
void deepcpy(sample & dest, sample & src)
{
    dest.ptr=malloc(strlen(src.ptr)+1);
    memcpy(dest.ptr,src.ptr);
}

5

Trong Điều khoản đơn giản, Bản sao nông tương tự như Gọi theo tham chiếu và Bản sao sâu tương tự như Gọi theo giá trị

Trong cuộc gọi theo tham chiếu, cả hai tham số chính thức và thực tế của một hàm đều đề cập đến cùng một vị trí bộ nhớ và giá trị.

Trong Call By Value, cả hai tham số chính thức và thực tế của một hàm đều đề cập đến vị trí bộ nhớ khác nhau nhưng có cùng giá trị.


5

Hãy tưởng tượng có hai mảng được gọi là Array1 và Array2.

arr1 = arr2;   //shallow copy
arr1 = arr2.clone(); //deep copy

5

Một bản sao nông xây dựng một đối tượng ghép mới và chèn các tham chiếu của nó vào đối tượng ban đầu.

Không giống như bản sao nông, deepcopy xây dựng đối tượng ghép mới và cũng chèn các bản sao của các đối tượng gốc của đối tượng ghép ban đầu.

Hãy lấy một ví dụ.

import copy
x =[1,[2]]
y=copy.copy(x)
z= copy.deepcopy(x)
print(y is z)

Trên mã in FALSE.

Để xem thế nào.

Đối tượng ghép gốc x=[1,[2]](được gọi là hợp chất vì nó có đối tượng bên trong đối tượng (Inception))

nhập mô tả hình ảnh ở đây

như bạn có thể thấy trong hình, có một danh sách bên trong danh sách.

Sau đó, chúng tôi tạo ra một bản sao nông của nó bằng cách sử dụng y = copy.copy(x). Những gì python làm ở đây là, nó sẽ tạo ra một đối tượng ghép mới nhưng các đối tượng bên trong chúng đang chỉ vào các đối tượng gốc.

nhập mô tả hình ảnh ở đây

Trong hình ảnh, nó đã tạo ra một bản sao mới cho danh sách bên ngoài. nhưng danh sách bên trong vẫn giống như bản gốc.

Bây giờ chúng tôi tạo ra bản đồ sâu của nó bằng cách sử dụng z = copy.deepcopy(x). Những gì python làm ở đây là, nó sẽ tạo đối tượng mới cho danh sách bên ngoài cũng như danh sách bên trong. như thể hiện trong hình ảnh dưới đây (màu đỏ nổi bật).

nhập mô tả hình ảnh ở đây

Ở phần cuối mã in False, vì y và z không phải là cùng một đối tượng.

HTH.


2

Sao chép nông là tạo một đối tượng mới và sau đó sao chép các trường không tĩnh của đối tượng hiện tại sang đối tượng mới. Nếu một trường là một loại giá trị -> một bản sao từng bit của trường được thực hiện; đối với loại tham chiếu -> tham chiếu được sao chép nhưng đối tượng được tham chiếu thì không; do đó, đối tượng ban đầu và bản sao của nó tham chiếu đến cùng một đối tượng.

Sao chép sâu đang tạo một đối tượng mới và sau đó sao chép các trường không thuộc tính của đối tượng hiện tại sang đối tượng mới. Nếu một trường là một loại giá trị -> một bản sao từng bit của trường được thực hiện. Nếu một trường là một kiểu tham chiếu -> một bản sao mới của đối tượng được tham chiếu được thực hiện. Các lớp được nhân bản phải được gắn cờ là [Nối tiếp].


2

Lấy từ [blog]: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

Sao chép sâu liên quan đến việc sử dụng nội dung của một đối tượng để tạo một thể hiện khác của cùng một lớp. Trong một bản sao sâu, hai đối tượng có thể chứa thông tin ht giống nhau nhưng đối tượng đích sẽ có bộ đệm và tài nguyên riêng. sự phá hủy của một trong hai đối tượng sẽ không ảnh hưởng đến đối tượng còn lại. Toán tử gán quá tải sẽ tạo ra một bản sao sâu của các đối tượng.

Bản sao nông bao gồm sao chép nội dung của một đối tượng vào một thể hiện khác của cùng một lớp, do đó tạo ra một hình ảnh phản chiếu. Do sao chép thẳng các tham chiếu và con trỏ, hai đối tượng sẽ chia sẻ cùng một nội dung được chứa bên ngoài của đối tượng khác để không thể đoán trước.

Giải trình:

Sử dụng một hàm tạo sao chép, chúng ta chỉ cần sao chép các giá trị dữ liệu theo thành viên. Phương pháp sao chép này được gọi là bản sao nông. Nếu đối tượng là một lớp đơn giản, bao gồm các kiểu được xây dựng và không có con trỏ thì điều này có thể được chấp nhận. Hàm này sẽ sử dụng các giá trị và các đối tượng và hành vi của nó sẽ không bị thay đổi với một bản sao nông, chỉ các địa chỉ của các con trỏ là thành viên được sao chép và không phải là giá trị mà địa chỉ đang trỏ tới. Các giá trị dữ liệu của đối tượng sau đó sẽ vô tình bị thay đổi bởi hàm. Khi hàm vượt quá phạm vi, bản sao của đối tượng với tất cả dữ liệu của nó sẽ được bật ra khỏi ngăn xếp.

Nếu đối tượng có bất kỳ con trỏ nào, một bản sao sâu cần được thực thi. Với bản sao sâu của một đối tượng, bộ nhớ được phân bổ cho đối tượng trong cửa hàng miễn phí và các yếu tố được trỏ đến được sao chép. Một bản sao sâu được sử dụng cho các đối tượng được trả về từ một hàm.


2

Để thêm nhiều hơn vào các câu trả lời khác,

  • Bản sao nông của một đối tượng thực hiện sao chép theo giá trị cho các thuộc tính dựa trên loại giá trị và sao chép theo tham chiếu cho các thuộc tính dựa trên loại tham chiếu.
  • Bản sao sâu của đối tượng thực hiện sao chép theo giá trị cho các thuộc tính dựa trên loại giá trị, cũng như sao chép theo giá trị cho các thuộc tính dựa trên loại tham chiếu nằm sâu trong cấu trúc phân cấp (của loại tham chiếu)

2

Bản sao nông sẽ không tạo tài liệu tham khảo mới nhưng bản sao sâu sẽ tạo tài liệu tham khảo mới.

Đây là chương trình để giải thích các bản sao sâu và nông.

public class DeepAndShollowCopy {
    int id;
    String name;
    List<String> testlist = new ArrayList<>();

    /*
    // To performing Shallow Copy 
    // Note: Here we are not creating any references. 
      public DeepAndShollowCopy(int id, String name, List<String>testlist)
       { 

       System.out.println("Shallow Copy for Object initialization");
       this.id = id; 
       this.name = name; 
       this.testlist = testlist; 

       }
    */  

    // To performing Deep Copy 
    // Note: Here we are creating one references( Al arraylist object ). 
    public DeepAndShollowCopy(int id, String name, List<String> testlist) {
        System.out.println("Deep Copy for Object initialization");
        this.id = id;
        this.name = name;
        String item;
        List<String> Al = new ArrayList<>();
        Iterator<String> itr = testlist.iterator();
        while (itr.hasNext()) {
            item = itr.next();
            Al.add(item);
        }
        this.testlist = Al;
    }


    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Oracle");
        list.add("C++");
        DeepAndShollowCopy copy=new DeepAndShollowCopy(10,"Testing", list);
        System.out.println(copy.toString());
    }
    @Override
    public String toString() {
        return "DeepAndShollowCopy [id=" + id + ", name=" + name + ", testlist=" + testlist + "]";
    }
}

1

Sao chép ararys:

Mảng là một lớp, có nghĩa là nó là kiểu tham chiếu nên mảng1 = mảng2 dẫn đến hai biến tham chiếu cùng một mảng.

Nhưng hãy nhìn vào ví dụ này:

  static void Main()
    {
        int[] arr1 = new int[] { 1, 2, 3, 4, 5 }; 
        int[] arr2 = new int[] { 6, 7, 8, 9, 0 };

        Console.WriteLine(arr1[2] + " " + arr2[2]);
        arr2 = arr1;
        Console.WriteLine(arr1[2] + " " + arr2[2]); 
        arr2 = (int[])arr1.Clone();
        arr1[2] = 12;
        Console.WriteLine(arr1[2] + " " + arr2[2]);
    }

clone nông có nghĩa là chỉ bộ nhớ được đại diện bởi mảng nhân bản được sao chép.

Nếu mảng chứa các đối tượng kiểu giá trị, các giá trị được sao chép ;

nếu mảng chứa kiểu tham chiếu, chỉ các tham chiếu được sao chép - do đó, có hai mảng có thành viên tham chiếu cùng một đối tượng .

Để tạo một bản sao sâu, trong đó kiểu tham chiếu được sao chép, bạn phải lặp qua mảng và sao chép từng phần tử theo cách thủ công.


Tôi không biết về các ngôn ngữ khác, nhưng trong C # / VB, sao chép nông một mảng các loại giá trị không sao chép các giá trị. Hai mảng đề cập đến cùng một đối tượng. Thêm một nút vào một biểu mẫu và thêm mã này để xem:private void button1_Click(object sender, EventArgs e) { int[] arr1 = new int[]{1,2,3,4,5}; int[] arr2 = new int[]{6,7,8,9,0}; MessageBox.Show(arr1[2] + " " + arr2[2]); arr2 = arr1; MessageBox.Show(arr1[2] + " " + arr2[2]); arr1[2] = 12; MessageBox.Show(arr1[2] + " " + arr2[2]); }
DeanOC

bạn nói đúng, tôi đã sửa câu trả lời của mình để chính xác hơn, sử dụng bản sao trên mảng. Bạn hoàn toàn đúng khi "sao chép nông một mảng các loại giá trị không sao chép các giá trị", nhưng sử dụng bản sao trên mảng thì không. Tôi đã cố gắng giải thích điều đó, hãy thử nó. Cảm ơn
lukaszk

1

Tôi đã hiểu từ những dòng sau.

Shallow sao chép các trường loại giá trị đối tượng (int, float, bool) vào các loại tham chiếu của đối tượng và đối tượng (chuỗi, lớp, v.v.) được sao chép dưới dạng tham chiếu trong đối tượng đích. Trong mục đích này, các kiểu tham chiếu sẽ được trỏ đến vị trí bộ nhớ của đối tượng nguồn.

Bản sao sâu sao chép các giá trị và loại tham chiếu của một đối tượng thành một bản sao hoàn toàn mới của các đối tượng đích. Điều này có nghĩa là cả loại giá trị và loại tham chiếu sẽ được phân bổ một vị trí bộ nhớ mới.


0

Thêm vào tất cả các định nghĩa ở trên, một bản sao sâu hơn và được sử dụng phổ biến nhất, nằm trong hàm tạo sao chép (hoặc nạp chồng công cụ chuyển nhượng) của lớp.

Bản sao nông -> là khi bạn không cung cấp hàm tạo sao chép. Ở đây, chỉ có đối tượng được sao chép nhưng không phải tất cả các thành viên của lớp được sao chép.

Sao chép sâu -> là khi bạn đã quyết định triển khai hàm tạo sao chép hoặc gán quá tải trong lớp của mình và cho phép sao chép tất cả các thành viên của lớp.

MyClass& MyClass(const MyClass& obj) // copy constructor for MyClass
{
          // write your code, to copy all the members and return the new object
}
MyClass& operator=(const MyClass& obj) // overloading assignment operator,
{
          // write your code, to copy all the members and return the new object
}

0

Hàm tạo sao chép được sử dụng để khởi tạo đối tượng mới với đối tượng được tạo trước đó của cùng một lớp. Theo mặc định trình biên dịch đã viết một bản sao nông. Sao chép nông hoạt động tốt khi không phân bổ bộ nhớ động vì khi tham gia cấp phát bộ nhớ động thì cả hai đối tượng sẽ hướng về cùng một vị trí bộ nhớ trong một đống, do đó để loại bỏ vấn đề này, chúng tôi đã viết bản sao sâu để cả hai đối tượng có bản sao thuộc tính riêng trong một ký ức Để đọc chi tiết với các ví dụ và giải thích đầy đủ, bạn có thể xem các nhà xây dựng bài viết C ++ .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.