this is totally strange. I have some code in which I read some parameters from a file and I store them in two stl vectors. I have atoms and residues, and every atom keeps a pointer to his residue. Once finished reading, after declaring a variable, looks like the values in memory changed:
atoms[0].resid :0x96fc250
&(atoms[0].resid->ID) :0x96fc25c
**(atoms[0].resid->ID) :1**
atoms[1].resid :0x96fc250
&(atoms[1].resid->ID) :0x96fc25c
**(atoms[1].resid->ID) :1**
atoms[2].resid :0x96fc3ec
&(atoms[2].resid->ID) :0x96fc3f8
(atoms[2].resid->ID) :2
atoms[3].resid :0x96fc3ec
&(atoms[3].resid->ID) :0x96fc3f8
(atoms[3].resid->ID) :2
---------------------------------------
atoms[0].resid :0x96fc250
&(atoms[0].resid->ID) :0x96fc25c
**(atoms[0].resid->ID) :891301941**
atoms[1].resid :0x96fc250
&(atoms[1].resid->ID) :0x96fc25c
**(atoms[1].resid->ID) :891301941**
atoms[2].resid :0x96fc3ec
&(atoms[2].resid->ID) :0x96fc3f8
(atoms[2].resid->ID) :2
atoms[3].resid :0x96fc3ec
&(atoms[3].resid->ID) :0x96fc3f8
(atoms[3].resid->ID) :2
Here is the code. I don't really know what I did wrong
#define FT_GRO 1
using namespace std;
class residue{
public:
residue(){}
residue(const residue& r){atoms=r.atoms; ID=r.ID; name= r.name;}
residue(int n, string s) {name=s;ID=n;}
public:
vector<class atom*> atoms;
int ID;
string name;
atom& addAtom(atom& a) { atoms.push_back(&a); return a;}
};
class atom{
public:
atom(){}
atom(const atom& a){ID=a.ID,name=a.name,coord=a.coord,resid=a.resid ;}
atom(const int anum, const string aname, const point3D& p, residue& res){coord=p; name=aname; resid=&res; ID=anum;}
~atom(){}
public:
point3D coord;
int ID;
string name;
double distance(point3D& p) {return coord.distance(p);}
double distance(atom& p) {return coord.distance(p.coord);}
class residue* resid;
};
int main(){
vector<atom> atoms;
vector<residue> residues;
double box1,box2,box3,x,y,z;
char l[256];
int nr,na;
string sr,sa;
int lastResNum = -1;
string lastResName("");
int nAtomsIn=4;
for(int i =0; i<nAtomsIn;i++){
cin.getline(l,255);
istringstream ssatm(l,ios::in);
ssatm >> setw(5) >> nr >> setw(5) >> sr >> setw(5) >> sa >> setw(5) >>na >> setw(8) >> x >>setw(8) >> y >>setw(8) >> z;
if (lastResNum!=nr || sr!=lastResName){
residues.push_back(residue(nr,sr));
}
point3D p(x,y,z);
atoms.push_back( atom(na,sa,p,residues.back()) );
residues.back().addAtom(atoms.back());
cout << "atoms["<<i<<"].resid :" << atoms[i].resid << endl;
cout << "&(atoms["<<i<<"].resid->ID) :" << &(atoms[i].resid->ID) << endl;
cout << "&(atoms["<<i<<"].resid->ID) :" << (atoms[i].resid->ID) << endl;
lastResNum=nr; lastResName=sr;
}
cout << "---------------------------------------"<<endl;
cin.getline(l,255);
istringstream ssbox(l);
ssbox >> setw(10) >> box1>>setw(10) >> box2>>setw(10) >> box3;
for(int i =0; i<atoms.size();i++){
cout << "atoms["<<i<<"].resid :" << atoms[i].resid << endl;
cout << "&(atoms["<<i<<"].resid->ID) :" << &(atoms[i].resid->ID) << endl;
cout << "&(atoms["<<i<<"].resid->ID) :" << (atoms[i].resid->ID) << endl;
}
return 0;
}
What you're seeing is perfectly normal behaviour -- when you add new elements to a vector, it may get resized, hence all the elements are copied to a new memory location.
If you need a guarantee that existing elements aren't moved in memory, use a different container such as list or set.
std::vector will move memory when it needs more space. It allocates a contiguous block of memory, and when that block fills up, it allocates a bigger block, copies all the elements from the old block to the new one, frees the old block, and moves on.
To prevent the behavior you are seeing, you can do any of a few things to improve your design patter:
1) Change your vectors in main() to store pointers instead of stack options. This way, the object will always be in the same place in memory.
2) Change your class declarations to allow deep copies by implementing a copy-constructor and assignment operator
3) Modify your class heirarchy to remove the circular dependency between your classes. You can do this by having a Residue class, an Atom class, and another class that maps the 2 to each other.
The simplest option will be #1. You'll just need to make sure you clean up memory properly.
Like casablanca said, whenever your vector expands, it change where the objects are in memory.
If you really want to use vectors instead of some other container
1) you can reserve a large piece of memory for your vector. If you have a guarantee that the number of these objects won't exceed a certain bound and you don't mind using up that much memory, then make your vector that large.
2) make them vectors of pointers. If you have a very modern compiler (gcc >= 4.4 for example), you may even have access to the new unique_ptr smart pointer class from C++0x, which lets you use smart pointers in stl containers. These great additions to the language.
Related
While performing a practice assignment online I came across a problem which I am not able to solve.
The user has to a number(number of sentences he will be entering) and then proceed to enter the sentences one by one, which are to be stored as strings(by the way, declaring a dynamic array of pointers is mandatory). However, since the number of sentences is not a priori deducible, I know that the size of the array of pointers actually is the number of sentences but I can't figure out how to declare a dynamic array of pointers to strings.
Using something I had already known beforehand, I figured out how to do the same but with arrays of characters, not arrays of strings. The line that declared a dynamic array of pointers to dynamic arrays of chars looked like this:
char **ptr=new char*[n] {};
So with my understanding, this creates a pointer ptr which points to a dynamic array of pointers, the elements of which each point to one array of characters. I want to do something similar now, where the result should be that ptr is a pointer to a dynamic array of pointers, the elements of which each point to a string.
Can anyone help out? I'd be thankful!
I think what you are looking for is something like
std::size_t num;
std::cout << "enter the number of sentences\n";
std::cin >> num;
std::string *sentences = new std::string[num];
for(std::size_t i=0; i!=num; ++i) {
std::cout << "enter the " << (i+1) << "th sentence\n";
std::cin >> sentences[i];
}
/*
... (do something with the sentences, accessing them as sentences[i])
*/
delete[] sentences; // free the memory
Note that this style of coding is highly discouraged. The problem is the need to manage the allocated memory: avoid memory leaks and dangling pointers (including exception safety). The correct approach is to use a container or smart pointer. For example:
std::size_t num;
std::cout << "enter the number of sentences\n";
std::cin >> num;
std::vector<std::string> sentences{num};
for(std::size_t i=0; i!=num; ++i) {
std::cout << "enter the " << (i+1) << "th sentence\n";
std::cin >> sentences[i];
}
/*
... (do something with the sentences, accessing them as sentences[i])
*/
or
std::size_t num;
std::cout << "enter the number of sentences\n";
std::cin >> num;
std::unique_ptr<std::string[]> sentences{new std::string[num]};
for(std::size_t i=0; i!=num; ++i) {
std::cout << "enter the " << (i+1) << "th sentence\n";
std::cin >> sentences[i];
}
/*
... (do something with the sentences, accessing them as sentences[i])
*/
when in both cases you don't have to worry about calling delete: the allocated memory will be automatically deleted (even if an exception occurs).
You can avoid pointers completely and use
std::vector<std::string> input;
A std::array needs to know the size at compile time, and you learn this at runtime. The vector works like an array but can have items push_backed at runtime.
You could declare pointer to some strings, using n once you know it:
std::string * pInputs = new std::string[n];
but it's easier to use the vector.
Each pInput will be a string, as with the std::vector version.
#include <iostream>
#include <vector>
int main()
{
unsigned int numVec;
unsigned int input;
std::cout << "Enter Number of Vectors: ";
std::cin >> numVec;
std::vector<int>* Vec;
for (unsigned int i = 0; i < numVec; i++)
{
std::cout << "Enter Vector Value " << i << ": ";
std::cin >> input;
Vec->push_back(input);
}
std::cout << std::endl;
for (unsigned int i = 0; i < Vec->size(); i++)
{
std::cout << "Value at Index (" << i << ") " << Vec->at(i) << std::endl;
}
std::cout << std::endl;
return 0;
}
I am trying to learn how Vectors work as it is a topic that i have withheld learning for a very long time for no apparently reason.
My above code will compile and run however once i put in a number to store in the Vector it will crash.
The program did work before when i was just using a vector without the pointer but just for learning reasons i wanted to try it with a pointer, I am just wondering what am i doing wrong with this code and if someone could possibly flame me for doing something or give me some good advice on what i am doing wrong in this situation so i can learn for future reference.
Replace
std::vector<int>* Vec;
with
std::vector<int> vec;
and replace the pointer to member operator -> with the member selection operator ..
Only on rare occasions do you need to use dynamic storage for a std::vector instance, as that class does an excellent job of managing the memory for you. Currently you are not allocating any memory for your vector, and the behaviour of your code is undefined.
If you must use a pointer then write
std::vector<int>* vec = new std::vector();
and don't forget to call delete vec; when you're done. Consider using std::unique_ptr &c. so the delete is taken care of automatically.
My above code will compile and run however once i put in a number to store in the Vector it will crash.
What vector?
You never created a vector.
You only created a pointer, one which (a) is uninitialised, and (b) does not point to anything, let alone a (c) vector.
For example, I have a vector which is declared this way:
vector<Shapes> *ShapeVector;
If I want to have a shape object, and to be able to access different shapes that're of different sizes, would declaring 'new' or not be needed? What about pointers then?
To me, pointers point to different addresses to access. So, would I need pointers too?
So far, I did the following code to create my object, and to store arrays in it. After that, I would plan to store the object into the vector itself.
int tempx[100],tempy[100];
for (int i = 0; i < 4;i ++)
{
cout << "Enter x-coordinate of pt " << i << ":" << endl;
cin >> tempx[i];
cout << "Enter y-coordinate of pt " << i << ":" << endl;
cin >> tempy[i];
Square mysquare = new Square(tempx,tempy);
Not sure if it's correct though, unsure on when to use 'new' and when to use pointers.
You can use simply std::vector<Shapes> my_vector, without pointers. The vector object will be allocated on the stack, its content on the heap. You will have the advantage that the Shape objects will be placed contiguously in memory.
Excuse me again, I'm not any genius in Programming.
First of all, a summary: array input. Two 3D vectors...ha ha, let's use vectors to calculate MORE vectors. Anyway: dot product is just and plain ridiculous (nine numerals before decimals; I mean, seriously, I didn't ever thought that 1x8+7x5+4x2 could have NINE numerals). Cross product is...even worse.
I made the...uhm...how could I call it? Well, we call it "traza". I'll translate a definition ir order to get understood: a code's "traza" tell us the sequence of instructions of its execution, and how do the variables change after every line of code. You know, the table with variables and number marks referred to code lines where we look if the code is doing something unexpected. Getting to the point: it's everything fine as far as I could see.
Then, I made an unexpectedly "pseudotraza" with a print command and every value from the vectors. Just after input and just before te dot product (in a function). Guess what:
1) it's not my input, in either of them
2) they are not even the same values
3) first values are far away from my input, but the following ones at least were more logic (less difference to the input).
I learned this morning, 12 hours ago, to use arrays/vectors/whatever. I didn't ever have any need to set as 0 as default any value before its input. But it's the only thing I have known to do when things like this happened to me before.
(Someday any of you will be my Programming teacher, you are learning me more than himself...and excuse my awful grammar, English teaching in Spain is just "take some grammar rules and no more than 50 exercises in last High School year...it's all you need to pass the University Entrance Exam!")
#include <iostream>
using namespace std;
#include <stdlib.h>
const int N = 3;
typedef int Vector[N];
void introduirVector (Vector);
float producteEscalar (const Vector, const Vector); /*Input vector and dot product*/
int main (void)
{
Vector v1, v2;
float p_esc;
cout << "Introduim les dades del vector A: "; /* Input */
introduirVector (v1);
cout << "Introduim les dades del vector B: "; /* 2x Input combo */
introduirVector (v2);
cout << v1[0] << "\n" << v1[1] << "\n" << v1[2] << "\n" << v2[0] << "\n" << v2[1] << "\n" << v2[2] << endl; /* "Puseudotraza*/
p_esc= producteEscalar (v1, v2); /*Dot product*/
cout << "El producte escalar: " << p_esc; /*Dot product is...*/
system ("PAUSE");
return 0;
}
/*3x Input combo*/
void introduirVector (Vector)
{
int i;
Vector v;
for (i = 0; i < N; i++)
{
cin >> v[i];
}
return;
}
/* Dot product (why all the Vectors are set as constants but another after this is not set? It's the hint given by the teacher, my (not) beloved teacher...they gave us the main function and the other function's prototypes, but that's all) */
float producteEscalar (const Vector, const Vector)
{
float escalar;
Vector v1, v2;
/* Pseudotrazas for all*/
cout << v1[0] << "\n" << v1[1] << "\n" << v1[2] << "\n" << v2[0] << "\n" << v2[1] << "\n" << v2[2] << endl;
/* Dot product and all that */
escalar = (v1[0]*v2[0])+(v1[1]*v2[1])+(v1[2]*v2[2]);
return escalar;
}
The problem is this:
/*3x Input combo*/
void introduirVector (Vector)
{
int i;
Vector v;
This function takes a Vector as a parameter, but the Vector has no name so it cannot be used inside the function.
Then you declare a new, local Vector v. You read your user's input into this vector.
The function then ends, at which point the vector into which you read user input goes away.
Firstly, you should be using the parameter you were called with, not a local variable. But your second problem is that you are using pass by value. When you call this function, introduirVector (v1); it is not the "v1" you know and love from main that you are working with inside introduirVector, but a local copy of it that ceases to exist when your function returns.
What you need to do is make your function accept a pointer or a reference to the Vector it is being called with:
void introduirVector(Vector& v)
{
for (size_t i = 0; i < 3; ++i) {
cin >> v[i];
}
}
This does not fully solve all of the problems with your code, but it should get you moving forward.
I'm not seeing any input, which would be why you are not receiving any input.
Try using:
string inpt;
int a, b, c;
cin >> inpt;
a = atoi( inpt.c_str());
inpt = "";
cin >> inpt;
b = atoi( inpt.c_str());
// etc...
// Make your vector in this fashion, grabbing each integer separately then loading them
// into a vector
I am new to c++ programming and I have a basic issue, I want to create N objects, N is is actually a user input.
I am specific about having object names, say beam1, beam2,...,beamX.
2 quick things
Is it possible in C++ to create dynamic object as this?
if it is how do we do tht? I am pasting code for your refrence..
#include "iostream"
# include <conio.h>
using namespace std;
// Static member variable is defined outside the class..
class beam {
public:
int length;
};
int main ()
{
int i=0, no_of_spans, j;
cout<< "Design Of a Continous Beam \n1) No Of Spans : ";
cin >> no_of_spans;
for (i =0; i < no_of_spans; i++) {
j = i;
beam;
cout << "Length of Beam" << j+1 << " is : ";
cin >> beami.length;
}
cout << "\nPress any key to continue..\n";
getch ();
}
This is obviously a code with errors, its put up as an example to get the idea.
As has already been stated by others (Luchian, John, Component and Ed) you can use a std::vector and it will dynamically grow as necessary to store the number of beam objects required.
If you wish to refer to these objects later by name you could store them in a std::map, with the key of the map being the object name (e.g. beam1, beam2, beam3, ..., beamX):
std::map<std::string, beam> beams;
for (int i = 0; i < no_of_spans; i++)
{
j = i;
beam beam;
std::string beam_name("beam" + boost::lexical_cast<std::string>(i + 1));
cout << "Length of " << beam_name << " is : ";
cin >> beam.length;
beams.insert(std::make_pair(beam_name, beam));
}
--
boost::lexical_cast<> is a mechanism for converting (in this case) an int to a std::string. There other ways to achieve this (using std::ostringstream for example).
You can use a std::vector to store the objects.
You use push_back to add elements to the vector.
Something along the lines of:
std::vector<beams> beamCollection;
for (i =0; i < no_of_spans; i++) {
j = i;
beam beami;
cout << "Length of Beam" << j+1 << " is : ";
cin >> beami.length;
beamCollection.push_back(beami);
}
Yes, of course it's possible. There are several ways.
One way, the way I'd prefer if possible/practical, is to use std::vector and push_back, transform or generate_n how ever many objects you needed.
Another way is to use new to allocate an array of the object you want. This is less preferred to using a vector however, because by using new you take on the responsibility of managing the memory -- there needs to be a delete that corresponds to every new. This can be mitigated by using a smart pointer such as std::unique_ptr, but it's often best to just avoid the cactus altogether.
Yes, it is possible. Your best bet is to use an appropriate STL collection and dynamically grow it at runtime by adding / removing objects.
Short answer no - the compiler needs to know the names of variables at compile time.
You need to use an array (or vector).