说我有这个名为Dog的课程。每只狗都有不同的名字,但是同样的吠叫声(从资源文件中加载)。
class Dog {
public:
Dog(const string &name) : _name(name) {
_barkingVoice.load();
}
~Dog() {
_barkingVoice.free();
}
string getName() const { return _name; }
void bark() { _barkingVoice.play(); }
private:
string _name;
VoiceResource _barkingVoice;
};
我想仅在Dog的实例是第一个时调用_barkingVoice.load()
,并且仅在没有Dog的实例时才调用_barkingVoice.free()
。
显而易见的解决方案是将_barkingVoice设置为static并将Dog的引用计数器保留为数据成员。
我的问题是,是否有更简单的方法来做到这一点。也许是std实现或类似的东西。
答案 0 :(得分:2)
首先,为什么VoiceResource
不是静态的?如果它在Dog
的所有实例之间共享,那么它应该是。{否则,您需要在每次构造函数调用时加载或复制resuorce。
拥有一个静态变量static int instanceCount;
,设置为0
。在每个临时,复制和移动(C ++ 11)构造函数中递增它,在析构函数中递减它。这将使你有机会做你想做的事。
这基本上就像shared_ptr<T>
那样工作,可能是一种在这里使用它而不是编写自己的代码的方法,我只是想不出来。
class Dog {
public:
Dog(const string &name) : _name(name) {
loadResource();
}
Dog(const Dog& b) : name(b.name) {
loadResource();
}
// only C++11:
Dog(Dog&& b) : name(std::move(b.name)) {
loadResource();
}
~Dog() {
freeResource();
_barkingVoice.free();
}
string getName() const { return _name; }
void bark() { _barkingVoice.play(); }
private:
string _name;
static VoiceResource _barkingVoice;
static int instanceCount;
static void loadResource() {
if (instanceCount == 0) {
_barkingVoice.load();
}
++instanceCount;
}
static void freeResource() {
--instanceCount;
if (instanceCount == 0) {
_barkingVoice.free();
}
}
};
int Dog::instanceCount = 0;
答案 1 :(得分:2)
创建一个可重用的类来封装引用计数:
template<class ResourceType, class OwnerType>
class RefCounted {
public:
RefCounted() { if (++_refCount == 1) _resource.load(); }
virtual ~RefCounted() { if (--_refCount == 0) _resource.free(); }
ResourceType& operator*() { return _resource; }
ResourceType* operator->() { return &_resource; }
private:
static unsigned _refCount;
static ResourceType _resource;
};
template<class T, class U> unsigned RefCounted<T, U>::_refCount = 0;
template<class T, class U> T RefCounted<T, U>::_resource;
class Dog {
public:
Dog(const string &name) : _name(name) { }
string getName() const { return _name; }
void bark() { _barkingVoice->play(); }
private:
string _name;
RefCounted<VoiceResource, Dog> _barkingVoice;
};
每个模板实例化都有自己的_refCount
和_resource
。
第二个模板参数用于处理使用相同RefCounted
实例化ResourceType
但希望对这些实例具有单独引用计数的情况。例如。如果您添加Cat
类并希望它拥有自己的Refcounted<VoiceResource>
:
class Cat {
// ...
private:
RefCounted<VoiceResource, Cat> _meowingVoice;
};
答案 2 :(得分:1)
将_barkingVoice
设为std::shared_ptr<VoiceResource>
。
shared_ptr
完全符合您的需要:使用引用计数来跟踪最后一个对象的删除,以及何时释放资源。