vector of sequences - c++

I have this data structure Seq which inherits the class vector but has some extra functionalities.
Using this data structure Seq I have this predefined data structure:
typedef Seq< vector<int> > MxInt2d;
I want now to have a vector of several components of type MxInt2d;
I was thinking about something like:
MxInt2d* loops;
it is just that I think I have to initialize this vector and I do not have a constructor for it. should I write a constructor in order to initialize it ?
So if on one hand I would have the declaration of the following data structure:
MxInt2d myEdges_;
which is then initialized.
And on the other hand the declaration of my variable loops:
vector<MxInt2d> loops;
If I want to copy in loops[0] the first 5 elements of myEdges_, I would use the syntax:
for (int i=0;i<5;i++)
loops[0].push_back(myEdges_[i]);
The program gets compiled but when I run it I obtain a bus error message..
The same stuff happens if I use the initialization for a second loop:
for (int i=0;i<5;i++){
loops[1].push_back(myEdges_[i]);
}
(sorry for my bad judgement, I am really new with vector)
madalina

Before getting into your problem-- an observation:
Are you inheriting the vector ? Deriving vector is not a good idea. All the the standard STL containers, lacks a virtual destructor, and publicly inheriting from classes without virtual destructors is a major C++ no-no.

Don't use pointers, unless you have to. Use vector again:
vector<MxInt2d> loops;
Right now, the loops container is empty (i.e. there are no matrices inside). If you want it to contain 2 MxInt2d object, you'll either have to insert them or initialize loops differently:
// loops will contain two empty MxInt2d objects
vector<MxInt2d> loops(2);
// after the following command,
// loops will contain 3 MxInt3d objects
loops.push_back(MxInt2d());
Only after you've populated loops you can start populating its elements.

It's not a good idea to inherit from STL containers because they don't have virtual destructors, which can lead to underfined behaviour, if you try to delete a derived pointer through a base pointer (hope I got that right).

As it is, your data structure looks complex. By creating a pointer of it, you are making it even more complicated. It's better if you can create an array/vector of MxInt2d instead of making it a pointer.

No, not necessarily. std::vector will initialize all elements to 0, so if this is what you need, you won't have to write a custom constructor.

Arrays are evil in C++. You can use vector for almost anything that you can use array for. One common problem; that of initialization can be solved. Refer to this discussion how-to-initialize std::vector like 'C' array.
So, you can use 'vector loops;' without problems.
HTH,

You have a couple of problems here.
One, you should not derive from vector. If you need code that does custom stuff with a vector, you should write a class with your custom stuff that has-a vector, not is-a vector. For example:
class Seq
{
public:
// assorted constructors
// construct vec_ with zero elements
Seq() {};
// construct vec_ with one element
Seq(int singleItemToAdd)
: vec_(1, singleItemToAdd) {};
// construct vec_ with 'multipleItemsToAdd' elements
Seq(const int* multipleItemsToAdd, size_t numItemsToAdd)
: vec_(multipleItemsToAdd,multipleItemsToAdd+numItemsToAdd) {};
// assorted custom operations (instead of deriving from vector)
void customSeqOperation() const
{
/// your custom stuff here
: :
}
private:
vector<int> vec_;
};
Next problem, you are saying this code compiles but crashes at runtime:
vector<MxInt2d> loops;
for (int i=0;i<5;i++)
loops[0].push_back(myEdges_[i]);
If this is your essentially compete code, the reason why it crashes is because there is no element at loops[0] -- you haven't added it yet. You need to add an element to loops (which is a vector) before you can access the first one:
vector<MxInt2d> loops;
MxInt2d firstElement = getTheElement();
loops.push_back(firstElement);
for (int i=0;i<5;i++)
loops[0].push_back(myEdges_[i]);

Related

How C++ call parameterized ctor to create object arrays?

