Łatwiej jest wdrożyć metodę kopiowania przy zapisie w języku obiektowym, takim jak C++. Na przykład większość klas kontenera w Qt to copy-on-write.
Ale jeśli oczywiście możesz to zrobić w C, to tylko trochę więcej pracy. Kiedy chcesz przypisać dane do nowego bloku danych, nie wykonujesz kopii, zamiast tego po prostu kopiujesz wskaźnik w obrysie otaczającym twoje dane. Musisz śledzić w swoich blokach danych status danych. Jeśli teraz zmienisz coś w swoim nowym bloku danych, zrobisz "prawdziwą" kopię i zmienisz status. Oczywiście nie można już używać prostych operatorów takich jak "=" do przypisania, zamiast tego trzeba mieć funkcje (w C++ wystarczy przeciążenie operatora).
Bardziej niezawodna implementacja powinna wykorzystywać liczniki odwołań zamiast prostej flagi, pozostawiam to Tobie.
szybkie i brudne przykład: Jeśli masz
struct big {
//lots of data
int data[BIG_NUMBER];
}
trzeba wdrożyć przypisać funkcje i pobierające/ustawiające się.
// assume you want to implent cow for a struct big of some kind
// now instead of
struct big a, b;
a = b;
a.data[12345] = 6789;
// you need to use
struct cow_big a,b;
assign(&a, b); //only pointers get copied
set_some_data(a, 12345, 6789); // now the stuff gets really copied
//the basic implementation could look like
struct cow_big {
struct big *data;
int needs_copy;
}
// shallow copy, only sets a pointer.
void assign(struct cow_big* dst, struct cow_big src) {
dst->data = src.data;
dst->needs_copy = true;
}
// change some data in struct big. if it hasn't made a deep copy yet, do it here.
void set_some_data(struct cow_big* dst, int index, int data } {
if (dst->needs_copy) {
struct big* src = dst->data;
dst->data = malloc(sizeof(big));
*(dst->data) = src->data; // now here is the deep copy
dst->needs_copy = false;
}
dst->data[index] = data;
}
Musisz napisać konstruktorów i destruktorów, jak również. Naprawdę polecam C++ do tego.
Jakie dane kopiujesz?Kopiowanie przy zapisie może nie być jedynym rozwiązaniem. –