C++ - 写入时复制的基本实现
C++ - copy-on-write basic implementation
我们应该在学校项目中使用写时复制。我一直在尝试一个非常简单的课程,但没有任何运气。我有这个:
#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;
}
这很奇怪,因为当我取出 cout 时,一切正常(没有泄漏,valgrind 没有错误)。
任何帮助将不胜感激。
你的设计有缺陷。 您需要在字符数据本身上实现引用计数,而不是在单个CPerson
对象上实现引用计数,因为它们彼此不共享单个引用计数变量。
尝试更多类似的东西:
#include <iostream>
#include <string>
using namespace std;
struct SPersonData
{
string m_name;
string m_surname;
int m_refcnt;
SPersonData() : m_refcnt(0) {}
void incRef() { ++m_refcnt; }
void decRef() { if (--m_refcnt == 0) delete this; }
};
class CPerson
{
private:
SPersonData *m_data;
public:
CPerson ();
CPerson (const CPerson&);
~CPerson ();
CPerson& operator= (const CPerson&);
string getName() const;
string getSurname() const;
void rename (const string&, const string&);
};
CPerson::CPerson ()
: m_data(NULL) {}
CPerson::CPerson (const CPerson& src)
: m_data (src.m_data)
{
if (m_data) m_data->incRef();
}
CPerson::~CPerson ()
{
if (m_data) m_data->decRef();
}
CPerson& operator= (const CPerson &src)
{
if (this != &src)
{
if (m_data) m_data->decRef();
m_data = src.m_data;
if (m_data) m_data->incRef();
}
return *this;
}
string CPerson::getName() const
{
if (m_data) return m_data->m_name;
return string();
}
string CPerson::getSurname() const
{
if (m_data) return m_data->m_surname;
return string();
}
void CPerson::rename (const string &name, const string &surname)
{
if ((m_data) && (m_data->m_refcnt > 1))
{
m_data->decRef();
m_data = NULL;
}
if (!m_data)
{
m_data = new SPersonData;
m_data->incRef();
}
m_data->m_name = name;
m_data->m_surname = surname;
}
在 C++11 及更高版本中,通过使用 std::shared_ptr
管理引用计数,可以大大简化:
#include <iostream>
#include <string>
#include <memory>
using namespace std;
struct SPersonData
{
string m_name;
string m_surname;
};
class CPerson
{
public:
shared_ptr<SPersonData> m_data;
string getName() const;
string getSurname() const;
void rename (const string&, const string&);
};
string CPerson::getName() const
{
if (m_data) return m_data->m_name;
return string();
}
string CPerson::getSurname() const
{
if (m_data) return m_data->m_surname;
return string();
}
void CPerson::rename (const string &name, const string &surname)
{
if (!((m_data) && m_data.unique()))
m_data = make_shared<SPersonData>();
m_data->m_name = name;
m_data->m_surname = surname;
}
无论哪种方式,您的测试都将如下所示:
int main ()
{
CPerson a;
a.rename ("Jack", "Smith");
cout << a.getName() << " " << a.getSurname() << endl;
CPerson b(a);
cout << a.getName() << " " << a.getSurname() << endl;
cout << b.getName() << " " << b.getSurname() << endl;
// good so far...
a.rename ("John", "Anderson"); // should rename only 'a' not 'b'
cout << a.getName() << " " << a.getSurname() << endl;
cout << b.getName() << " " << b.getSurname() << endl;
return 0;
}
相关文章:
- 为共享 ptr 向量实现复制 c'tor?
- 使用共享指针实现复制 c'tor?
- 如何在双向链表上实现复制赋值?
- 实现不可复制的C++类
- 在C++中正确实现复制构造函数
- 如何在模板容器类中实现复制构造函数和赋值运算符
- 在单个链接列表中实现复制构造函数C
- 如何为具有自引用指针的类实现复制构造函数/赋值运算符
- 为什么完美的转发(全部捕获)不能实现复制分配?
- 在 C++11 中实现复制和交换习语的更好方法
- 如何为派生类实现复制构造函数
- 复制/移动操作符是否可以安全地用于实现复制/移动分配操作符
- C++实现复制构造函数
- 为什么使用 swap 来实现复制分配
- 使用桥接模式 c++ 实现复制构造函数
- PFArrayD.cpp实现复制构造函数
- 为简单向量实现复制构造函数
- 实现复制构造函数
- 矢量实现复制构造函数错误
- 根据move构造函数实现复制赋值操作符