简体   繁体   中英

C++: Container of original pointers

I need to store references to instances of derived classes in C++. I considered using a vector of shared_ptrs to the base class (for it needs to hold different types of derived classes), however, it's important that the container holds the original pointers, which is not the case with vectors (or other stl containers), if I'm not mistaken. Is there a way to do this in native C++, or do I have to use special containers like Boost's ptr_vector?

EDIT: This is my test code:

class Foo
{
public:
    Foo() {}
    virtual ~Foo() {}
    virtual void set_x(int i) = 0;
};

class Bar : public Foo
{
public:
    Bar() {}

    void set_x(int i)
    {
        this->x = i;
    }

    int x;
};

int main()
{
    Bar bar;

    // ptr
    std::cout << &bar << "\n";

    std::vector<Foo*> foos;
    foos.push_back(&bar);

    // different ptr value
    std::cout << &foos[0] << "\n";

    foos[0]->set_x(1);

    // however, changes are made
    std::cout << bar.x;

    return 0;
}

Thanks in advance,

jena

You can create a std::vector<foo*>, which will hold any pointers to foo that you hand to it. It won't make any attempt to delete those pointers on destruction, which may or may not be what you want, but it will hold exactly the values you pass in.

You can also create an std::vector< shared_ptr<foo> >, which will hold pointers that will be released once there are no dangling copies of the shared_ptr floating around. Those will also hold the "original" foo* you passed in; you can get it again by using the shared_ptr::get() method.

The only time you wouldn't see exactly the same pointer as your derived object is if you're using multiple inheritance of classes, and your base classes include data. Because a foo* would end up, in that case, pointing to the "foo" part of the data, which wouldn't necessarily be at the "root" of the object.

In your example above, what you are printing out is the address of the pointer not the value of the pointer.

Instead of:

// different ptr value
std::cout << &foos[0] << "\n";

Do

// different ptr value
std::cout << foos[0] << "\n";

Aside from that your vector<Foo*> will work just fine.

If you use shared_ptr as your container member, the pointer in each member will retain access to the original object instance. You can get a copy of a shared_ptr at any point after container housekeeping, but the original object will still be its target.

For a simpler solution you might use boost::ptr_vector , provided none of your pointers occur twice in the container - that scenario would introduce tricky resource management complexity and point you back to shared_ptr .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM