C++ need some inputs and help

Hello!
Ill just start out by showing some code:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Person {
private:
    string _name;
    int _age;
    int _id;
public:

    Person(string name, int age, int id) { _name = name; _age = age; _id = id; }

    void showPerson(){
        cout << "Persons name:\t" << _name << endl;
        cout << "Persons age: \t" << _age << endl;
        cout << "Persons id: \t" << _id << endl;
    }
};

int main() {

    vector<Person> Store;
    int id = 100;

    bool rProgram = true;
    do
    {
        string userInput;
        getline(cin, userInput);

        if(userInput == "1"){
            string name1 = "Boris";
            int age1     = 23;

            string name2 = "Selma";
            int age2     = 28;

            Person person1(name1, age1, id);
            Store.push_back(person1);

            id++;

            Person person2(name2, age2, id);
            Store.push_back(person2);
        }
        else if(userInput == "2"){
            for (int i = 0; i < Store.size(); ++i) {
                Store[i].showPerson();
                cout << endl;
            }
        }
        else if(userInput == "3"){
            cout << Store.size() << endl;

            for (int i = 0; i < Store.size(); ++i) {
                cout << Store[i] << endl;
            }
        }
        else if(userInput == "4"){
            rProgram = false;
        }


    }while(rProgram == true);


    return 0;
}

[I save me objects(person) in to the vector named Store]

My first question is, is it possible to show the content in my vector some how?
I did this: " cout << Store.size() << endl; " and that worked. But i want to be able to do something like this (for learning):
" for (int i = 0; i < Store.size(); ++i) {
cout << Store[i] << endl; "
which is not possible?

So my next question is, what is actually stored in my vector. Is it the address to my objects? Nope? Its the objects that is stored in it and each object is taking up 8 bites+ the string…?

ill try it to explain why i might want to do this. If i want to move the objects around in my vector, say for sorting. it could be nice to see what what they are named? So i can move forward and tackle the next problem, for example sort them buy the persons name or age or id.

I’m not sure if any of this makes sense. Apologies in advance!
Best regards!

The way you have this setup, your calls to push_back copy construct a Person instance into your vector. So each call to push_back copies the Person object located on the stack into the vector.

So Store[i] returns a reference to the Person object located in the vector.

Your code “cout << Store[i] << endl;” does not compile because cout has no << overload dealing with Person objects. The simplest way to make your code compile is probably to add a conversion operator to your Person class to convert a Person to a const char * since cout has a << function overload for char *.

add:

operator const char *() const {
            return _name.c_str(); }

to your Person definition and your code will compile.

Simple explanation: Your store is returning references to Person instances, not the Person object itself.

Technical explanation: Your store object is an std::vector whos, operator[] function returns a reference. See here: http://en.cppreference.com/w/cpp/container/vector/operator_at

Solution: You need to use the dereference operator * to go through the reference to the actual object.

for (int i = 0; i < Store.size(); ++i) {
    Person p = *Store[i];  // Dereference person
    p.showPerson();
}

Simple answer: Vector copies each object you pass into push_back() or any insert function.

The technical answer is both. Vectors take ownership of the elements they are storing, because the lifetime of each element in the vector must live at least as long as the array holds a reference to it.

Thus, as the vector elements are owned by the vector, the iterator components of a vector will return the addresses to the objects in which it is storing, rather than copies of the object itself. Think of it as a borrowing mechanism.

It’s unlikely you should want to manipulate an array whilst iterating over it, so it makes sense that, in iteration, it simply returns the address in memory where the element resides, rather than a copy of the element itself.

Edit: To improve, you should use a more safe method of iteration to iterate over a vector:

for (std::vector<Person>::const_iter iter = Store.begin(); iter != Store.end(); ++iter) {
    // Here, `iter` points to a reference of the currently iterated item.
    const Person& p = iter;  // to use a reference
    const Person pObject = *iter; // to dereference Person
}

Using iterators means you do not need to worry about out-of-bounds access as much.

1 Like

That’s correct, and what I said above.

That’s obviously wrong because you can’t use a pointer dereference operator on a reference to an object. If you attempt to compile *Store[i] where Store is a vector < Person > the compiler is going to give you an illegal indirection error.

???

I have no interest in arguing really basic cpp semantics. I urge you to try this before posting again.

It is basic. *Store[i] does not compile… Because Store[i] returns a reference to a Person… And you can’t use a POINTER dereference operator on an object reference…

@cburn11 is correct. You can’t dereference a reference. Go try it out :slightly_smiling_face:

k I stand corrected then. I dunno why most of my code compiles, I could have sworn that references and pointers are exactly the same thing, C++ spec forces references to be non-null.

An alternate way of printing to the one shown by cburn is to overload operator<<. It basically involves making a function for “<<” that takes an ostream object (like cout) and a person object.
That would look something like this:

class Person {
  // keep the rest but also add this.
  // so that the printing can access the variables
  friend ostream &operator<<(ostream &out, const Person &person);
};

// here is the operator overload.
ostream &operator<<(ostream &out, const Person &person) {
  out << "Persons name:\t" << person._name << endl;
  out << "Persons age: \t" << person._age << endl;
  out << "Persons id: \t" << person._id << endl;
  return out; 
  // by returning the ostream, you will be able to chain it together as with normal cout stuff
}

With this, it compiles for me and seems to print as expected.

1 Like