Store pointers in a vector?

Discussion in 'C++' started by Roland Bengtsson, Dec 19, 2003.

  1. I have a class Conception and I have this in a vector, it should be:

    vector<Conception> vek; // vector
    vector<Conception>::iterator vek; // iterator to vek

    But what if I want to have pointers to class Conception instead? How
    can I do that? And how should I write to declare an iterator to this
    vector?
     
    Roland Bengtsson, Dec 19, 2003
    #1
    1. Advertising

  2. "Roland Bengtsson" <> wrote in message
    news:...
    > I have a class Conception and I have this in a vector, it should be:
    >
    > vector<Conception> vek; // vector
    > vector<Conception>::iterator vek; // iterator to vek
    >
    > But what if I want to have pointers to class Conception instead? How
    > can I do that? And how should I write to declare an iterator to this
    > vector?


    I am just moving to C++, so this may be wrong, but isn't a pointer just a
    data type like anything else? I would think you could declare it like this:

    vector<Conception*> vek; // vector

    No?

    Jeremy
     
    Jeremy Cowles, Dec 19, 2003
    #2
    1. Advertising

  3. Jeremy Cowles wrote:
    > "Roland Bengtsson" <> wrote in message
    > news:...
    >
    >>I have a class Conception and I have this in a vector, it should be:
    >>
    >>vector<Conception> vek; // vector
    >>vector<Conception>::iterator vek; // iterator to vek
    >>
    >>But what if I want to have pointers to class Conception instead? How
    >>can I do that? And how should I write to declare an iterator to this
    >>vector?

    >
    >
    > I am just moving to C++, so this may be wrong, but isn't a pointer just a
    > data type like anything else? I would think you could declare it like this:
    >
    > vector<Conception*> vek; // vector
    >
    > No?
    >
    > Jeremy
    >


    Right, but make sure you've declared vector, and that you're looking in
    the right namespace for it:

    #include <vector>

    int main( )
    {
    std::vector<Conception*> vek; // useless comment
    }
     
    Jeffrey Schwab, Dec 19, 2003
    #3
  4. Jeffrey Schwab wrote:
    > Jeremy Cowles wrote:
    >
    >> "Roland Bengtsson" <> wrote in message
    >> news:...
    >>
    >>> I have a class Conception and I have this in a vector, it should be:
    >>>
    >>> vector<Conception> vek; // vector
    >>> vector<Conception>::iterator vek; // iterator to vek
    >>>
    >>> But what if I want to have pointers to class Conception instead? How
    >>> can I do that? And how should I write to declare an iterator to this
    >>> vector?

    >>
    >>
    >>
    >> I am just moving to C++, so this may be wrong, but isn't a pointer just a
    >> data type like anything else? I would think you could declare it like
    >> this:
    >>
    >> vector<Conception*> vek; // vector
    >>
    >> No?
    >>
    >> Jeremy
    >>

    >
    > Right, but make sure you've declared vector, and that you're looking in
    > the right namespace for it:
    >
    > #include <vector>
    >
    > int main( )
    > {
    > std::vector<Conception*> vek; // useless comment


    Whoops! That should be:

    class Conception;

    std::vector<Conception*> vek; // useless comment

    > }
    >
     
    Jeffrey Schwab, Dec 19, 2003
    #4
  5. Roland Bengtsson

    Mike Wahler Guest

    "Roland Bengtsson" <> wrote in message
    news:...
    > I have a class Conception and I have this in a vector, it should be:
    >
    > vector<Conception> vek; // vector
    > vector<Conception>::iterator vek; // iterator to vek


    You have the same name ('vek') for two different objects!

    >
    > But what if I want to have pointers to class Conception instead?


    No problem.

    > How
    > can I do that?


    Same way you specify any other type element.

    vector<Conception *> vek;

    >And how should I write to declare an iterator to this
    > vector?


    vector<Conception *>::iterator vi;

    Of course now you're responsible for managing any memory pointed
    to by your pointers.

    -Mike
     
    Mike Wahler, Dec 19, 2003
    #5
  6. More code here may clarify!
    Now I have this compiler error:
    main.cpp(37) : error C2679: binary '=' : no operator defined which
    takes a right-hand operand of type 'class std::list<class Conception,
    class std::allocator<class Conception> >::iterator' (or there is no
    acceptable conversion)

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

    class Conception
    {
    public:
    Conception();
    virtual ~Conception();

    char *name; // the classen contains more than this...
    };

    void ListConcept(list &ConceptList);

    void main()
    {
    list CList;

    ListConcept(CList);
    }

    void ListConcept(list &ConceptList)
    {
    // 1. Declare a list with Conception
    list::iterator It_Print;
    // 2. Declare a vector with pointers to Conceptions
    vector SortPage(ConceptList.size());
    // 3. Declare an iterator to go through nr 2.
    vector::iterator it_SortPage;

    // This loop fills SortPage vector with pointers to Conceptions in
    // declaration 1.
    for(It_Print = ConceptList.begin();It_Print !=
    ConceptList.end();It_Print++)
    {
    *it_SortPage = It_Print; // What should be here???
    it_SortPage++;
    }
    }
     
    Roland Bengtsson, Dec 20, 2003
    #6
  7. Roland Bengtsson

    Rolf Magnus Guest

    Roland Bengtsson wrote:

    > More code here may clarify!
    > Now I have this compiler error:
    > main.cpp(37) : error C2679: binary '=' : no operator defined which
    > takes a right-hand operand of type 'class std::list<class Conception,
    > class std::allocator<class Conception> >::iterator' (or there is no
    > acceptable conversion)
    >
    > #include <iostream>
    > #include <vector>
    > #include <list>
    > using namespace std;
    >
    > class Conception
    > {
    > public:
    > Conception();
    > virtual ~Conception();
    >
    > char *name; // the classen contains more than this...
    > };
    >
    > void ListConcept(list &ConceptList);


    ConceptList doesn't have a type, since list is the name of a template,
    not of a type. You must specify the template parameters, like:

    void ListConcept(list<Conception*> &ConceptList);

    I assume you want that, since you asked how to define a container of
    pointers to Conception.

    > void main()



    main() _must_ return int. Nothing else. Never!

    > {
    > list CList;
    >
    > ListConcept(CList);
    > }
    >
    > void ListConcept(list &ConceptList)


    void ListConcept(list<Concept*> &ConceptList)

    > {
    > // 1. Declare a list with Conception
    > list::iterator It_Print;


    list<Concept*>::iteraotr It_Print;

    > // 2. Declare a vector with pointers to Conceptions
    > vector SortPage(ConceptList.size());


    vector<Concept*> SortPage(ConceptList.size());

    > // 3. Declare an iterator to go through nr 2.
    > vector::iterator it_SortPage;


    vector<Concept*>::iterator it_SortPage;

    > // This loop fills SortPage vector with pointers to Conceptions in
    > // declaration 1.
    > for(It_Print = ConceptList.begin();It_Print !=
    > ConceptList.end();It_Print++)
    > {
    > *it_SortPage = It_Print; // What should be here???


    It_Print is an iterator to Concept*, *it_SortPage is a Concept*. That
    doesn't match. Write:

    *it_SortPage = *It_Print;

    > it_SortPage++;
    > }
    > }


    Uhm, I assume your function actually does a bit more, because as it is
    now, it copies the container and then destroys the copy without doing
    anything with it. You also don't seem to modify the list, so your
    function should take a const reference to it.
    Btw, you could make your function a lot shorter by using std::copy from
    <algorithm>:

    void ListConcept(list<Concept*> &ConceptList)
    {
    vector<Concept*> SortPage;
    SortPage.reserve(ConceptList.size());
    std::copy(ConceptList.begin(), ConceptList.end(),
    std::back_inserter(SortPage));

    //the rest, whatever it is supposed to do
    }
     
    Rolf Magnus, Dec 20, 2003
    #7
  8. > > void ListConcept(list &ConceptList);
    >
    > ConceptList doesn't have a type, since list is the name of a template,
    > not of a type. You must specify the template parameters, like:
    >
    > void ListConcept(list<Conception*> &ConceptList);
    >
    > I assume you want that, since you asked how to define a container of
    > pointers to Conception.


    But the list stores not pointers to Conceptions, they store the whole
    Conception

    void ListConcept(list<Conception> &ConceptList)

    A reference is passed to ListConcept()

    > > void main()

    >
    >
    > main() _must_ return int. Nothing else. Never!


    Ok, but I have heared that the compiler put a return 0; in the end of
    main() if the type is void. And this is ansi standard now.

    > Uhm, I assume your function actually does a bit more, because as it is
    > now, it copies the container and then destroys the copy without doing
    > anything with it. You also don't seem to modify the list, so your
    > function should take a const reference to it.


    No, the ListConcept() will sort Conceptions and then list them. The
    ConceptList will not be modified. Is this the right prototyp if I use
    const?

    void ListConcept(const list<Conception> &ConceptList);

    > Btw, you could make your function a lot shorter by using std::copy from
    > <algorithm>:


    This kind of help is always welcome, but I can't compile the code
    anymore with this modifications. VC++ says:

    include\xutility(19) : error C2679: binary '=' : no operator defined
    which takes a right-hand operand of type 'class Conception' (or there
    is no acceptable conversion)

    I got an error in a standard include-file, I have not a clue what it
    is...
    Btw, the next step is the sorting, I have two alternatives, use a
    functionpointer or a functionoperator. None of these are working:)

    Here are the new code:

    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <list>
    using namespace std;

    class Conception
    {
    public:
    Conception(int p=0): page(p) {};

    void SetPage(int t)
    {
    page = t;
    };

    int GetPage()
    {
    return page;
    };
    int page; // The class contains more, this is just a testcase
    };

    // This class is for the sorting
    class Conceptionsorter
    {
    public:
    // A functionoperator
    int operator() (int pageA, int pageB)
    {
    return pageA - pageB;
    };
    };

    void ListConcept(list<Conception> &ConceptList);

    void main()
    {
    list<Conception> CList;
    Conception A,B,C;

    A.SetPage(12);
    B.SetPage(7);
    C.SetPage(24);

    CList.push_back(A);
    CList.push_back(B);
    CList.push_back(C);

    ListConcept(CList);
    }


    // a simple sort function
    int Csort(int pageA, int pageB)
    {
    return pageA - pageB;
    }

    void ListConcept(list<Conception> &ConceptList)
    {
    // 2. Declare a vector with pointers to Conceptions
    vector<Conception *> SortPage;
    vector<Conception *>::iterator it_SortPage;

    SortPage.reserve(ConceptList.size());
    std::copy(ConceptList.begin(), ConceptList.end(),
    std::back_inserter(SortPage));

    // Print all data from the vector, in reality the data is in the
    list
    for(it_SortPage = SortPage.begin();it_SortPage !=
    SortPage.end();it_SortPage++)
    cout << (*it_SortPage)->GetPage() << endl;

    // Sort the data, I have 2 alternatives
    // 1. Give a function as argument
    //sort(SortPage.begin(), SortPage.end(),Csort);

    // 2. Give a functionobject as argument
    //sort(SortPage.begin(), SortPage.end(),Conceptionsorter());
    }
     
    Roland Bengtsson, Dec 21, 2003
    #8
  9. Roland Bengtsson

    Rolf Magnus Guest

    Roland Bengtsson wrote:

    >> > void ListConcept(list &ConceptList);

    >>
    >> ConceptList doesn't have a type, since list is the name of a
    >> template, not of a type. You must specify the template parameters,
    >> like:
    >>
    >> void ListConcept(list<Conception*> &ConceptList);
    >>
    >> I assume you want that, since you asked how to define a container of
    >> pointers to Conception.

    >
    > But the list stores not pointers to Conceptions, they store the whole
    > Conception


    How should I have known that from your incorrect pseudo code? Please
    always post real code to avoid such misunderstandings.

    > void ListConcept(list<Conception> &ConceptList)
    >
    > A reference is passed to ListConcept()
    >
    >> > void main()

    >>
    >>
    >> main() _must_ return int. Nothing else. Never!

    >
    > Ok, but I have heared that the compiler put a return 0; in the end of
    > main() if the type is void. And this is ansi standard now.


    No. A void function doesn't return anything. The C++ standard clearly
    says that main must return int. What you are probably referring to is
    that you can leave out a return statement in main, which will
    implicitly return 0 then. Nevertheless, the return type must still be
    int. Note also that this implicit return is an exception that is only
    valid for the main() function.

    >> Uhm, I assume your function actually does a bit more, because as it
    >> is now, it copies the container and then destroys the copy without
    >> doing anything with it. You also don't seem to modify the list, so
    >> your function should take a const reference to it.

    >
    > No, the ListConcept() will sort Conceptions and then list them. The
    > ConceptList will not be modified.


    Ah, now I see what you want.

    > Is this the right prototyp if I use
    > const?
    >
    > void ListConcept(const list<Conception> &ConceptList);


    Yes.

    >> Btw, you could make your function a lot shorter by using std::copy
    >> from <algorithm>:

    >
    > This kind of help is always welcome, but I can't compile the code
    > anymore with this modifications.


    Well, I was assuming that both containers are supposed to contain
    pointers. If one has direct instances, and the other one has pointers,
    this will of course not work.

    > VC++ says:
    >
    > include\xutility(19) : error C2679: binary '=' : no operator defined
    > which takes a right-hand operand of type 'class Conception' (or there
    > is no acceptable conversion)
    >
    > I got an error in a standard include-file, I have not a clue what it
    > is...


    This is because the std::copy template tries to assign an instance of
    type Conception to a pointer to Conecption, which is not possible. The
    error message could be more clear (e.g. by telling the left hand type,
    too or the line of your code that was the reason for the assignment).

    > Btw, the next step is the sorting, I have two alternatives, use a
    > functionpointer or a functionoperator. None of these are working:)
    >
    > Here are the new code:
    >
    > #include <iostream>
    > #include <algorithm>
    > #include <vector>
    > #include <list>
    > using namespace std;
    >
    > class Conception
    > {
    > public:
    > Conception(int p=0): page(p) {};
    >
    > void SetPage(int t)
    > {
    > page = t;
    > };


    You don't need a semicolon after a function definition.

    >
    > int GetPage()
    > {
    > return page;
    > };
    > int page; // The class contains more, this is just a testcase
    > };
    >
    > // This class is for the sorting
    > class Conceptionsorter
    > {
    > public:
    > // A functionoperator
    > int operator() (int pageA, int pageB)
    > {
    > return pageA - pageB;
    > };
    > };


    The comparison object is expected to take two objects of the element
    type of your container (i.e. pointers to Conception, not int) and
    return a bool (true if the first argument is less, false if it's
    greater than the other), so change it to:

    class Conceptionsorter
    {
    public:
    // A functionoperator
    bool operator()(Conception* a, Conception* b) const
    {
    return a->GetPage() < b->GetPage();
    }
    };


    > void ListConcept(list<Conception> &ConceptList);
    >
    > void main()
    > {
    > list<Conception> CList;
    > Conception A,B,C;
    >
    > A.SetPage(12);
    > B.SetPage(7);
    > C.SetPage(24);
    >
    > CList.push_back(A);
    > CList.push_back(B);
    > CList.push_back(C);
    >
    > ListConcept(CList);
    > }
    >
    >
    > // a simple sort function
    > int Csort(int pageA, int pageB)
    > {
    > return pageA - pageB;
    > }


    You'd need changes similar to those for the function object:

    // a simple sort function
    bool Csort(Conception* a, Conception* b)
    {
    return a->GetPage() < b->GetPage();
    }

    > void ListConcept(list<Conception> &ConceptList)
    > {
    > // 2. Declare a vector with pointers to Conceptions
    > vector<Conception *> SortPage;
    > vector<Conception *>::iterator it_SortPage;
    >
    > SortPage.reserve(ConceptList.size());
    > std::copy(ConceptList.begin(), ConceptList.end(),
    > std::back_inserter(SortPage));


    Well, if one container contains objects and the other one pointers to
    them, you'll need either a function object that returns a pointer, or
    you have to go back to copying the data yourself. I'd do it something
    like this:

    vector<Conception *> SortPage;
    list<Conception>::iterator it = ConceptList.begin();
    list<Conception>::iterator end = ConceptList.end();

    SortPage.reserve(ConceptList.size());
    for(; it != end; ++it)
    SortPage.push_back(&(*it));

    *it will be the element to which the iterator points, and then you need
    to take that element's address with the & operator and append the
    result to the vector.

    > // Print all data from the vector, in reality the data is in the
    > list
    > for(it_SortPage = SortPage.begin();it_SortPage !=
    > SortPage.end();it_SortPage++)
    > cout << (*it_SortPage)->GetPage() << endl;
    >
    > // Sort the data, I have 2 alternatives
    > // 1. Give a function as argument
    > //sort(SortPage.begin(), SortPage.end(),Csort);
    >
    > // 2. Give a functionobject as argument
    > //sort(SortPage.begin(), SortPage.end(),Conceptionsorter());



    Those sort() calls should work with the above modifications.

    > }


    --
    Why is lemon juice mostly artificial ingredients but
    dishwashing liquid contains real lemons?
     
    Rolf Magnus, Dec 21, 2003
    #9
  10. Roland Bengtsson wrote:

    > I have a class Conception and I have this in a vector, it should be:
    >
    > vector<Conception> vek; // vector
    > vector<Conception>::iterator vek; // iterator to vek
    >
    > But what if I want to have pointers to class Conception instead? How
    > can I do that? And how should I write to declare an iterator to this
    > vector?


    The solution might be for you as some other suggest to just just object
    pointers, but that opens up a new can of worms.

    "Who manages the lifetime of the objects in the vector."

    If the aggregated vector goes out of scope your constructor might want
    to delete all the object in the vector. Other objects might now have
    dangling pointers to objects that has been deleted.

    Instead have a look at boost and it's shared pointer implementation. It
    introduces reference counted objects, and ensures that you never get
    another dangling pointer. And you don't have to worry about destruction
    either :)

    The syntax is like

    typedef boost::shared_ptr<Conception> ConceptionPtr;
    std::vector<ConceptionPtr> ConceptionVector;

    // Put new elements in vector
    ConceptionVector.push_back( ConceptionPtr( new Conception(...) );

    // Use elements in vector
    ConceptionVector[42]->ConceptionMemberFunction(...);


    // NOTE: Don't worry about destruction. On end of scope, the shared
    pointer will call the destructors on all objects that have a ref. count = 0

    Hope that helps

    /Anders
     
    Anders Hybertz, Dec 21, 2003
    #10
  11. Btw I didn't get the copy function to compile for me. I suspect that
    it try to copy the whole conception in the ConceptList instead of
    pointers?

    > Btw, you could make your function a lot shorter by using std::copy from
    > <algorithm>:
    >
    > void ListConcept(list<Concept*> &ConceptList)
    > {
    > vector<Concept*> SortPage;
    > SortPage.reserve(ConceptList.size());
    > std::copy(ConceptList.begin(), ConceptList.end(),
    > std::back_inserter(SortPage));
    >
    > //the rest, whatever it is supposed to do
    > }
     
    Roland Bengtsson, Dec 21, 2003
    #11
  12. Anders Hybertz <> wrote in message news:<4cfFb.63024$>...
    > Roland Bengtsson wrote:
    >
    > > I have a class Conception and I have this in a vector, it should be:
    > >
    > > vector<Conception> vek; // vector
    > > vector<Conception>::iterator vek; // iterator to vek
    > >
    > > But what if I want to have pointers to class Conception instead? How
    > > can I do that? And how should I write to declare an iterator to this
    > > vector?

    >
    > The solution might be for you as some other suggest to just just object
    > pointers, but that opens up a new can of worms.
    >
    > "Who manages the lifetime of the objects in the vector."
    >
    > If the aggregated vector goes out of scope your constructor might want
    > to delete all the object in the vector. Other objects might now have
    > dangling pointers to objects that has been deleted.
    >
    > Instead have a look at boost and it's shared pointer implementation. It
    > introduces reference counted objects, and ensures that you never get
    > another dangling pointer. And you don't have to worry about destruction
    > either :)
    >
    > The syntax is like
    >
    > typedef boost::shared_ptr<Conception> ConceptionPtr;


    Hi, I got this error when typing the line above in my program. I have
    never heard of boost, is this a keyword in C++?

    main.cpp(37) : error C2653: 'boost' : is not a class or namespace name

    Anyway I don't think it's a problem with bad pointers in my case
    because I use the vector with pointers as a local variable. When the
    function is ended the vector with the pointers is also automatically
    deleted. But I think you had a good point there to be careful about.

    /Roland
     
    Roland Bengtsson, Dec 21, 2003
    #12
  13. Roland Bengtsson wrote in
    news::

    >
    > Hi, I got this error when typing the line above in my program. I have
    > never heard of boost, is this a keyword in C++?
    >
    > main.cpp(37) : error C2653: 'boost' : is not a class or namespace name
    >


    Boost is a set of C++ libraries goto http://www.boost.org

    boost::shared_ptr docs are at:

    http://www.boost.org/libs/smart_ptr/shared_ptr.htm

    Unfortunatly the download is between 5 and 10 MB depending on the
    archive format you choose, and there is no option to just get only
    the library you want (in this case shared_ptr).

    Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
     
    Rob Williscroft, Dec 21, 2003
    #13
  14. Thanks for your advices, but the problem is solved now.

    /Roland
     
    Roland Bengtsson, Dec 21, 2003
    #14
  15. Roland Bengtsson

    Rolf Magnus Guest

    Roland Bengtsson wrote:

    > Btw I didn't get the copy function to compile for me. I suspect that
    > it try to copy the whole conception in the ConceptList instead of
    > pointers?


    Read my answer to your other posting.
     
    Rolf Magnus, Dec 22, 2003
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. pmatos
    Replies:
    6
    Views:
    23,822
  2. Replies:
    8
    Views:
    1,930
    Csaba
    Feb 18, 2006
  3. ssylee
    Replies:
    1
    Views:
    1,212
    Zachary Turner
    Jan 13, 2009
  4. zl2k
    Replies:
    27
    Views:
    1,589
    Francesco S. Carta
    Sep 7, 2010
  5. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    682
Loading...

Share This Page