将对象作为参数传递的好方法是什么?在我的代码中,我一直在使用引用而不是指针,如果可能的话,我想坚持这种方法。但是,有一种情况不能正常工作:
class Resource {
Resource(...) { //expensive resource initialization }
~Resource() { //destroy resource }
};
class User {
User(const Resource & res) : res_(res) { //initialize user }
private:
Resource res_;
}
void Init() {
Resource res(...);
User user = new User(res);
} //res is destroyed - along with its associated resource
//user can no longer use the resource
在这种情况下是否应该使用最佳实践?我想要实现的结果是在Resource
对象被销毁时自动销毁User
,但不依赖于User
对象来创建Resource
本身。我的感觉是我应该重载Resource
的复制构造函数。还有其他想法吗?
答案 0 :(得分:1)
你最好的镜头是在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&&
”或“复制construtor” Resource
被禁用。“
&&
强调对象是暂时的,并且会消失。因此,这种方法更适用于由函数生成和返回Resource的场景。如果我是你,我会将构造函数设为私有,并使用友元函数生成它。
Resource GetResource(....)
{
Resource res(...);
return res;
}
void Init()
{
User user = new User( GetResource(...) );
}