答案 0 :(得分:3)
对象的“所有者”不是C ++语言的实际部分,而是一个概念工具 - 作为“所有者”的想法负责决定何时可以销毁对象。如果一个对象只有一个所有者,那么很容易弄清楚何时需要销毁该对象 - 只需看看所有者即可。然而,当一个对象被多个其他对象引用时,事情就不那么清楚 - 没有一个引用对象可以自己删除裁判对象,因为这会给其他引用者带来问题。因此,没有“单一,固定的所有者”。
举一些例子,考虑一个'图片'对象。
class Picture {
char *rawData;
public:
Picture(char *rawData_) : rawData(rawData_) { }
Picture(const Picture &p) : rawData(p.rawData) { }
};
图片不拥有rawData
;正如我们从复制构造函数中看到的那样,让多个图片引用相同的数据非常容易。更好的版本可能如下:
class Picture {
std::vector<char> rawData;
public:
Picture(const std::vector<char> &rawData_) : rawData(rawData_) { }
};
这是类似的,但现在vector正在为我们隐藏原始指针;两个Pictures
引用相同的指针是不可能的。我们负责在销毁图片时销毁rawData数组。在这种情况下,Picture拥有原始数据。
现在,您没有拥有来使用STL容器来拥有一个拥有的对象。你可以手动完成:
class Picture {
size_t rawDataSize;
char *rawData;
public:
Picture(size_t rds, char *rd) {
rawDataSize = rds;
rawData = new char[rds];
memcpy(rawData, rd, rds);
}
~Picture() { delete [] rawData; }
Picture(const Picture &pic) {
rawDataSize = pic.rawDataSize;
rawData = new char[rawDataSize];
memcpy(rawData, pic.rawData, rawDataSize);
}
Picture& operator=(const Picture &pic) {
delete [] rawData;
rawDataSize = pic.rawDataSize;
rawData = new char[rawDataSize];
memcpy(rawData, pic.rawData, rawDataSize);
return *this;
}
};
这也是一种拥有关系; rawData数组'永久地'属于图片对象。所有访问都通过图片对象,并与图片对象一起被销毁。
通常,对于拥有关系,建议使用包装类来自动销毁,并防止意外复制。在我的第三个例子中,如果我忘记了复制构造函数或operator=
,例如,会发生可怕的事情。使用包含类std::unique_ptr
,boost::scoped_ptr
/ boost::scoped_array
或std::vector
(对于拥有的数组)有助于防止您犯错误。
答案 1 :(得分:2)
按照bdonlan的回答,一个C ++示例:
int main()
{
// owner of 'obj' is main()
Object *obj = new Object;
// even if 'foo' receives an object, it is not its owner;
// it shouldn't be responsible for destroying it
foo(obj);
// obj is still alive
obj->DoSomething();
// the owner should clean up what it created
delete obj;
}
你问,
在c ++中,它是如何实现的。它只是指向对象的指针吗?
通常它会是一个指针,但并非总是如此。正如bdonlan所说,所有权是一个概念,一个对象的所有者将负责清理事后。参考的一个例子:
void foo(Object &obj) {}
int main()
{
// owner of 'obj' is main()
Object obj;
obj.Init();
foo(obj);
// the owner is responsible for calling Cleanup()
// it would be unnatural and confusing if Cleanup()
// was called in foo(), which is not the owner
obj.Cleanup();
}