Copy on Write
What is it ?
Copy-on-write (COW) is an optimisation strategy used in C++ to improve performance by delaying the copying of objects until it's necessary. This is particularly useful in managing resources like strings or large data structures, allowing multiple instances to share the same data until one of them needs to modify it.
Key Concepts of Copy-on-Write
- Shared Ownership: Multiple objects can share the same underlying data.
- Lazy Copying: Actual copying occurs only when one of the objects needs to modify the data.
- Reference Counting: Typically, a reference count is maintained to track how many objects are sharing the data.
#include <iostream>
#include <cstring>
#include <memory>
class String {
public:
// Constructor
String(const char* str = "") : size(strlen(str)), data(new Data(str)) {
std::cout << "Constructor called\n";
}
// Copy Constructor
String(const String& other) : size(other.size), data(other.data) {
std::cout << "Copy Constructor called\n";
data->refCount++; // Increment reference count
}
// Assignment Operator
String& operator=(const String& other) {
std::cout << "Assignment Operator called\n";
if (this != &other) {
// Decrement the reference count
if (--data->refCount == 0) {
delete data; // Free old data if no references left
}
size = other.size;
data = other.data;
data->refCount++; // Increment reference count
}
return *this;
}
// Destructor
~String() {
std::cout << "Destructor called\n";
if (--data->refCount == 0) {
delete data; // Free data if no references left
}
}
// Access data with copy-on-write semantics
char& operator[](size_t index) {
if (data->refCount > 1) {
// If there are multiple references, create a copy
Data* newData = new Data(*data);
data->refCount--; // Decrease the old data's reference count
data = newData; // Point to the new copy
}
return data->str[index];
}
// Display function
void display() const {
std::cout << "String: " << data->str << " (refCount: " << data->refCount << ")\n";
}
private:
struct Data {
char* str;
size_t refCount;
Data(const char* s) : refCount(1) {
str = new char[strlen(s) + 1];
strcpy(str, s);
}
~Data() {
delete[] str;
}
};
size_t size;
Data* data; // Pointer to shared data
};
int main() {
String str1("Hello");
String str2 = str1; // Copy constructor
str2.display(); // Should show refCount of 2
str1[0] = 'h'; // Modify str1, causing a copy
str1.display(); // Shows modified string
str2.display(); // Should remain unchanged
return 0;
}