为什么这些shared_ptrs不指向同一个容器?

时间:2010-04-04 16:40:05

标签: c++ boost shared-ptr

我有一个班级模型:

class Model
{
    ...

    boost::shared_ptr<Deck>  _deck;
    boost::shared_ptr<CardStack> _stack[22];
};

Deck继承自CardStack

我试图让_stack[0]指向_deck指向的同一件事:

{
    _deck = boost::shared_ptr<Deck>(new Deck());
    _stack[0] = _deck;
}

似乎_deck _stack[0]的作业会产生_deck的副本。 (我知道这一点,因为对_stack[0]的修改不会导致_deck的修改。)我怎样才能让它们指向同一个东西?

好的 - 没有调用复制构造函数。我通过实现它并查看它是否被调用来验证这一点 - 它没有。

但是 - 我有一个对CardStack个对象进行操作的函数:

void TransferSingleCard(CardStack & src, CardStack & dst, Face f)
{
    if( !src._cards.empty() )
    {
        src._cards.back().SetFace(f);
        dst.PushCard(src._cards.back());
        src._cards.pop_back();
    }   

}

现在 - 当我打电话时:

{
    TransferSingleCard(*_stack[DECK], _someotherplace, FACEDOWN);
    std::cout << *_stack[DECK];
    std::cout << *_deck;
}

我得到了这个输出(CardStack上的std :: cout将打印出该堆栈的大小):

Num(103) TOP
Num(104) TOP

...所以我总结(错误地?)_stack[DECK]指向不同的东西。

The Deck

class Deck : public CardStack
{
public:
    Deck(int numsuits=2, StackIndex index = NO_SUCH_STACK );
    Deck::Deck( const Deck & d);
    int DealsLeft() const;
    void RecalcDealsLeft();
private:
    int _dealsleft;
};

4 个答案:

答案 0 :(得分:2)

不清楚你在问什么 - 请考虑以下代码:

#include <iostream>
#include "boost/shared_ptr.hpp"
using namespace std;

struct A {
    virtual ~A() {
        cout << "destroyed" << endl;
    }
};

struct B : public A {
};

int main() {
    boost::shared_ptr<B> b( new B );
    boost::shared_ptr<A> a;
    a = b;
}

仅显示一条“销毁”消息,表示未进行任何复制。

答案 1 :(得分:1)

认为问题在于你在这里分配不同的类型。 boost::shared_ptr是一个模板,即使模板中的类型是模板也不是多态的。所以发生的事情是你的编译器看到从boost::shared_ptr<Deck>boost::shared_ptr<CardStack>的赋值,并注意到它可以通过调用CardStack的复制构造函数来复制Deck对象来进行赋值。

我认为你希望作业看起来像这样:

_stack[0] = boost::static_pointer_cast<CardStack>(_deck);

将按照您的预期进行转换。

答案 2 :(得分:1)

这个例子 - 来自@ Neil的答案,试图模仿你说的正在发生的事情。你能检查一下你的系统是否正常工作(A和B的计数相同)。

然后我们可以尝试修改此代码或代码,直到匹配为止。

#include <boost/shared_ptr.hpp>
#include <iostream>

class A {
    public:
    virtual ~A()
    {
        std::cerr << "Delete A" << std::endl;
    }
    int _count;
    void decrement()
    {
        _count --;
    }
};
class B : public A {
    public:
    virtual ~B()
    {
        std::cerr << "Delete B" << std::endl;
    }
};

int main()
{
    boost::shared_ptr<B> b(new B);
    b->_count = 104;
    boost::shared_ptr<A> a;
    a = b;

    a->decrement();

    std::cerr << "A:" << a->_count << std::endl;
    std::cerr << "B:" << b->_count << std::endl;
    return 0;
}

编辑:

所以从评论中我们知道原始指针是正确的,所以现在我们需要追踪。

或者:

  1. 记录指针以查看它们何时发生变化。
  2. 在调试器中使用观察点来查看指针何时发生变化。
  3. 使用第三个共享指针查看哪个指针已更改。
  4. 介绍一个同时更改两个指针的函数。

答案 3 :(得分:1)

我认为shared_array可能需要_stack。 。 。请查看shared_ptr上的文档;来自boost.org,具体来说:

  

http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_ptr.htm

     

“通常,shared_ptr不能   正确地按住一个指针   动态分配的数组。看到   shared_array用于该用法。“

另外,请注意T* get()函数(没有充分理由不使用),它返回托管指针所占的原始指针(在本例中为shared_ptr)。