在Google c++风格指南中引用的对象所有者是什么?

What is the object owner referred to in the Google C++ Style Guide?

本文关键字:对象 所有者 是什么 引用 c++ Google 风格      更新时间:2023-10-16

谷歌c++风格指南中关于智能指针的部分说:

  • 我们更喜欢那些对象只有一个固定的所有者的设计。

我不完全理解这个句子。

  • 对象所有者是什么?
  • 它只是指针吗?

对象的"所有者"不是c++语言的实际组成部分,而是一个概念性工具——作为"所有者"的想法是负责决定何时可以销毁对象。如果一个对象只有一个所有者,那么很容易判断出该对象何时需要销毁——只要看看所有者就知道了。然而,当一个对象被多个其他对象引用时,事情就不那么清楚了——任何引用对象都不能单独删除仲裁对象,因为这会给其他引用者带来问题。因此,不存在"单一的、固定的所有者"。

举一些例子,考虑一个'picture'对象。

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数组。在本例中,图片拥有原始数据。

现在,您不需要使用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(用于自有数组)有助于防止您犯错误。

在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();
}