Reputation: 211
I have this:
std::vector <BinaryTree*> children;
where BinaryTree
is a class. How can I add an element into this vector?
I tried children.push_back(X)
where X
is an instance of the class but it gives me this error:
cannot convert parameter 1 from 'BinaryTree' to 'BinaryTree *&&'
Upvotes: 4
Views: 23457
Reputation: 42083
You have vector of pointers:
std::vector <BinaryTree*> children;
so the proper way of adding elements is:
BinaryTree* child = new BinaryTree();
children.push_back(child);
just be careful while doing something like this:
{
BinaryTree child;
children.push_back(&child);
}
because lifetime of such an element might be shorter than lifetime of the vector and you might end up trying to access an element that no longer exists (dangling pointer) which produces undefined behavior. Also don't forget to delete
these elements when done with it.
But it's always good to consider using vector of objects first (i.e.std::vector<BinaryTree>
) since that would take care of that ugly memory management for you.
Upvotes: 0
Reputation: 126412
Just use the push_back()
and pass a pointer to an instance of BinaryTree
:
std::vector <BinaryTree*> children;
BinaryTree* pTree = new BinaryTree();
children.push_back(pTree);
...
delete pTree;
In order to avoid manual memory management, if you need reference semantics, use smart pointers instead of raw pointers:
#include <memory> // For std::shared_ptr
std::vector <std::shared_ptr<BinaryTree>> children;
std::shared_ptr<BinaryTree> pTree = std::make_shared<BinaryTree>();
children.push_back(pTree);
...
// No need to delete pTree
The std::shared_ptr<>
class template is part of the C++11 Standard Library. In C++03, you could use the (almost) equivalent boost::shared_ptr<>
:
#include <boost/shared_ptr.hpp> // For std::shared_ptr
std::vector <boost::shared_ptr<BinaryTree>> children;
boost::shared_ptr<BinaryTree> pTree = boost::make_shared<BinaryTree>();
children.push_back(pTree);
...
// No need to delete pTree
Finally, if you do not need reference semantics at all and want to treat your binary trees as values instead, you can even consider defining a std::vector<BinaryTree>
:
std::vector<BinaryTree> children;
BinaryTree tree;
children.push_back(tree);
Upvotes: 11
Reputation: 227370
It really depends on who is supposed to own the pointers. In the simplest case, where the vector doesn't own them, then you pass the address of a BinaryTree
object.
BinaryTree b = ...;
children.push_back(&b);
But you have to be sure b
lives at least as long as children
does.
If the vector owns the pointers, then you should probably store smart pointers to avoid having to deal with memory managemen:
std::vector<std::unique_ptr<BinaryTree>> children;
children.push_back(std::unique_ptr<BinaryTree>(new BinaryTree(args)));
If you don't know what all this "ownership" business means, then you are most likely better off with a plain vector of objects:
std::vector<BinaryTree> children;
Upvotes: 3
Reputation: 109089
The vector
contains pointers to objects of type BinaryTree
. You need
BinaryTree bt;
children.push_back( &bt );
But you must ensure that the lifetime of the bt
object at least matches that of the vector
.
You may want this instead
children.push_back( new BinaryTree );
But in this case you must call delete
on the pointer contained in the vector
to prevent a memory leak.
As evident, neither option is easy to manage. An easy change is to make your container store the elements by value.
std::vector<BinaryTree> children;
BinaryTree bt;
children.push_back( bt );
If you must store pointers, use a smart pointer to hold them instead.
std::vector<std::unique_ptr<BinaryTree>> children;
children.push_back( new BinaryTree );
Now you don't need to worry about deleting the objects before emptying the vector.
Upvotes: 0
Reputation: 26022
Omit the asterisk *
from the template argument:
std::vector<BinaryTree> children;
You want children to hold the data, without manual/dynamic memory allocation as in new BinaryTree
.
Upvotes: 3
Reputation: 151
children.push_back(&X);
Pass the address as if you were using it as a pointer. But the problem then is if that instance goes out of scope, so better to do this
BinaryTree* X = new BinaryTree;
children.push_back(X);
This will ensure that X never goes out of scope, but then you have to manually delete it when you're finished with it.
Upvotes: 0
Reputation: 672
children.push_back(&X);
This will work but bear in mind that once your object leaves scope, its deleter will be called and you will be left with an invalid pointer.
Upvotes: 0
Reputation: 4888
std::vector<SomeObject*> objectVector;
objectVector.push_back(new SomeObject());
Is how I do it.
Upvotes: 1