2

Essentially, I want 2 of my classes to be sharing some data, which i want to have as a vector of shared_ptr objects.

I have cut down my code into the following simple compilable example.

I want object A, to be looking at the data that was initialized in object B. However when I try and do push_back() inside a method of A, it hasnt changed the size of the vector of shared_ptr objects in B. (At the line with the comment "This is the point of interest".)

What approach do I need to use to get this functionality, or am I on the wrong track. (c++ newbie here)

#include <memory>
#include <vector>
#include <iostream>
using std::cout;
using std::endl;
class DataClass {
    public:
        int i_;
};
class B {
    public:
        // constructor:
        B() : my_data_(std::vector<std::shared_ptr<DataClass> >()) {
            my_data_.push_back(std::shared_ptr<DataClass> (new DataClass));
            my_data_.push_back(std::shared_ptr<DataClass> (new DataClass));
            my_data_[0]->i_ = 1;
            my_data_[1]->i_ = 2;
            cout<<my_data_.size()<<endl;
        };

        // return the data
        std::vector< std::shared_ptr<DataClass> > get_my_data() {
            return my_data_;
        };

        // check the data:
        void CheckData() {
            cout<<my_data_.size()<<endl; // This is the point of interest
        };
        // member variable
        std::vector< std::shared_ptr<DataClass> > my_data_;
};
class A {

    public:
        void start() {
            // begin interaction with B class:
            B b;

            // get the vector of data pointers:
            a_has_data_ = b.get_my_data();

            // modify some of the data:
            a_has_data_.push_back(std::shared_ptr<DataClass> (new DataClass));
            a_has_data_[2]->i_ = 42;

            b.CheckData(); 
        };
    private:
    std::vector< std::shared_ptr<DataClass> > a_has_data_;

};
int main() {
    A a;
    a.start();
}
CptLightning
  • 555
  • 1
  • 8
  • 18
  • 1
    You're making a copy of the vector. Return it by reference instead: `std::vector< std::shared_ptr >& get_my_data()` – Peter Wood Mar 01 '13 at 21:32
  • @Peter That doesn't seem to work, I think it is because I am trying to save a reference as a member variable in A? it does work if I do: b.get_my_data().push_back()...etc, however it's not working in the form: a_has_data_.push_back() even after your suggestion. – CptLightning Mar 01 '13 at 21:44
  • You may want to rethink your design. Maybe combine the two classes, or let the data live on `A` instead. – Peter Wood Mar 01 '13 at 21:57

3 Answers3

4

You are returning a copy of the vector. You need to return a reference to the data:

// return the data
std::vector< std::shared_ptr<DataClass> >& get_my_data()
{
        return my_data_;
};

That was A is accessing b's vector, not a copy of it.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • That doesn't seem to work, I think it is because I am trying to save a reference as a member variable in A? it does work if I do: b.get_my_data().push_back()...etc, however it's not working in the form: a_has_data_.push_back() even after your suggestion. – CptLightning Mar 01 '13 at 21:42
  • 1
    @CptLightning then you can keep a `B` as a data member of `A`, and drop the vector data member. The problem is that you are trying to couple two things with a different lifetime: the `B` that lives in the scope of `A::start()`, and `A::a_has_data`. – juanchopanza Mar 01 '13 at 21:46
  • oh yes, I do see the conflict of lifetimes now. Thanks – CptLightning Mar 01 '13 at 21:50
1
a_has_data_.push_back(std::shared_ptr<DataClass> (new DataClass));

With the return type is by copy, the above statement is going to modify the a_has_data_. And in b.CheckData(); you are actually checking the size of b's member.

Introduce a member function in A to check the vector size and you should see the increase.

Mahesh
  • 34,573
  • 20
  • 89
  • 115
0

Here in

 std::vector< std::shared_ptr<DataClass> > get_my_data()

The value is got with return by value so new object is created. See the following implementation. It solves your problem by sending pointer.

#include <tr1/memory>
#include <vector>
#include <iostream>
using namespace std;
using std::cout;
using std::endl;
class DataClass {
    public:
        int i_;
};
class B {
    public:
        // constructor:
        B() : my_data_(std::vector<tr1::shared_ptr<DataClass> >()) {
            my_data_.push_back(tr1::shared_ptr<DataClass> (new DataClass));
            my_data_.push_back(tr1::shared_ptr<DataClass> (new DataClass));
            my_data_[0]->i_ = 1;
            my_data_[1]->i_ = 2;
        };

        // return the data
        std::vector< tr1::shared_ptr<DataClass> >* get_my_data() {
            return &my_data_;
        };

        // check the data:
        void CheckData() {
            cout<<my_data_.size()<<endl; // This is the point of interest
        };
        // member variable
        std::vector< tr1::shared_ptr<DataClass> > my_data_;
};
class A {

    public:
        void start() {
            // begin interaction with B class:
            B b;

            // get the vector of data pointers:
            a_has_data_ = b.get_my_data();

            // modify some of the data:
            b.CheckData(); 
            a_has_data_->push_back(tr1::shared_ptr<DataClass> (new DataClass));
            (*a_has_data_)[2]->i_ = 42;
            b.CheckData(); 
        };
    private:
    std::vector< tr1::shared_ptr<DataClass> >* a_has_data_;

};
int main() {
    A a;
    a.start();
}

Note: I changed the code to tr1/memory as I have older gcc.

Krish
  • 1,747
  • 14
  • 19