I know in c++11 I can use initializer to create array/vector elements one by one like:
int ar[10]={1,2,3,4,5,6};
vector<int> vi = {1,2,3,4};
This is done manually, but what if I wish to initialize an array/vector with 10000 elements and specify their value, can it be done in one statement, RAII pattern?
E.g. I've defined a class:
class Somebody{
int age;
string name;
public:
Somebody():age(20),name("dummy"){} // default ctor
Somebody(int a, const char* n):age(a),name(n){} // but I wish to call this ctor
Somebody& operator = (const Somebody& s) {...}
};
Then in main function:
int main(int argc, char const *argv[])
{
Somebody obj(2, "John"); // parameterized ctor
Somebody ar[300]; // initialized, but called default ctor
for(int i=0;i<300;++i){ // initialize again in a loop
ar[i] = ... ; // call operator =
...
Question: could Somebody ar[300] be constructed with parameterized ctor?
If not, then I have to create this object array ar first(Compiler generated code will loop and call default parameter), then apply value changes for each object. This seems quite a bit redundant of cpu cycles.
Is there a way to do what I expected with just one call? (Loop and update each array element with parameterized ctor)
Thanks.
You can not do this with C-style arrays. One of the many reasons you should not be using them in the first place.
You should be using std::vector, which provides a constructor to populate the vector using a single value:
std::vector<Somebody> ar{300, Somebody("42", "filler")};
But often it is better to not create such dummy entries in the first place. A std::vector can grow dynamically so you can just add Somebody objects to it as you get their age and name.
std::vector people;
people.reserve(2); // optional but makes adding lots of objects more efficient
Somebody adam(42, "Adam");
people.push_back(adam);
people.emplace_back(23, "Eve");
This shows you 2 ways to add objects to the vector, the push_back adds objects to the vector (copies/moves it) while emplace_back will construct the object directly in the vector, which is often more efficient.
If you want a fixed size array then you can use
std::array<Somebody, 300> ar;
ar.fill(Somebody(23, "filler"));
But this has the same problem as the C-style array of using the default construtor. std::arrays::fill replaces all the objects with a new value.
Unfortunately there is no array constructor to do this in one go which is rather unfortunate.
Well, with simple arrays there's always the direct approach:
Somebody ar[300]={ {1, "Larry"}, {2, "Moe"}, {3, "Curly"} ... };
You'd have to write out whatever you want to write out 297 more times. This gets real old, real quickly.
One could potentially concoct, in a pinch, something that involves a variadic template to generate the whole bunch of them. Something like that is the classical approach to generating a fast 256-value array lookup for a textbook-style base64 decoder.
But for the simplistic case where you only want the same value, just #n copies of it, the simplest solution is to use a std::vector instead of a plain array and use one of its contructors that takes a single object and the vector size, and then constructs the vector by copying the object the requisite number of times. That involves slightly more overhead but is generally good enough, for this simple use case.
You can use std::fill_n:
Somebody obj(2, "John");
Somebody ar[300];
fill_n(ar, 300, obj);

push_back() changes size of other vector in function

I'm making a class which has a function that concatenates two vectors of unique_ptrs. When I use the push_back function, the size of the parameter vector changes, and I don't know why.
class A: public vector<unique_ptr<int>>{
public:
A& concatenate(A& c);
};
A& A::concatenate(A& c) {
for(int i = 0; i < c.size(); i++) { //this loop never stops
push_back(make_unique<int>()); //this line changes the size of c?
(*this)[(*this).size() - 1] = move(c[i]);
}
return *this;
}
The for loop doesn't stop running because every time the push_back method is used, the size of c is also incremented by 1.
I also thought to use resize() before the for loop, and then move all the pointers, but I want to know why the push_back method changes another vector.
That might happen when this A and the c A objects are same, i.e. you are trying to call concatenate on an object and passing the same object as param to concatenate.
So actually push_back is not changing size of another vector. Its the same vector you are working on.
On a sidenote, there are few issues with your code and post
As #PaulMcKenzie said, you should post an MCVE
In general, its not a good idea to derive from STL containers
Unless you are trying to learn how to implement, you should first try to find and use methods provided by STL containers. e.g. insert as suggested by
#Some programmer dude.

C++ std::vector in constructor

I am trying to code an effective implementation of the following composite class:
class composite{
vector<base_class *> Vec;
//Other useful constants
public:
composite(vector<base_class*>);
//Other useful operations...
};
My question is about the constructor and instantiation of the class and in particular the object Vec. At the minute, I use the rather crude implementation outlined below. I the implementation to be memory efficient. I'm pretty much a newb with C++, so I'm not sure I have the optimal solution here...
I use polymorphism to store different derived classes in a vector, e.g.
vector<base_class *> Vec1;
Vec1.reserve(2);
class1 * C1 = new class1(....);
Vec1.push_back(C1);
class2 * C2 = new class(....);
Vec1.push_back(C2);
where class1 and class2 are derived classes of base_class. I then pass Vec1 to the constructor of composite as follows:
composite::composite(vector<base_class*> Vec1){
Vec.reserve(Vec1.size());
Vec.swap(Vec1);
//etc...
}
My feeling is that this is quite efficient on the memory, because Vec1 will be empty after the construction (it's elements have been swapped into Vec). On the other hand, it seems to be quite wasteful, as I am essentially copying the Vec1 into Vec. Is there a better way for me to do this? Can I somehow embed the vector Vec1 into composite? Thanks in advance!
First, use proper smart pointer instead of raw pointer.
Next - in the method you used, the reserve() call is totally unnecessary - swap() just swaps internal pointers.
And last - since we're in 2013, C++11 is already to be used, so the constructor should look like this:
composite::composite(std::vector<std::unique_ptr<base_class>> v)
: vec{ std::move(v) }
{
}
Why this way? Taking the parameter by value already copies it, and since you aren't going to use that copy anymore, it is safe to be moved out, which achieves the least amount of copies to initialize the member.
If you really care about whether a copy of any vector will be made or not, you should first pass the constructors argument by reference. So the "usual" implementation would look like this:
composite::composite( const vector<base_class*>& Vec1 )
: Vec( Vec1 )
{
}
This will omit already one copy. I wouldn't bother about this until you have some signs that this will cause any problem. You already did three dynamic memory allocations before, why do you care about a fourth?

need a std::vector with O(1) erase

I was surprised to find out the vector::erase move elements on calling erase . I thought it would swap the last element with the "to-be-deleted" element and reduce the size by one. My first reaction was : "let's extend std::vector and over-ride erase()" . But I found in many threads like " Is there any real risk to deriving from the C++ STL containers? ", that it can cause memory leaks. But, I am not adding any new data member to vector. So there is no additional memory to be freed. Is there still a risk?
Some suggest that we should prefer composition over inheritance. I can't make sense of this advice in this context. Why should I waste my time in the "mechanical" task of wrapping every function of the otherwise wonderful std::vector class.? Inheritance indeed makes the most sense for this task - or am I missing something?
Why not just write a standalone function that does what you want:
template<typename T>
void fast_erase(std::vector<T>& v, size_t i)
{
v[i] = std::move(v.back());
v.pop_back();
}
All credit to Seth Carnegie though. I originally used "std::swap".
Delicate issue. The first guideline you're breaking is: "Inheritance is not for code reuse". The second is: "Don't inherit from standard library containers".
But: If you can guarantee, that nobody will ever use your unordered_vector<T> as a vector<T> you're good. However, if somebody does, the results may be undefined and/or horrible, regardless of how many members you have (it may seem to work perfectly but nevertheless be undefined behaviour!).
You could use private inheritance, but that would not free you from writing wrappers or pulling member functions in with lots of using statements, which would almost be as much code as composition (a bit less, though).
Edit: What I mean with using statements is this:
class Base {
public:
void dosmth();
};
class Derived : private Base {
public:
using Base::dosmth;
};
class Composed {
private:
Base base;
public:
void dosmth() {return base.dosmth(); }
};
You could do this with all member functions of std::vector. As you can see Derived is significantly less code than Composed.
The risk of inheritance is in the following example:
std::vector<something> *v = new better_vector<something>();
delete v;
That would cause problems because you deleted a pointer to a base class with no virtual destructor.
However if you always delete a pointer to your class like:
better_vector<something> *v = new better_vector<something>();
delete v;
Or don't allocate it on the heap there is no danger. just don't forget to call the parent destructor in your destructor.
I thought it would swap the last element with the "to-be-deleted"
element and reduce the size by one.
vector::erase maintains order of elements while moving last element to erased element and reduce the size by one does not. Since vector implements array, there is no O(1) way to maintain order of elements and to erase at the same time (unless you remove the last element).
If maintaining order of elements is not important than your solution is fine, otherwise, you better use other containers (for example list, which implements doubly-linked list).

Accessing members in a vector of objects as vectors

I have a c++ class that is contained as a vector of objects in another class.
class Small
{
public:
int a;
int b;
int c;
};
class Big
{
public:
vector< Small > getSmallVec() const { return m_smallVec;}
private:
vector< Small > m_smallVec;
};
I'd like to be able to access the members of the Small class as a vector themselves. In other words, I'd like to have a function in Big like
vector<int> getSmallVec_a()
which would return a vector that contains each value of int Small::a in m_smallVec. The only way I can think of doing it would be to iterate over m_smallVec and copy to a vector of int. Is there a way to do this without copying?
If this is how you expect to access data and performance is important, have you considered using parallel vectors? Instead of
std::vector<Small>
In "Big" you actually maintain 3 vectors
std::vector<int> aVec;
std::vector<int> bVec;
std::vector<int> cVec;
All elements at 0 correspond to the 0'th "Small", and you can easily seperate out all the as from the bs.
This comes a lot of annoying bookkeeping that you'd be have to be sure to get right and encapsulate well. Its not a more elegant solution, I usually dislike this kind of thing and would probably question in a code review, but it would probably give you the best performance for the operations you've described.
there is no way to do that without seperating small components in diffrent vectors since a vector is just working as an array that means when you are creating a vector of smalls there will be 2 blocks space between small::a variables whereas what you what to return is just an array of ints. and by the way it's much more efficient if you delcere you function as vector <int> & getSmall() since if you don't return a refrence it'll cause a copying m_smallVec and returning it as the result, it also makes it impossible to change any value in m_smallVec.