Мы должны использовать copy-on-write в нашем школьном проекте. Я экспериментировал с очень простым классом, но без везения. У меня есть это:C++ - основная реализация копирования на запись
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
class CPerson {
public:
CPerson();
CPerson (const CPerson&);
~CPerson();
char* m_name;
char* m_surname;
int m_refs;
void rename (const char*, const char*);
};
CPerson :: CPerson() : m_name(NULL), m_surname(NULL), m_refs(1) {}
CPerson :: CPerson (const CPerson& src) : m_name (src.m_name), m_surname (src.m_surname), m_refs(src.m_refs+1) {} // supposed to be a shallow copy
CPerson :: ~CPerson() {
if (m_refs == 1) {
delete [] m_name;
delete [] m_surname;
}
else --m_refs;
}
void CPerson :: rename (const char* name, const char* surname) {
delete [] m_name;
delete [] m_surname;
m_name = new char [strlen(name)+1];
m_surname = new char [strlen(surname)+1];
strcpy (m_name, name);
strcpy (m_surname, surname);
}
int main() {
CPerson a;
a.rename ("Jack", "Smith");
cout << a.m_name << " " << a.m_surname << endl;
CPerson b(a);
cout << a.m_name << " " << a.m_surname << endl;
cout << b.m_name << " " << b.m_surname << endl;
// good so far...
a.rename ("John", "Anderson"); // should rename both 'a' and 'b'
cout << a.m_name << " " << a.m_surname << endl;
cout << b.m_name << " " << b.m_surname << endl;
// prints random values
return 0;
}
Это странно, потому что, когда я вынимаю couts, все работает КИ (без утечек, без ошибок с помощью Valgrind).
Любая помощь будет оценена по достоинству.
Ваша реализация распадается на этот простой code: 'int main() {CPerson * a = новый CPerson; CPerson b (* a); удалить a; cout << b.m_name; } 'Другими словами, первый созданный один уничтожается, а второй (' b') все еще жив и теперь будет иметь доступ к памяти, которая была освобождена. Пора посмотреть на ваш дизайн, особенно на эту переменную подсчета ссылок (которая на самом деле не разделяется экземплярами). – PaulMcKenzie
Совет: не заново изобретайте колесо (кроме, возможно, в объеме, необходимом для вашего назначения). Слежение за подсчетом ссылок и освобождением памяти, когда счетчик ссылок достигает нуля, уже имеет значение 'shared_ptr', и вы можете использовать его в своем классе. – hvd
*** a.rename («Джон», «Андерсон»); // должен переименовывать оба 'a' и 'b' ***. Я бы ожидал, что переименование не изменится 'b', если вы делаете копию при записи. – drescherjm