468,768 Members | 1,605 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,768 developers. It's quick & easy.

static vector of pointers

Jia
Hi all,

I have a class foo which has a static vector of pointers of type base
class, and a static function to set this vector.

#include <iostream>
#include <vector>
using namespace std;
class super{
protected:
int a;
public:
virtual void printOut(){ cout << "super " << endl;}
};

class subA : public super{
protected:
int a_a;
public:
virtual void printOut(){ cout << "subA" << endl;}
};

class subB : public super{
protected:
int a_b;
public:
virtual void printOut(){cout << "subB" << endl;}
};

class foo {
protected:
static std::vector<super*myList;
static std::vector<static subAtemplist;
static int count;
public:
static void setMyList();
static vector<super*getMyList();
};

std::vector<super*>foo::myList;
std::vector<subAfoo::templist;
int foo:: count = 0;
void foo::setMyList(){
subA mysubA;
templist.push_back(mysubA);
myList.push_back(&(templist[count]));
count++;
cout<< count << " time call setMyList" << endl;
}

vector<super*foo::getMyList()
{
return myList;
}

main()
{

foo::setMyList();
foo::setMyList();

vector<super*newList;
newList = foo::getMyList();
newList[0]->printOut();
}
What I really try to achieve is to set the myList to a vector of
pointers of super type, but actually points to the derived class
objects. I use a static vector of subA to store the sub object, so
that I could use its address to initilize myList( I know this is very
ugly, but I haven't figure out other method). But my problem is that
myList is not properly set as I expected. For example, as above
program will crush as try to execute newList[0]->printOut(). I
figured out that everytime templist calls push_back, its address has
been changed ( the first time is 0x0033c10, and second time after
push_back is called, its address has been changed) so that myList
first pointer points to nowhere, but I have already defined the
templist as static. Can anyone explain this to me? I hope I explain
myself clearly.

Apr 20 '07 #1
6 3684
On Apr 20, 11:21 am, Jia <JiaLi...@gmail.comwrote:
Hi all,

I have a class foo which has a static vector of pointers of type base
class, and a static function to set this vector.

#include <iostream>
#include <vector>
using namespace std;
class super{
protected:
int a;
public:
virtual void printOut(){ cout << "super " << endl;}

};

class subA : public super{
protected:
int a_a;
public:
virtual void printOut(){ cout << "subA" << endl;}

};

class subB : public super{
protected:
int a_b;
public:
virtual void printOut(){cout << "subB" << endl;}

};

class foo {
protected:
static std::vector<super*myList;
static std::vector<static subAtemplist;
static int count;
public:
static void setMyList();
static vector<super*getMyList();

};

std::vector<super*>foo::myList;
std::vector<subAfoo::templist;
int foo:: count = 0;
void foo::setMyList(){
subA mysubA;
templist.push_back(mysubA);
myList.push_back(&(templist[count]));
count++;
cout<< count << " time call setMyList" << endl;

}

vector<super*foo::getMyList()
{
return myList;

}

main()
{

foo::setMyList();
foo::setMyList();

vector<super*newList;
newList = foo::getMyList();
newList[0]->printOut();}

What I really try to achieve is to set the myList to a vector of
pointers of super type, but actually points to the derived class
objects. I use a static vector of subA to store the sub object, so
that I could use its address to initilize myList( I know this is very
ugly, but I haven't figure out other method). But my problem is that
myList is not properly set as I expected. For example, as above
program will crush as try to execute newList[0]->printOut(). I
figured out that everytime templist calls push_back, its address has
been changed ( the first time is 0x0033c10, and second time after
push_back is called, its address has been changed) so that myList
first pointer points to nowhere, but I have already defined the
templist as static. Can anyone explain this to me? I hope I explain
myself clearly.
Apparently my previous response didn't go through or has been delayed.
The fundamental problem is that templist is being resized by the
push_back, which invalidates all pointers and iterators. Try this
instead:
#include <iostream>
#include <vector>
using namespace std;

struct super
{
virtual ~super() {}
virtual void printOut()
{ cout << "super\n";}
};

struct subA : super
{
virtual void printOut()
{ cout << "subA\n"; }
};

class foo
{
vector<super*myList;
public:
~foo()
{
for( size_t n=0; n < myList.size(); ++n )
{
delete myList[n];
}
}

void setMyList()
{
myList.push_back( new subA );
cout<< "called setMyList" << endl;
}

vector<super*getMyList() const
{
return myList;
}
};

int main()
{
foo f;
f.setMyList();
f.setMyList();

const vector<super*newList = f.getMyList();
for( size_t n=0; n < newList.size(); ++n )
{
newList[n]->printOut();
}
}

Cheers! --M

Apr 20 '07 #2
Jia
On 20 Apr, 22:12, mlimber <mlim...@gmail.comwrote:
On Apr 20, 11:21 am, Jia <JiaLi...@gmail.comwrote:
Hi all,
I have a class foo which has a static vector of pointers of type base
class, and a static function to set this vector.
#include <iostream>
#include <vector>
using namespace std;
class super{
protected:
int a;
public:
virtual void printOut(){ cout << "super " << endl;}
};
class subA : public super{
protected:
int a_a;
public:
virtual void printOut(){ cout << "subA" << endl;}
};
class subB : public super{
protected:
int a_b;
public:
virtual void printOut(){cout << "subB" << endl;}
};
class foo {
protected:
static std::vector<super*myList;
static std::vector<static subAtemplist;
static int count;
public:
static void setMyList();
static vector<super*getMyList();
};
std::vector<super*>foo::myList;
std::vector<subAfoo::templist;
int foo:: count = 0;
void foo::setMyList(){
subA mysubA;
templist.push_back(mysubA);
myList.push_back(&(templist[count]));
count++;
cout<< count << " time call setMyList" << endl;
}
vector<super*foo::getMyList()
{
return myList;
}
main()
{
foo::setMyList();
foo::setMyList();
vector<super*newList;
newList = foo::getMyList();
newList[0]->printOut();}
What I really try to achieve is to set the myList to a vector of
pointers of super type, but actually points to the derived class
objects. I use a static vector of subA to store the sub object, so
that I could use its address to initilize myList( I know this is very
ugly, but I haven't figure out other method). But my problem is that
myList is not properly set as I expected. For example, as above
program will crush as try to execute newList[0]->printOut(). I
figured out that everytime templist calls push_back, its address has
been changed ( the first time is 0x0033c10, and second time after
push_back is called, its address has been changed) so that myList
first pointer points to nowhere, but I have already defined the
templist as static. Can anyone explain this to me? I hope I explain
myself clearly.

Apparently my previous response didn't go through or has been delayed.
The fundamental problem is that templist is being resized by the
push_back, which invalidates all pointers and iterators. Try this
instead:
#include <iostream>
#include <vector>
using namespace std;

struct super
{
virtual ~super() {}
virtual void printOut()
{ cout << "super\n";}
};

struct subA : super
{
virtual void printOut()
{ cout << "subA\n"; }
};

class foo
{
vector<super*myList;
public:
~foo()
{
for( size_t n=0; n < myList.size(); ++n )
{
delete myList[n];
}
}

void setMyList()
{
myList.push_back( new subA );
cout<< "called setMyList" << endl;
}

vector<super*getMyList() const
{
return myList;
}
};

int main()
{
foo f;
f.setMyList();
f.setMyList();

const vector<super*newList = f.getMyList();
for( size_t n=0; n < newList.size(); ++n )
{
newList[n]->printOut();
}
}

Cheers! --M
Thanks a lot. Your program makes much more sense than mine. Just want
to ask you a further question(sorrry if it is stupid). Does resize
means that everytime calls push_back(), the first address of memory
will change (not just adding the memory on the existing one)?

Many thanks,
Jia
Apr 21 '07 #3
On Apr 20, 8:09 pm, Jia <JiaLi...@gmail.comwrote:
On 20 Apr, 22:12, mlimber <mlim...@gmail.comwrote:
On Apr 20, 11:21 am, Jia <JiaLi...@gmail.comwrote:
Hi all,
I have a class foo which has a static vector of pointers of type base
class, and a static function to set this vector.
#include <iostream>
#include <vector>
using namespace std;
class super{
protected:
int a;
public:
virtual void printOut(){ cout << "super " << endl;}
};
class subA : public super{
protected:
int a_a;
public:
virtual void printOut(){ cout << "subA" << endl;}
};
class subB : public super{
protected:
int a_b;
public:
virtual void printOut(){cout << "subB" << endl;}
};
class foo {
protected:
static std::vector<super*myList;
static std::vector<static subAtemplist;
static int count;
public:
static void setMyList();
static vector<super*getMyList();
};
std::vector<super*>foo::myList;
std::vector<subAfoo::templist;
int foo:: count = 0;
void foo::setMyList(){
subA mysubA;
templist.push_back(mysubA);
myList.push_back(&(templist[count]));
count++;
cout<< count << " time call setMyList" << endl;
}
vector<super*foo::getMyList()
{
return myList;
}
main()
{
foo::setMyList();
foo::setMyList();
vector<super*newList;
newList = foo::getMyList();
newList[0]->printOut();}
What I really try to achieve is to set the myList to a vector of
pointers of super type, but actually points to the derived class
objects. I use a static vector of subA to store the sub object, so
that I could use its address to initilize myList( I know this is very
ugly, but I haven't figure out other method). But my problem is that
myList is not properly set as I expected. For example, as above
program will crush as try to execute newList[0]->printOut(). I
figured out that everytime templist calls push_back, its address has
been changed ( the first time is 0x0033c10, and second time after
push_back is called, its address has been changed) so that myList
first pointer points to nowhere, but I have already defined the
templist as static. Can anyone explain this to me? I hope I explain
myself clearly.
Apparently my previous response didn't go through or has been delayed.
The fundamental problem is that templist is being resized by the
push_back, which invalidates all pointers and iterators. Try this
instead:
#include <iostream>
#include <vector>
using namespace std;
struct super
{
virtual ~super() {}
virtual void printOut()
{ cout << "super\n";}
};
struct subA : super
{
virtual void printOut()
{ cout << "subA\n"; }
};
class foo
{
vector<super*myList;
public:
~foo()
{
for( size_t n=0; n < myList.size(); ++n )
{
delete myList[n];
}
}
void setMyList()
{
myList.push_back( new subA );
cout<< "called setMyList" << endl;
}
vector<super*getMyList() const
{
return myList;
}
};
int main()
{
foo f;
f.setMyList();
f.setMyList();
const vector<super*newList = f.getMyList();
for( size_t n=0; n < newList.size(); ++n )
{
newList[n]->printOut();
}
}
Cheers! --M

Thanks a lot. Your program makes much more sense than mine. Just want
to ask you a further question(sorrry if it is stupid). Does resize
means that everytime calls push_back(), the first address of memory
will change (not just adding the memory on the existing one)?
Not necessarily, but it could. It depends on whether or not there is
unused capacity in the vector where the new element could be created.
You can use the reserve member function to specify the desired
capacity (which is different from the size), and when the capacity is
exceeded on push_back, the vector will grow by doubling its capacity
and then increasing its size by one. If the capacity is not exceeded,
no growing is necessary, so iterators and pointers are not
invalidated.

BTW, a couple of other remarks about your program that were lost from
my original reply:

Returning the vector like this:

vector<super*newList;
newList = foo::getMyList();

instead of like this:

vector<super*newList = foo::getMyList();

will likely introduce an extra, temporary copy of the vector. The
latter makes use of the return value optimization to eliminate this
copy.

In any case, it's usually better to hide your underlying
representation via encapsulation (see
http://www.parashift.com/c++-faq-lit....html#faq-7.4),
which in this case would likely mean that you give foo a member
function to do the printing for all of its "super" objects rather than
handing out copies of the vector in which it holds them.

Note that I added a virtual destructor to super (see
http://www.parashift.com/c++-faq-lit...html#faq-20.7).

Also, instead of using the destructor that I added to foo, you could
use a smart pointer with container-compatible copy semantics, such as
std::tr1::shared_ptr (aka boost::shared_ptr), Loki::SmartPtr (with
reference counting policies etc.), or the reference counted smart
pointer from this FAQ and those following:

http://www.parashift.com/c++-faq-lit...html#faq-16.22

I omitted this for brevity and clarity, but it's what I would use in
your shoes.

Cheers! --M

Apr 21 '07 #4
On Apr 21, 2:09 am, Jia <JiaLi...@gmail.comwrote:
On 20 Apr, 22:12, mlimber <mlim...@gmail.comwrote:
On Apr 20, 11:21 am, Jia <JiaLi...@gmail.comwrote:
Hi all,
I have a class foo which has a static vector of pointers of type base
class, and a static function to set this vector.
#include <iostream>
#include <vector>
using namespace std;
class super{
protected:
int a;
public:
virtual void printOut(){ cout << "super " << endl;}
};
class subA : public super{
protected:
int a_a;
public:
virtual void printOut(){ cout << "subA" << endl;}
};
class subB : public super{
protected:
int a_b;
public:
virtual void printOut(){cout << "subB" << endl;}
};
class foo {
protected:
static std::vector<super*myList;
static std::vector<static subAtemplist;
static int count;
public:
static void setMyList();
static vector<super*getMyList();
};
std::vector<super*>foo::myList;
std::vector<subAfoo::templist;
int foo:: count = 0;
void foo::setMyList(){
subA mysubA;
templist.push_back(mysubA);
myList.push_back(&(templist[count]));
count++;
cout<< count << " time call setMyList" << endl;
}
vector<super*foo::getMyList()
{
return myList;
}
main()
{
foo::setMyList();
foo::setMyList();
vector<super*newList;
newList = foo::getMyList();
newList[0]->printOut();}
What I really try to achieve is to set the myList to a vector of
pointers of super type, but actually points to the derived class
objects. I use a static vector of subA to store the sub object, so
that I could use its address to initilize myList( I know this is very
ugly, but I haven't figure out other method). But my problem is that
myList is not properly set as I expected. For example, as above
program will crush as try to execute newList[0]->printOut(). I
figured out that everytime templist calls push_back, its address has
been changed ( the first time is 0x0033c10, and second time after
push_back is called, its address has been changed) so that myList
first pointer points to nowhere, but I have already defined the
templist as static. Can anyone explain this to me? I hope I explain
myself clearly.
Apparently my previous response didn't go through or has been delayed.
The fundamental problem is that templist is being resized by the
push_back, which invalidates all pointers and iterators. Try this
instead:
#include <iostream>
#include <vector>
using namespace std;
struct super
{
virtual ~super() {}
virtual void printOut()
{ cout << "super\n";}
};
struct subA : super
{
virtual void printOut()
{ cout << "subA\n"; }
};
class foo
{
vector<super*myList;
public:
~foo()
{
for( size_t n=0; n < myList.size(); ++n )
{
delete myList[n];
}
}
void setMyList()
{
myList.push_back( new subA );
cout<< "called setMyList" << endl;
}
vector<super*getMyList() const
{
return myList;
}
};
int main()
{
foo f;
f.setMyList();
f.setMyList();
const vector<super*newList = f.getMyList();
for( size_t n=0; n < newList.size(); ++n )
{
newList[n]->printOut();
}
}
Cheers! --M

Thanks a lot. Your program makes much more sense than mine. Just want
to ask you a further question(sorrry if it is stupid). Does resize
means that everytime calls push_back(), the first address of memory
will change (not just adding the memory on the existing one)?

Many thanks,
Jia

Apr 21 '07 #5
On Apr 21, 2:09 am, Jia <JiaLi...@gmail.comwrote:
On 20 Apr, 22:12, mlimber <mlim...@gmail.comwrote:
Thanks a lot. Your program makes much more sense than mine. Just want
to ask you a further question(sorrry if it is stupid). Does resize
means that everytime calls push_back(), the first address of memory
will change (not just adding the memory on the existing one)?
It might. Formally, changes in capacity() will cause
invalidation of pointers, references and iterators into the
vector. If you know the final size of the vector, for example,
you can call reserve beforehand, and be sure that push_back
never invalidates anything. Because of the complexity
constraints, too, not every push_back can change the capacity;
but if you've not verified the capacity before hand, or used
reserve, you don't know which ones might.

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 21 '07 #6
Jia
On 21 Apr, 03:22, mlimber <mlim...@gmail.comwrote:
On Apr 20, 8:09 pm,Jia<JiaLi...@gmail.comwrote:
On 20 Apr, 22:12, mlimber <mlim...@gmail.comwrote:
On Apr 20, 11:21 am,Jia<JiaLi...@gmail.comwrote:
Hi all,
I have a class foo which has a static vector of pointers of type base
class, and a static function to set this vector.
#include <iostream>
#include <vector>
using namespace std;
class super{
protected:
int a;
public:
virtual void printOut(){ cout << "super " << endl;}
};
class subA : public super{
protected:
int a_a;
public:
virtual void printOut(){ cout << "subA" << endl;}
};
class subB : public super{
protected:
int a_b;
public:
virtual void printOut(){cout << "subB" << endl;}
};
class foo {
protected:
static std::vector<super*myList;
static std::vector<static subAtemplist;
static int count;
public:
static void setMyList();
static vector<super*getMyList();
};
std::vector<super*>foo::myList;
std::vector<subAfoo::templist;
int foo:: count = 0;
void foo::setMyList(){
subA mysubA;
templist.push_back(mysubA);
myList.push_back(&(templist[count]));
count++;
cout<< count << " time call setMyList" << endl;
}
vector<super*foo::getMyList()
{
return myList;
}
main()
{
foo::setMyList();
foo::setMyList();
vector<super*newList;
newList = foo::getMyList();
newList[0]->printOut();}
What I really try to achieve is to set the myList to a vector of
pointers of super type, but actually points to the derived class
objects. I use a static vector of subA to store the sub object, so
that I could use its address to initilize myList( I know this is very
ugly, but I haven't figure out other method). But my problem is that
myList is not properly set as I expected. For example, as above
program will crush as try to execute newList[0]->printOut(). I
figured out that everytime templist calls push_back, its address has
been changed ( the first time is 0x0033c10, and second time after
push_back is called, its address has been changed) so that myList
first pointer points to nowhere, but I have already defined the
templist as static. Can anyone explain this to me? I hope I explain
myself clearly.
Apparently my previous response didn't go through or has been delayed.
The fundamental problem is that templist is being resized by the
push_back, which invalidates all pointers and iterators. Try this
instead:
#include <iostream>
#include <vector>
using namespace std;
struct super
{
virtual ~super() {}
virtual void printOut()
{ cout << "super\n";}
};
struct subA : super
{
virtual void printOut()
{ cout << "subA\n"; }
};
class foo
{
vector<super*myList;
public:
~foo()
{
for( size_t n=0; n < myList.size(); ++n )
{
delete myList[n];
}
}
void setMyList()
{
myList.push_back( new subA );
cout<< "called setMyList" << endl;
}
vector<super*getMyList() const
{
return myList;
}
};
int main()
{
foo f;
f.setMyList();
f.setMyList();
const vector<super*newList = f.getMyList();
for( size_t n=0; n < newList.size(); ++n )
{
newList[n]->printOut();
}
}
Cheers! --M
Thanks a lot. Your program makes much more sense than mine. Just want
to ask you a further question(sorrry if it is stupid). Does resize
means that everytime calls push_back(), the first address of memory
will change (not just adding the memory on the existing one)?

Not necessarily, but it could. It depends on whether or not there is
unused capacity in the vector where the new element could be created.
You can use the reserve member function to specify the desired
capacity (which is different from the size), and when the capacity is
exceeded on push_back, the vector will grow by doubling its capacity
and then increasing its size by one. If the capacity is not exceeded,
no growing is necessary, so iterators and pointers are not
invalidated.

BTW, a couple of other remarks about your program that were lost from
my original reply:

Returning the vector like this:

vector<super*newList;
newList = foo::getMyList();

instead of like this:

vector<super*newList = foo::getMyList();

will likely introduce an extra, temporary copy of the vector. The
latter makes use of the return value optimization to eliminate this
copy.

In any case, it's usually better to hide your underlying
representation via encapsulation (seehttp://www.parashift.com/c++-faq-lite/classes-and-objects.html#faq-7.4),
which in this case would likely mean that you give foo a member
function to do the printing for all of its "super" objects rather than
handing out copies of the vector in which it holds them.

Note that I added a virtual destructor to super (seehttp://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.7).

Also, instead of using the destructor that I added to foo, you could
use a smart pointer with container-compatible copy semantics, such as
std::tr1::shared_ptr (aka boost::shared_ptr), Loki::SmartPtr (with
reference counting policies etc.), or the reference counted smart
pointer from this FAQ and those following:

http://www.parashift.com/c++-faq-lit...html#faq-16.22

I omitted this for brevity and clarity, but it's what I would use in
your shoes.

Cheers! --M
I see now. Thanks a lot for giving me those links.

Apr 21 '07 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by | last post: by
5 posts views Thread by Vincent RICHOMME | last post: by
11 posts views Thread by toton | last post: by
5 posts views Thread by mast2as | last post: by
5 posts views Thread by Jim Langston | last post: by
11 posts views Thread by Andreas Wollschlaeger | last post: by
reply views Thread by zhoujie | last post: by
reply views Thread by Marin | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.