2011-12-31 53 views

回答

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_) { } 
}; 

这是类似的,但现在矢量隐藏我们的原始指针;不可能有两个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_arraystd::vector(对于拥有的阵列)有助于防止出错。

+0

好吧,'所有者'不是C++语言的实际部分。然而,在C++中,它是如何实现的。它只是指向对象的指针? – ashim 2011-12-31 16:39:40

+0

@capoluca,'所有者'是一个概念,所以有多种方式来实现所有权关系。指针可能是所有权的一部分,但是指针也可以指向共享(非拥有)对象。 – bdonlan 2011-12-31 17:35:33

+0

@bdonlan当我们不需要/希望复制语义和/或复制昂贵时会发生什么?我们是否只将所有内容作为shared_ptr传递? – aromero 2012-05-14 16:33:45

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