Vector of object pointers does not seem to perform as intended in C++
I have been a follower for a long time but this is the first time I ask a question. In a nutshell, the issue is; vector<Student*> studentvector
that is a vector of object pointers seems to push the student info back as student
; but when I print to see the first one in vector whether it performs as intended, I see it always updates the first record with new coming student info although there is no problem on studentvector.size()
It pushes the record back to the vector as many as how many time I call addStudent(...)
but it fills all vector with the information of last student. What may be done to succeed in filling vector with correct info within this frame, without using smart pointers or advanced stuff?
Sorry if I am vague on my question. You may lead me to provide what is also necessary to understand the problem. Thanks in advance.
addStudent(const string alias, const string name) throw(StudentException)
{
Student* student = new Student(alias, name)
studentvector.push_back(student);
cout << studentvector.front() << endl;
}
That is the implementation of Student;
#include "Student.h"
string *Alias;
string *Name;
Student::Student(string alias)
{
Alias = new string(alias);
}
Student::Student(string alias, string name)
{
Alias = new string(alias);
Name = new string(name);
}
Student::~Student()
{
delete Alias;
delete Name;
}
const string& Student::getAlias() const
{
开发者_如何学JAVAreturn *Alias;
}
void Student::setAlias(const string& alias)
{
*Alias = alias;
}
const string& Student::getName() const
{
return *Name;
}
void Student::setName(const string& name)
{
*Name = name;
}
Consider alias is not reserved.
Doh! Here's your problem - all objects from type Student
use the same global pointers:
string *Alias;
string *Name;
Make these two as members in you class
class Student
{
private:
string *Alias;
string *Name;
//..
};
EDIT:
Also, I don't think, that it's a good idea to use pointer to std::string
, I'd suggest you to use like this:
class Student { private: string Alias; string Name; //.. };
Your Student.cpp defines a single global pointer Alias
and a single pointer Name
. What you really want is a separate Alias
and Name
for each Student
object. You do this by adding members to the class:
class Student {
public:
Student(const std::string& a, const std::string& n);
//...
private:
std::string Alias;
std::string Name;
};
Student::Student(const std::string& a, const std::string& n)
: Alias(a), Name(n)
{}
I may be delirious here, but are you not specifically printing out front, while pushing back?
studentvector.push_back(student);
cout << studentvector.front() << endl;
You're pushing onto the back, not the front, then printing what's in front. Of course you're not seeing front changing. You need to print back or push front. If push front isn't available, you can use insert(container.begin(), object)
.
You also need to move those global string variables into the class as members, so that for each instance of Student
, the student has instances of Name
and Alias
.
Another note... you're dynamically allocating a string class. The purpose of the string class is to handle the dynamic memory of a char*
string for you. There's no reason for you to use string*
s in this situation, as far as I can tell from your code. string
will handle the new
and delete
internally for you.
I agree with what everyone else has said. However, I can't reproduce the problem you say you're having. In particular, the following (rather icky) code correctly outputs two lines saying "Student(foo,bar)".
#include <iostream>
#include <vector>
#include <string>
// NOTE WELL: many things in this code are bad style and should not be imitated.
// One of them is the namespace-polluting using-directive below:
using namespace std;
struct Student {
string alias, name;
Student(string a, string n) : alias(a), name(n) {}
};
class StudentException : public exception {};
vector<Student*> studentvector;
ostream& operator<<(ostream& stream, Student* student) {
stream << "Student(" << student->alias << "," << student->name << ")";
return stream;
}
void addStudent(const string alias, const string name) throw(StudentException)
{
Student* student = new Student(alias, name);
studentvector.push_back(student);
cout << studentvector.front() << endl;
}
int main(void) {
addStudent("foo","bar");
addStudent("baz","quux");
}
It might be helpful to know how your (not-working) code diverges from the above.
A couple of remarks that conceivably might be relevant:
- You aren't by any chance confusing the front and back ends of the vector somehow?
- If (unlike your addStudent function) your actual code has a single Student object, and is modifying it and then pushing a pointer to it onto your vector, then of course you'll get the kind of wrong results you describe, because it'll be the same pointer every time.
std::vector::front() will return you the reference to the first element in the vector. If you want to remove element, you need to call pop_back() which will return the element and remove from the vector.
If you have Boost then check out Boost Pointer Containers.
精彩评论