Ваш лучший выстрел - член shared_ptr<Resource>
в классе User
. Но для этого требуется, чтобы ресурс генерировался в свободной (куче) памяти.
class User {
User(Resource * res) : res_ptr(res) { //initialize user }
private:
shared_ptr<Resource> res_ptr;
}
void Init() {
Resource * res = new Resource(...);
User user = new User(res);
}
Второй подход - предоставить конструктор поддельных копий и механизм подкачки для Resource
.
class Resource
{
private:
explicit Resource(const Resource &); // disabled to avoid heavy copy.
const Resource & operator = (const Resource & );
int * int_res;
public:
Resource() : int_res(new int(100)) { }
~Resource()
{
if(int_res != NULL)
delete int_res;
}
Resource(Resource & other) : int_res(NULL)
{
this->swap(other);
}
void swap(Resource & other)
{
using std::swap;
swap(int_res, other.int_res);
}
};
class User
{
private:
Resource resource;
User();
User(const User &);
const User & operator = (const User &);
public:
User(Resource & res) : resource(res) { }
~User() { }
};
Но это опасно и подвержено ошибкам, потому что после создания пользователя вы оставляете ресурс в состоянии зомби. Для этого фрагмента кода весь доступ к указателю int_res
, который назначен на NULL
, приведет к ошибке нарушения доступа.
Последний подход, который я могу объяснить, - это использование в C ++ 0x функции "семантика перемещения".
class Resource
{
// ...
// ...
// Replace with Resource(Resource & other)
Resource(Resource && other) : int_res(NULL) //Move constructor
{
this->swap(other);
}
const Resource & operator = (Resource && other) // Move assignment operator
{
this->swap(other);
return *this;
}
void swap(Resource & other)
{
using std::swap;
swap(int_res, other.int_res);
}
};
class User
{
private:
Resource resource;
User();
User(const User &);
const User & operator = (const User &);
public:
User(Resource && res) : resource(std::move(res)) { }
~User() { }
};
void Init() {
Resource res(...);
User user = new User(std::move(res));
}
Этот подход несколько безопаснее. Вам не нужно иметь дело с указателями, и если вы забудете написать std::move
, вы получите сообщение об ошибке компилятора, говорящее «вы не можете привязать экземпляр Resource
к Resource&&
» или «отключено создание копии Resource
«.
&&
подчеркивает, что объект является временным и собирается испаряться. Таким образом, этот подход больше подходит для сценариев, где Resource генерируется и возвращается функцией. На вашем месте я бы сделал конструктор закрытым и сгенерировал бы его с помощью функции друга.
Resource GetResource(....)
{
Resource res(...);
return res;
}
void Init()
{
User user = new User( GetResource(...) );
}
Этот фрагмент кода идеально соответствует "семантике перемещения". Вы должны изучить это, если вы можете написать код C ++ 0x. Это и , это - это два хороших видео для начала.