container access question
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 28

Thread: container access question

  1. #1
    Join Date
    Mar 2005
    Posts
    55

    container access question

    Hi c++ experts:

    I am trying to write a simple c++ code with 2 classes.

    First Class:

    Code:
    #ifndef __Cell__
    #define __Cell__
    
    #include<vector>
    using namespace std;
    
    class Cell
    {
    	private:
    		double			x;
    		
    	public:
    		Cell();
    		~Cell();
    		void			set_x(double );
    
    		double			get_x();
    		
    
    };
    inline void			Cell::set_x(double xx)				{ x = xx;}
    inline double			Cell::get_x()					{ return x;}
    #endif
    second class:

    Code:
    #ifndef __md__
    #define __md__
    
    #include<vector>
    #include "Cell.h"
    
    using namespace std;
    class Cell;
    
    class md
    {
    	public:
    		md();
    		~md();
    
    		vector<Cell*>	get_cellCollection();
    		void		set_cellCollection(vector<Cell*> );
    
    	private:
    		vector<Cell*>	mCellCollection;
    
    };
    inline vector<Cell*>	md::get_cellCollection()			{ return mCellCollection;}
    inline void		md::set_cellCollection(vector<Cell*> coll)	{ mCellCollection = coll;}
    #endif
    The main:
    Code:
    #include "md.h"
    #include "Cell.h"
    
    #include<iostream>
    #include<vector>
    #include<fstream>
    using namespace std;
    
    main() 
    {
    	md *argon = new md();
    
    	vector<Cell*> Collection = argon->get_cellCollection();
    
    	for(int i=1; i<4; i++){
    		Cell *cell = new Cell();
    		cell->set_x(1.0);
    		Collection.push_back(cell);
    	}
    
    	vector<Cell*> collect = argon->get_cellCollection();
    	for(int i=0; i<collect.size(); i++){
    		Cell *cell = collect[i];
    		double x = cell->get_x();
    		cout << x << endl;
    	}
    	return 0;
    }
    In main, I have already accessed the container Collection at
    Code:
     vector<Cell*> Collection = argon->get_cellCollection();
    and is filled in the first for loop. In second for loop the container is accessed again and write output. But there is no output. Because the first for loop does not fill it because it could not access the container. The container is already defined in the Cell.h. Why could not it access this container? Thanks a lot for your help.
    Last edited by manojg; October 27th, 2006 at 01:21 PM.

  2. #2
    Join Date
    Mar 2002
    Location
    California
    Posts
    1,582

    Re: container access question

    get_cellCollection() should return a reference to the container. In your code, it's returning a copy.


    Jeff

  3. #3
    Join Date
    Mar 2002
    Location
    California
    Posts
    1,582

    Re: container access question

    There are more problems with this code:

    - main() is not a valid signature. Use "int main()".
    - don't use "using namespace" in header files.
    - There's no need to create md dynamically with new. Just create it as a local variable(btw, you never delete it).
    - The container should either be a container of values vector<Cell> or a container of smart pointers vector<boost::shared_ptr<Cell> >. This promotes RAII.
    - Providing access to the class internals via get_cellCollection() is a very poor abstraction. There's probably something better you can do.

    Jeff

  4. #4
    Join Date
    Mar 2005
    Posts
    55

    Re: container access question

    Hi again,

    While I am reading about smart pointers and thinking another way to access the container, I made a small change in my previous code and it arrised another question that I could not figure out (I have no good c++ experience).

    In md.h file I changed
    Code:
     vector<Cell*>	get_cellCollection(); to 
     vector<Cell*>&	get_cellCollection();
    so that it returns reference to the vector mCellCollection.

    The main is
    Code:
    #include "md.h"
    #include "Cell.h"
    
    #include<iostream>
    #include<vector>
    #include<fstream>
    using namespace std;
    
    void done(md* );
    
    int main() 
    {
    	md *argon = new md();
    
    	vector<Cell*>& mCellCollection = argon->get_cellCollection();
    
    	for(int i=1; i<9; i++){
    		Cell *cell = new Cell();
    		cell->set_x(1.0);
    		cell->set_y(2.0);
    		cell->set_indexX(i*4);
    		cell->set_indexY(i*5);
    		vector<Particle*> particle_list;
    		cell->set_particleList(particle_list);
    		mCellCollection.push_back(cell);
    	}
    	done(argon);
    	return 0;
    }
    
    void done(md* argon)
    {
    	vector<Cell*> collection = argon->get_cellCollection();
    	for(int i=0; i<collection.size(); i++){
    		Cell *cell = collection[i];
    		double x = cell->get_x();
    		double y = cell->get_y();
    		int idx = cell->get_indexX();
    		int idy = cell->get_indexY();
    		cout << x << "  " << y << "  " << idx << "  " << idy << endl;
    		cell->set_indexX(i*6);
    	}
    	
    	vector<Cell*> coll = argon->get_cellCollection();
    	for(int j=0; j<coll.size(); j++){
    		Cell *cel = coll[j];
    		double x = cel->get_x();
    		double y = cel->get_y();
    		int idx  = cel->get_indexX();
    		int idy  = cel->get_indexY();
    		cout << x << "  " << y << "  " << idx << "  " << idy << endl;
    	}
    	coll.clear();
    }
    In the main part I accessed the reference to the container and update it. In the function "done(md* )", I just copy the container and make some change in first "for loop". Because the reference to the container is not accessed, it is just copy and it should not make change in the container. However, when I accessed it in the second "for loop" it has been changed. If you please don't mind (because it could a be stupid question or the code is not good because in "md.h" I returned reference to the container and in "done(md* )" I just copied it) may I ask why? If I accessed the container in "int main()" like in "done(md* )" then it does not update the container even in "int main()".
    Last edited by manojg; October 30th, 2006 at 11:21 AM.

  5. #5
    Join Date
    Mar 2002
    Location
    California
    Posts
    1,582

    Re: container access question

    You have a copy of the container, that has copies of all the elements, which are pointers.

    A copy of a pointer points to the same thing in memory. Changing something through the copy is the same as changing it through the original pointer.

    This type of copy is known as a "shallow copy".

    Jeff

  6. #6
    Join Date
    Mar 2005
    Posts
    55

    Re: container access question

    ok.
    You have a copy of the container, that has copies of all the elements, which are pointers.
    A copy of a pointer points to the same thing in memory. Changing something through the copy is the same as changing it through the original pointer.
    Doesn't it contratict your first reply
    get_cellCollection() should return a reference to the container. In your code, it's returning a copy.
    Also, why does not it doing the same thing if in "int main()" I replace
    Code:
    vector<Cell*>& mCellCollection = argon->get_cellCollection(); to
    vector<Cell*> mCellCollection = argon->get_cellCollection();

  7. #7
    Join Date
    Mar 2002
    Location
    California
    Posts
    1,582

    Re: container access question

    Quote Originally Posted by manojg
    Doesn't it contratict your first reply
    No. My first reply may not have fixed all your problems, but it was the first step to finding a solution. The container should be returned by reference, leaving it up to the caller to make a copy or not.

    Quote Originally Posted by manojg
    Also, why does not it doing the same thing if in "int main()"
    In main(), you are modifying the container. Modifying a copy of the container has no effect on the original.

    In the function, you are modifying objects through pointers--it does not matter if you copy the pointers or not--you are looking at the same object.

    Jeff

  8. #8
    Join Date
    Mar 2005
    Posts
    55

    Re: container access question

    Thank you very much Jeff for your help. I am trying to fix it.

  9. #9
    Join Date
    Mar 2005
    Posts
    55

    Re: container access question

    Hi again,

    I guess I have fixed almost all problem about the pointer in my previous code. However, I have still one problem. I am trying to transfer a pointer from one container to other.
    For an example:

    Two containers are
    Code:
    vector<int*> x and
    vector<int*> y
    I want to transfer few members (let us say member with even index) which are pointers from x to y.
    I tried it different ways but still there is problem.

    I appreciate your help.

  10. #10
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773

    Re: container access question

    This looks just like a Java program "translated" into C++.

    Let's look at this class:
    Code:
    class md
    {
    public:
        md();
       ~md();
    
        vector<Cell*>	get_cellCollection();
       void set_cellCollection(vector<Cell*> );
    
    private:
       vector<Cell*>	mCellCollection;
    };
    This is a totally useless class. It adds nothing to vector< Cell * >. Perhaps you intend that your destructor will delete all the pointers in the vector (note that in C++ you have to take responsibility of doing this). The get and set functions are totally useless, and would be even if you were passing and returning by reference and even if you wrote 2 get functions, one const and one non-const.

    Now looking at this class
    Code:
    class Cell
    {
       private:
       double			x;
    		
      public:
       Cell();
     ~Cell();
      void			set_x(double );
      double			get_x();
    
    };
    inline void			Cell::set_x(double xx)				{ x = xx;}
    inline double			Cell::get_x()					{ return x;}
    Also totally pointless. Just use double.

    So at the end of all this you can throw away both your classes and work with std::vector<double>

  11. #11
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773

    Re: container access question

    Quote Originally Posted by manojg
    Hi again,

    I guess I have fixed almost all problem about the pointer in my previous code. However, I have still one problem. I am trying to transfer a pointer from one container to other.
    For an example:

    Two containers are
    Code:
    vector<int*> x and
    vector<int*> y
    I want to transfer few members (let us say member with even index) which are pointers from x to y.
    I tried it different ways but still there is problem.

    I appreciate your help.
    How often are you going to want a vector of pointers to int?

    What do you mean by transfer a few members?

  12. #12
    Join Date
    Apr 1999
    Posts
    27,449

    Re: container access question

    Quote Originally Posted by manojg
    Two containers are
    Code:
    vector<int*> x and
    vector<int*> y
    I agree with NMTop40. This looks like Java code, not C++ code. This looks like you have a misunderstanding of what vector does with its contents.

    There is absolutely no need for vector<int*>.
    Code:
    std::vector<int> x;
    std::vector<int> y;
    //..
    x.push_back(10);
    y.push_back(x[0]);
    When you have a vector of objects, there is no need for calling "new". The vector calls the copy constructor of the object and places a copy in the vector.

    Even more to the point, there is absolutely no need for a vector of pointers to fundamental types such as int, double, etc. In other words, a vector<double*> is unnecessary in a real program, when a vector<double> is all that's needed.

    Regards,

    Paul McKenzie

  13. #13
    Join Date
    Feb 2005
    Location
    "The Capital"
    Posts
    5,306

    Re: container access question

    Why do you need to keep pointers? I don't understand.

    What is the problem you are facing in transferring the members? Here is a sample code that filters the even and odd indexed elements into two vectors... it may contain bugs and there may be ways to better it
    Code:
    #include<algorithm>
    #include<vector>
    #include<iostream>
    
    template<typename T>
    struct IsEvenIndex{
    	private:
    		static int index;
    		std::vector<T>& refVec;
    	public:
    		bool operator()(const T& t) const{
    			if (index%2==0){
    				++index;
    				refVec.push_back(t);
    				return true;
    			}else{
    				++index;
    				return false;
    			}
    		}
    		IsEvenIndex(std::vector<T>& vec) : refVec(vec){}
    };
    
    int IsEvenIndex<int>::index=0;
    
    template<typename T>
    void PrintVector(const std::vector<T>& t){
    	std::cout << std::endl << "Printing vector contents" << std::endl;
    	for(size_t i=0; i<t.size(); ++i){
    		std::cout << t[i] << '\t';
    	}
    	std::cout << std::endl << std::endl;
    }
    
    int main(){
    	std::vector<int> myintVector;
    	std::vector<int> myotherintVector;
    	myintVector.push_back(10);
    	myintVector.push_back(20);
    	myintVector.push_back(30);
    	myintVector.push_back(40);
    	myintVector.push_back(50);
    	myintVector.push_back(60);
    	myintVector.push_back(70);
    	myintVector.push_back(80);
    	myintVector.push_back(90);
    	myintVector.push_back(100);
    
    	PrintVector(myintVector);
    	std::vector<int>::iterator itend = std::remove_if(myintVector.begin(), myintVector.end(), IsEvenIndex<int>(myotherintVector));
    	myintVector.erase(itend, myintVector.end());
    	PrintVector(myintVector);
    	PrintVector(myotherintVector);
    }
    Outputs:
    Code:
    Printing vector contents
    10      20      30      40      50      60      70      80      90      100
    Printing vector contents
    20      40      60      80      100
    Printing vector contents
    10      30      50      70      90

  14. #14
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773

    Re: container access question

    That's a long way round to do something very simple. Experimentation with algorithms?

    What you can't do is add 2 to your iterator unless you know the vector is even in size. It can be done with simple indexing thus:
    Code:
    for ( size_t idx = 0; idx < vector_size; idx += 2 )
    {
      // do stuff with vec[idx]
    }
    I don't know why you made your functor have a static, but you can provide a simple toggler with an initial value thus:

    Code:
    class Toggler
    {
     bool value;
    public:
      explicit Toggler ( bool init = true ) : value( init )
      {
      }
    
      template < typename T > bool operator() ( T )
      {
         value = !value; // value ^= true might be better
        return !value;
      }
    };
    Now if you want to move the elements from one vector into a new one then just use remove_if and apply both the copy and erase to the sequence (obviously the copy first).

    Code:
    std::vector<int>::iterator itend = std::remove_if
      (myintVector.begin(), myintVector.end(), Toggler( true ) );
    myotherintVector.insert( myotherintVector.back(), itend, myintVector.end() );
    myintVector.erase(itend, myintVector.end());

  15. #15
    Join Date
    Mar 2005
    Posts
    55

    Re: container access question

    Hi every body,

    Thank you very much for reply. I guess I should explain what I want to do.

    I am writing a simulation code for atomic (particle) interaction by cell method. We have a system of atoms say 625. We divide system into cells say 12 X 12 = 144. Each cell has few number of atoms. So, I wrote a class for atom and another for cell. Each cell has a conatiner ( I put vector<Particle*>) to hold the atoms that belongs to it. So, each atom has its cell id where it belongs. Also, each cell has another conainer of its own type to hold its neighbour cells. Now, during interaction the atoms from each cell interact with atoms from its neighbor cells. So, atoms can move from one cell to another. That is why I need to transfer atom from one cell to another. This transfer take place each time step and number of time step is more than 4000. Every time step we check the cell id of atom that depends on its position then they are transfered to the new cell according to their new cell id.

    Paul, I wrote vector<int*> just for an example. Actually, in my code it is vector<Particle*>.

    I am learning c++ and so I am trying to write by making classes.
    Last edited by manojg; November 8th, 2006 at 12:38 PM.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This a Codeguru.com survey!


On-Demand Webinars (sponsored)