2012-09-02 28 views
2

什么是正确的做法?我知道如果容器是基类值类型,那么存储的派生对象是'切片'。如果容器是派生类类型的,则不能存储基类对象。对?存储基本和派生对象的混合的容器?

如果要使用指针,auto_ptr不能使用,因为它有复制语义问题。 shared_ptr是解决这个问题的唯一解决方案吗?

任何人都可以提供解决此问题的更多详细信息,示例代码或在线文章?这应该是一个相当普遍的问题,但是我没有在教科书或在线上找到关于它的很多信息。

在此先感谢。

btw,我只是搜索unique_ptr。它似乎不支持复制语义。因此,在STL中使用auto_ptr并非只是安全的,但可能由于缺乏复制语义,许多STL操作或算法不能用于unique_ptr容器?

回答

2

最明显的解决方案是使用std::unique_ptr

class IBase {}; 
class Derived : virtual public IBase {}; 
std::vector<std::unique_ptr<IBase>> v; 
v.push_back(std::unique_ptr<IBase>(new Derived())); 

你可以使用std::shared_ptr,但它的所有权语义显著改变程序的行为,保持动态分配的对象活着的生命,直到没有人拥有对它们的引用。

+0

感谢juanchopanza,你能详细解释一下'但是它的所有权语义大大改变了程序的行为,保持......'吗?你的意思是,如果程序员不太在意,使用shared_ptr有时会留下未使用的副本,因此该对象不能及时释放;而unique_ptr总是有单个副本,并没有这样的问题? – user1559625

+0

@ user1559625 [this so question](http://stackoverflow.com/questions/6876751/differences-between-unique-ptr-and-shared-ptr)可能有所帮助。基本上,unique_ptr具有指针对象的所有权,并在被删除时将其删除。所有权可以从一个unique_ptr“移动”到另一个,但永远不会有多个所有者。通过shared_ptr,可以有任意数量的所有者,最后一个将会删除指针。有时候,你想知道指针被删除的时间,其他时间你不关心。 – juanchopanza

+0

我觉得'IBase'必须有一个虚拟析构函数。使用'shared_ptr'由于删除器的类型擦除而不是问题;但'unique_ptr'不是这种情况。 – rodrigo

5

如果你想要多态行为(你确实需要它),那么你必须使用指针或引用。这在许多地方都有很好的记录。

既然你不能使用容器的引用,你必须使用指针的容器。

现在,您可以使用您认为合适的任何类型的指针:unique_ptr,shared_ptr或原始指针。

+2

的确,您无法创建引用的容器。但你可以用'std :: reference_wrapper '来伪造它。它包含一个指针,但可以通过引用访问它。 –

+0

有没有办法知道算法是否可以安全地使用'unique_ptr'?显然有些不能('copy()','fill()'),但它看起来像删除或重新排列元素可能会或可能不会,这取决于它们如何实现。 –

+1

@PeteBecker:我尝试过'reference_wrapper'事物的容器,并且它不能很好地工作。问题是,在C++中,你不能重载'operator.',所以为了访问包含对象的成员,你必须做的,例如'c [0] .get() - > member'。如果你必须这样做,你可以做'c [0] - > member'。 – rodrigo

2

有std :: vector和std :: shared_ptr的例子。我认为这就是你想要的。

#include <iostream> 
#include <memory> 
#include <vector> 

class Base { 
public: 
    virtual void foo() { 
     std::cout << "base" << std::endl; 
    } 
}; 

class Derived : public Base { 
    void foo() { 
     std::cout << "derived" << std::endl; 
    } 
}; 

int main() 
{ 
    std::vector<std::shared_ptr<Base> > v; 
    v.push_back(std::shared_ptr<Base>(new Base)); 
    v.push_back(std::shared_ptr<Base>(new Derived)); 

    for (auto it : v) { 
     it->foo(); 
    } 
} 
+0

这里不清楚是否需要共享所有权。我会说,最好使用独特的所有权*除非*明确关心共享。 – juanchopanza

+0

我的问题也是,所以什么时候共享所有权是必须的? – user1559625

0

[http://www.boost.org/doc/libs/1_51_0/libs/ptr_container/doc/ptr_container.html](The升压指针容器库)是只为这制成。

+0

谢谢。非常有用的信息。 – user1559625

相关问题