Just wondering, because of a problem I am running into, is it possible to create a vector of pointers? And if so, how? Specifically concerning using iterators and .begin() with it, ie: How would I turn this vector into a vector of pointers:
class c
{
void virtual func();
};
class sc:public c
{
void func(){cout<<"using func";}
};
sc cobj;
vector<c>cvect
cvect.push_back(cobj);
vector<c>::iterator citer
for(citer=cvect.begin();citer<cvect.end();citer++)
{
citer->func();
}
Sure.
vector<c*> cvect;
cvect.push_back(new sc);
vector<c*>::iterator citer;
for(citer=cvect.begin(); citer != cvect.end(); citer++) {
(*citer)->func();
}
Things to keep in mind:
You'll need to cleanup after your self if you use dynamically allocated memory as I did in my example
e.g.:
for(...) { delete *i; }
This can be simplified by using a vector of shared_ptrs (like boost::shared_ptr). Do not attempt to use std::auto_ptr for this, it will not work (won't even compile).
Another thing to keep in mind, you should avoid using < to compare iterators in your loop when possible, it will only work for iterators that model a random access iterator, which means you can't change out your code to use e.g. a std::list.
vector <c> cvect is not a vector of pointers. It is a vector of objects of type c. You want vector <c*> cvect. and the you probably want:
cvect.push_back( new c );
And then, given an iterator, you want something like:
(*it)->func();
Of course, it's quite probable you didn't want a vector of pointers in the first place...
Yes it is possible, and in fact it is necessary to use pointers if you intend your vector to contain objects from an entire class hierarchy rather than of a single type. (Failing to use pointers will result in the dreaded problem of object slicing -- all objects are silently converted to base class type. This is not diagnosed by the compiler, and is almost certainly not what you want.)
class c
{
void virtual func();
};
class sc:public c
{
void func(){cout<<"using func";}
};
sc cobj;
vector<c*> cvect; // Note the type is "c*"
cvect.push_back(&cobj); // Note the "&"
vector<c*>::iterator citer;
for(citer=cvect.begin();citer != cvect.end();citer++) // Use "!=" not "<"
{
(*citer)->func();
}
Note that with a vector of pointers, you need to do your own memory management, so be very careful -- if you will be using local objects (as above), they must not fall out of scope before the container does. If you use pointers to objects created with new, you'll need to delete them manually before the container is destroyed. You should absolutely consider using smart pointers in this case, such as the smart_ptr provided by Boost.
Yes, sure.
// TestCPP.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
class c
{
public:
void virtual func() = 0;
};
class sc:public c
{
public:
void func(){cout<<"using func";}
};
int _tmain(int argc, _TCHAR* argv[])
{
sc cobj;
vector<c*> cvect;
cvect.push_back(&cobj);
vector<c*>::iterator citer;
for(citer=cvect.begin();citer<cvect.end();citer++)
{
(*citer)->func();
}
return 0;
}
Please note the declaration of vector<c*> cvect and the use of cvect.push_back(&cobj).
From the code provided, you are using iterator in a wrong way. To access the member an iterator is pointing to you must use *citer instead of citer alone.
You have create vector<c*> for a vector of pointers. Then use new to allocate the memory for c objects and push them into vector. Also, don't forget that you have to delete yourself and vector.clear() will not release the memory allocated for c objects. You have to store c as a vector of pointers here, otherwise the call to the virtual function will not work.
Try Boost Pointer Container Library. It has several advantages over regular vector of pointers, like:
my_container.push_back( 0 ); // throws bad_ptr
ptr_vector<X> pvec;
std::vector<X*> vec;
( *vec.begin() )->foo(); // call X::foo(), a bit clumsy
pvec.begin()->foo(); // no indirection needed
Related
I’m a C++ beginner with a background in Python, Java, and JS, so I’m still learning the ropes when it comes to pointers.
I have a vector of shared pointers. Inside of a different function, I assign a shared pointer to a variable and add it to the vector. If I try to access the added element after that function exits, a segmentation fault happens:
class Bar
{
private:
std::vector<std::shared_ptr<Foo>> fooVector;
}
void Bar::addToFoo()
{
std::shared_ptr<Foo> foo (new Foo(…));
fooVector.push_back(foo);
}
void Bar::otherMethod()
{
// this method gets called sometime after addToFoo gets called
…
fooVector[anIndex]->baz(); // segfaults
…
}
But, if push_back a shared pointer and not a variable, it works.
// this works:
fooVector.push_back(std::shared_ptr<Foo>(new Foo(…)));
// this segfaults:
std::shared_ptr<Foo> foo (new Foo(…));
fooVector.push_back(foo);
I believe it happens because the foo variable gets deleted when the addToFoo function exits (correct me if I’m wrong). How do you push_back a shared_ptr variable to a vector of shared_ptrs in C++?
Why Use A Variable
Though pushing shared_ptrs to vectors directly without variables works, I prefer to use variables in order to do this:
std::shared_ptr<Rider> rider;
switch (iProcessorModesParam)
{
case PEAKS_MODE:
rider = std::shared_ptr<Rider>(new PeaksRider(…));
break;
case RMS_MODE:
rider = std::shared_ptr<Rider>(new RMSrider(…));
break;
}
volumeRiders.push_back(rider);
PeaksRider and RMSrider are subclasses of Rider. I want to store all subtypes of Rider in the same vector of Riders. I learned that adding subtypes of Rider to a vector of Riders doesn’t work and pointers are needed in order to achieve this kind of polymorphism:
std::vector<Rider> // doesn’t work with subtypes
std::vector<*Rider>
std::vector<std::shared_ptr<Rider>>
Having the std::shared_ptr<Rider> rider; variable avoids repeating the .push_back(…) code for each type of Rider.
Instead of assigning shared pointer, user reset method.
rider.reset(new PeaksRider(…));
other that this, your code snippets seems to okay to me.
segfault may have caused because of the index variable ( which may be out of range). i suggest you to use .at(index) for accessing pointer from vector and wrap that part of code in a try..catch block and see what is the real error.
And regarding...
I believe it happens because the foo variable gets deleted when the addToFoo function exits (correct me if I’m wrong).
This is not true, share_ptrs use a local counter for #of references. as soon as you pushed the pointer to vector the counter gets incremented to 2 and event after control exits the function the counter is decremented to 1. so, your object is not destroyed yet.
There is no problem on creating a shared pointer instance, storing it in a variable, and doing a push_back to a vector after that. Your code should be fine as long as the index that you use when calling "otherMethod" is valid. However, I have a couple of suggestions for your code:
When you create a shared_ptr, it is highly recommended to do it through "std::make_shared" to ensure the safety and correctness of your code in all situations. In this other post you will find a great explanation: Difference in make_shared and normal shared_ptr in C++
When accessing positions of a vector using a variable that may contain values that would cause an out-of-bounds access (which usually leads to segmentation faults) it is a good practice to place asserts before using the vector, so you will detect these undesired situations.
I just wrote a small snippet that you can test to illustrate what I just mentioned:
#include <iostream>
#include <vector>
#include <memory>
#include <cassert>
class Foo
{
public:
int data = 0;
};
class Bar
{
public:
void addNewFoo(int d)
{
std::shared_ptr<Foo> foo(new Foo());
foo->data = d;
fooVector.push_back(foo);
}
void addNewFooImproved(int d)
{
auto foo = std::make_shared<Foo>();
foo->data = d;
fooVector.push_back(foo);
}
void printFoo(int idx)
{
assert(idx < fooVector.size());
std::cout << fooVector[idx]->data << std::endl;
}
private:
std::vector<std::shared_ptr<Foo>> fooVector;
};
int main()
{
Bar b;
b.addNewFoo(10);
b.addNewFoo(12);
b.addNewFooImproved(22);
b.printFoo(1);
b.printFoo(2);
b.printFoo(0);
}
I am making small simulation app, with base class named Entity and children classes named Herbivore and Carnivore. And since I am using SFML, I need to update them, deal with interactions etc, etc. My first idea was to store them in two different vectors, but that's not the most efficient solution, I guess.
Then I've tried using a little bit of polymorphism, but here is where I've utterly failed. I have one vector of pointers to the Entity objects. Here is its declaration:
std::vector<Entity*> entityVector;
While creating new objects, I call function from different class:
void ObjectFactory::createHerbivore(Sprite sprite, Vector2f position,
std::vector<Entity*> *vector)
{
Herbivore herbivore(sprite, position, m_GameResolution);
Entity* p_herbivore = &herbivore;
vector->push_back(p_herbivore);
}
Here is how I call that function in main Game class:
//Creating new herbivore objects
if (inputEvent.key.code == Keyboard::H)
{
srand((int)time(0) * dt.asMilliseconds() + 1 * 800 * entityVector.size() + 5);
herbivorePosition.x = rand() % (int)videoResolution.x;
herbivorePosition.y = rand() % (int)videoResolution.y;
factory.createHerbivore(herbivoreSprite, herbivorePosition, &entityVector);
(entityVector.back())->setDangerSprite(dangerSprite);
}
And then I proceed to work on that vector, or at least try to, but it crashes by the first try to read data saved under that pointer. Of course, through the painful and long process of debugging I've realised, that I create a new object here, pass its address and then destroy it by leaving this function. So my question is: how to deal with it, so I can keep all of this sweet polymorphism?
” I've realised, that I create a new object here, pass its address and then destroy it by leaving this function. So my question is: how to deal with it, so I can keep all of this sweet polymorphism?
You can have a vector of shared_ptr<Entity> and you can create a new dynamically allocated object with code like make_shared<Herbivore>(sprite, position, m_GameResolution).
The shared_ptr instead of a raw pointer like Entity* essentially takes care of cleanup. When there are no more shared_ptrs referring to that object, it's automatically destroyed and the memory deallocated. We say that it's owned by the collection of shared_ptrs referring to it.
The make_shared<Herbivore> instead of e.g. shared_ptr<Entity>{ new Herbivore{ sprite, position, m_GameResolution } } avoids some inefficiency (an extra dynamic allocation) of the latter, and can also help to avoid Undefined Behavior where you create two or more such objects as actual arguments in a function call.
Example:
#include <iostream>
#include <typeinfo> // for typeid
#include <memory>
#include <vector>
using namespace std;
struct Entity { virtual ~Entity(){} };
struct Herbivore: Entity {};
struct Carnivore: Entity {};
auto main() -> int
{
vector<shared_ptr<Entity>> entities;
entities.push_back( make_shared<Herbivore>() );
entities.push_back( make_shared<Herbivore>() );
entities.push_back( make_shared<Carnivore>() );
entities.push_back( make_shared<Herbivore>() );
for( auto p: entities )
{
cout << typeid( *p ).name() << endl;
}
}
People, I am new to all this programming talk. Up until now it was quite easy to find answers by googling them but right here I have big trouble expressing what I want to ask, let me try: Erasing a vector calls the destructor before freeing the memory, right? Now how does a struct-vector react, if it is destructed? One does not define a destructor for these things, but is it correct to assume that if a struct is "destructed" each of its members' destructors will be called as well?
Let me give you an example:
#include <string>
#include <vector>
struct ding_t {
std::string dang;
} foo;
strung boom_t {
vector <ding_t> chuck;
} bar;
int main () {
vector <boom_t> tom;
tom.resize(10);
tom[4].chuck.resize(5);
tom[4].chuck[3].dang = "jerry";
tom.erase();
return 0;
}
in this case, will the memory allocated by
tom[4].chuck.resize(5);
be freed as well? Sorry for my vocabulary, but at this moment I am trying to move from pointers to the more sophisticated cpp language equivalent of vectors. I hope I got my point across. Thanks in advance guys and please just redirect me if this has already been asked, as I've said, I don't know how to circumscribe this question.
Yes, the memory will be freed automatically.
When a vector is destructed it will call the destructor of all the elements it contains. You didn't define a destructor for your struct so the compiler will provide a default one for you (that does nothing).
However if your vector contains pointers to objects it will be your responsibility to call the destructor on the objects before destructing the vector (because the vector will call the destructor of the pointers, not the pointed objects), if you have no other way to access them later.
See http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.11 for the answer to your question and the entire article for a very good treatment of destructors in C++.
As to your second question: yes, the memory allocated by tom[4].chuck.resize(5); will get freed as well, since it is the vector's responsibility to manage its own memory allocations (which is the case for the "resize()" call.)
Answer: Since you are not allocating the Object dynamically with the new operator, you dont have to deallocate them manually.
It's done automatically for you.
Ok. Back to your code :)
If you want to erase the 6th element then use tom.erase (tom.begin()+5) .
And if you want to erase all elements then use tom.erase (tom.begin(),tom.end() ) .
To erase the first 3 elements use tom.erase (tom.begin(),tom.begin()+3).
#include <string>
#include <vector>
using namespace std;
struct ding_t
{
std::string dang;
} foo;
struct boom_t {
std::vector <ding_t> chuck;
} bar;
int main () {
vector <boom_t> tom;
tom.resize(10);
tom[4].chuck.resize(5);
tom[4].chuck[3].dang = "jerry";
//error C2661: 'erase' : no overloaded function takes 0 parameters
//tom.erase( );
// erase the 6th element
tom.erase (tom.begin()+5);
// erase the first 3 elements:
//tom.erase (tom.begin(),tom.begin()+3);
// erase everything:
//tom.erase (tom.begin(),tom.end() );
return 0;
}
Okay, I've done this little check, just to make sure. (Why didn't I think of this earlier... was quite late yesterday... ) The initial code was badly written and didn't work, apologies for that.
This:
#include <string>
#include <vector>
struct ding_t {
std::string dang;
} foo;
struct boom_t {
std::vector <ding_t> chuck;
} bar;
int main () {
std::vector <boom_t> tom;
while (true) {
tom.resize(10);
tom[4].chuck.resize(5);
tom[4].chuck[3].dang = "jerry";
tom.erase( tom.begin(), tom.end() );
}
return 0;
}
causes no memory leak, the used memory is stable.
Hey..
I'm having trouble with some homework.
We are working on VectorList ( kinda like linked list but with vectors - don't ask why.. )
Anyway I have something like this:
#ifndef VECTORLIST_H
#define VECTORLIST_H
#include <iostream>
#include <vector>
using namespace std;
template< typename NODETYPE >
class VectorList
{
public:
VectorList(); // constructor
~VectorList(); // destructor
void insertAtFront( const NODETYPE & );
void insertAtBack( const NODETYPE & );
bool removeFromFront( NODETYPE & );
bool removeFromBack( NODETYPE & );
bool isEmpty() const;
void print() const;
private:
vector< NODETYPE > *vList; // list data as a vector
};
I need to fill in the functions.. my problem is that I do not understand how
to use STIL when I have *vList.. its a pointer to the first vector element?
// display contents of VectorList
template< typename NODETYPE >
void VectorList< NODETYPE >::print() const
{
// Fill in the missing code
}
My Idea was to use a for loop on the vector and use cout<< vector[i]<< endl;
to print the vector out..
Problem is that I get all sorts of errors and seg faults.
I do not understand how to access the vector in the function,
and how to access its elements.
This is a header file, and in the main we declare an object of VectorList<NODETYPE> IntVector...
So how can I do this?
Any help with understanding of how this *vList plays a role here would help a lot and
I'd probably be able to finish the rest..
Also, for isEmpty(), I assume I can use vList.empty().. but since vList is a pointer..
it doesn't work quite well.
== For the constructor/destructor what can I do?
I know for destructor I should iterate through the vector and use delete on each element.
But shoul
Please explain this to me, I am frustrated =[
my problem is that I do not understand how to use STL when I
have *vList.. its a pointer to the first vector element?
I assume that you are required as part of your homework to use pointer-to-vector instead of a vector itself. As a rule, I never use pointers-to-containers. In fact, the best thing that I discovered in switching from C to C++ was that I could write entire programs with no pointers at all, thanks to STL programming. Unless you are required to use pointer-to-vector, I recommend that you use the vector directly.
Certainly it is easier to use the vector proper than a pointer, but don't worry. Using the pointer isn't too bad.
First, in order to use a pointer-to-something, one must allocate the something. So, in your constructor, invoke new.
vList = new std::vector<NODETYPE>;
Anytime we invoke new, we must have a matching delete somewhere. Since our new is in our constructor, we need to invoke delete in the destructor:
delete vList;
You said:
but since vList is a pointer.. it doesn't work quite well.
Here is where life gets easy. Generally, if p is a pointer to some type, then (*p) is the object to which p points. Here are some examples:
int i = 1;
int *pInt = &i;
i = 4;
(*pInt) = 4;
std::cout << i << " " << (*pInt) << "\n";
std::vector<NODETYPE> v;
std::vector<NODETYPE> *pVector;
v.push_back();
(*pVector).push_back();
it = v.begin();
it = (*pVector).end();
So, invoking members of vList is easy : (*vList).empty().
So, your code might be :
void insertAtFront(const NODETYPE& node) { (*vList).push_front(node); }
There is a short-cut operator -> that makes the above somewhat easier to read:
void insertAtFront(const NODETYPE& node) { vList->push_front(node); }
The expression x->y is more-or-less equivalent (*x).y.
To sum up:
Allocate your vList in your constructor with new. Destroy your vList in your destructor with delete. Invoke members of vList using either (*vList).function() or vList->function().
Good luck, and come back if you have other questions!
P.s. Since you have a non-trivial destructor, you'll need to consider the rule of three.
P.P.s. You said something about iterating the vector in your destructor and deleting each of the objetcs you find there. You would only need to do that if your data type were vector-of-pointers-to-NODETYPE (contrast to what you declared: pointer-to-vector-of-NODETYPE). Until and unless you become completely comfortable with pointers, I recommend that you never store pointers in STL containers.
You should construct your object in the constructor (if you really need using bare pointers): vList = new vector< NODETYPE >();, free memory in the destructor: delete vList;, translate your methods to corresponding methods of the container class. For example, insertAtBack would be implemented as vList->push_back(elem);
I am using an array in a simple logic simulator program and I want to switch to using a vector to learn it but the reference I am using "OOP in C++ by Lafore" doesn't have a lot about vectors and objects so I am kinda of lost .
Here is the previous code :
gate* G[1000];
G[0] = new ANDgate() ;
G[1] = new ORgate;
//gate is a class inherited by ANDgate and ORgate classes
class gate
{
.....
......
void Run()
{ //A virtual function
}
};
class ANDgate :public gate
{.....
.......
void Run()
{
//AND version of Run
}
};
class ORgate :public gate
{.....
.......
void Run()
{
//OR version of Run
}
};
//Running the simulator using overloading concept
for(...;...;..)
{
G[i]->Run() ; //will run perfectly the right Run for the right Gate type
}
Now what I want to do is
vector(gate*) G;
ANDgate a
G.push_back(a); //Error
ORgate o
G.push_back(o); //Error
for(...;...;...)
{
G[i]->Run(); //Will this work if I corrected the error ??
}
so can a vector array hold different types of objects(ANDgate , ORgate) but they inherit the type of the vector array (gate) ????
You're half-way there:
std::vector<gate*> G;
G.push_back(new ANDgate);
G.push_back(new ORgate);
for(unsigned i=0;i<G.size();++i)
{
G[i]->Run();
}
Of course, this way you need to take care to ensure that your objects are deleted. I'd use a vector of a smart pointer type such as boost::shared_ptr to manage that for you. You could just store the address of local objects (e.g. G.push_back(&a)), but then you need to ensure that the pointers are not referenced after the local objects have been destroyed.
Yes, that will work - as long as you make run() a virtual function in gate and use the address of operator(&) on a and o as you put them in the vector.
Be careful about object lifetime issues though. If a and/or o go out of scope then your vector will contain pointers to invalid objects.
Also, the base class "Gate" should have a virtual destructor else there would be issues while cleaning up the vector and it's contents.
You are using
vector(gate*) G;
change to
vector<gate*> G;
and you should do this
G.push_back(new ANDgate());
or if you use boost use shared_ptrs as vector does quite a lot of copying and naked pointers in a vector can be fatal.