-
October 27th, 2006, 12:17 PM
#1
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 12:21 PM.
-
October 27th, 2006, 12:31 PM
#2
Re: container access question
get_cellCollection() should return a reference to the container. In your code, it's returning a copy.
Jeff
-
October 27th, 2006, 12:35 PM
#3
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
-
October 30th, 2006, 11:12 AM
#4
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.
-
October 30th, 2006, 11:36 AM
#5
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
-
October 30th, 2006, 11:56 AM
#6
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();
-
October 30th, 2006, 12:05 PM
#7
Re: container access question
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.
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
-
October 31st, 2006, 02:55 PM
#8
Re: container access question
Thank you very much Jeff for your help. I am trying to fix it.
-
November 7th, 2006, 08:20 PM
#9
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.
-
November 8th, 2006, 05:10 AM
#10
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>
-
November 8th, 2006, 05:13 AM
#11
Re: container access question
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?
-
November 8th, 2006, 05:24 AM
#12
Re: container access question
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
-
November 8th, 2006, 07:17 AM
#13
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
Can you help me with my homework assignment?, Before you post!, Use code tags, How to post!, Codeguru technical FAQs, C++ FAQ Lite, Stroustrup: C++ Style and Technique FAQ, Guru of the Week, Comeau C and C++ FAQs, Comeau C++ Templates FAQs, CUJ @ DDJ, Spam threshold
My Blogs : Learning C++ is fun | Abnegator's reflections
Open Threads : C++ Aha! Moments | Nature of work in C++?
-
November 8th, 2006, 07:43 AM
#14
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());
-
November 8th, 2006, 10:02 AM
#15
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.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|