Using an array in an Object - c++

I'm using user input to determine the size of my array.
This array will be used by another object.
Additionally, this will be looping so the user will potentially change the array size.
What's the best way to do this?
And since the array is used by an object, would it be better to pass the array in the constructor or pass the size and create the array in the class?
I was thinking some sort of a new delete array combination?
Am I off the mark here?

For generic, dynamic array-like needs, the best option is probably the std::vector class. Just create it where it is needed, I'd say into the class.

std::vector is a resizable array provided by the standard template library. To get it,
#include <vector>
There is plenty of material on the internet for how to use vectors, e.g. http://www.cplusplus.com/reference/stl/vector/ . Without further information, a good first start would be to use std::vector's inside of your container.

Related

How do I copy arrays that contain non primitive types?

I'm writing C++ on an Arduino. I've run into a problem trying to copy and array using memcpy.
Character characters[5] = {
Character("Bob", 40, 20),
Character("Joe", 30, 10),
...
};
I then pass this array into a constructor like so:
Scene scene = Scene(characters, sizeof(characters)/sizeof(Character));
Inside this constructor I attempt to copy the characters using memcpy:
memcpy(this->characters, characters, characters_sz);
This seems to lock up my application. Upon research it appears that memcpy is not the right tool for this job. If I comment that line out the rest of the application continues to freeze.
I can't use vectors because they're not supported on the Arduino, neither is std::copy. Debugging is a pain.
Is there any way to do this?
Edit
The reason why I am copying is because multiple objects will get their own copy of the characters. Each class can modify and destroy them accordingly because their copies. I don't want to have the Scene class responsible for creating the characters, so I'd rather pass them in.
You will have to copy the members individually, or create a copy constructor in the Character class / struct
It's very unclear what's going on in your code.
First of all, you aren't using std::array as your question title suggests, you are using a built-in array.
You could concievably use std::array instead, and just use copy constructor of std::array. But that brings us to second question.
When you are doing memcpy in the constructor of Scene, what is the actual size of this->characters? It's not a good thing to have a constructor that takes characters_sz dynamically if in fact there is a static limit on how many it can accept.
If I were you and really trying to avoid dynamic allocations and std::vector, I would use std::array for both things, the member of Scene and the temporary variable you are passing, and I would make the constructor a template, so that it can accept arbitrary sized std::array of characters. But, I would put a static assert so that if the size of the passed array is too large, it fails at compile time.
Also assuming you are in C++11 here.
I guess depending on your application, this strategy wouldn't be appropriate. It might be that the size of the arrays really needs to be variable at run-time, but you still don't want to make dynamic allocations. In that case you could have a look at boost::static_vector.
http://www.boost.org/doc/libs/1_62_0/doc/html/container/non_standard_containers.html
boost::static_vector will basically be like a heap-allocated buffer large enough to hold N objects, but it won't default construct N of them for sure, you may have only one or two etc. It will keep track of how many of them are actually alive, and basically act like a stack-allocated std::vector with a capacity limit of N.
Use std::copy_n:
std::copy_n(characters, num_characters, this->characters);
Note that the order of arguments is different from memcpy and the number is the number of elements, not the size of those elements. You'll also need #include <algorithm> in the top of your source file.
That said, you're probably better off using a std::vector rather than a fixed size array, That way you can just use a simple assignment to copy it, and you can grow and shrink it dynamically.

Array of objects with constructor

I have class named Novel. I can declare array of objects as mentioned below:
Novel obj;
but problem is Novel has constructor which I want to be called for all indexes of array how can I do that. I tried following but it does not work.
Novel obj(i,n)[2];
You need to use a proper container that uses dynamic allocation to defer construction of individual elements.
std::vector<Novel> objs(2, Novel(i,n));
http://en.cppreference.com/w/cpp/container/vector/vector
Unfortunately the C++ language does not provide that capability. Arrays are allocated, but by default they are not initialised at all. If they are allocated in static storage they get filled with zeros; you can give a brace-initialiser; and you can provide a default constructor to initialise each value. What you cannot do is initialise an array with any other constructor.
To achieve a similar effect you have to approach the problem from a different angle. Basically, you can:
- write a macro or template that both allocates an array and calls a constructor on each element under the covers, or
- create an object with array semantics, which can initialise itself any way you like.
The built in collection classes are usually the best solution. For example, std::vector provides fill, range and copy constructors as well as array semantics. One of the other answers provides an example, but there are several ways to do it.
std::vector<Novel> objs(2, Novel(i,n));
It's not an array, but it should do what you need.

Array of structures in C++

I am trying to define
Vertex[] total_vertices = new Vertex[no_vertice];
in C++. But when compiling I get this:
:568:8: error: expected unqualified-id before ‘[’ token
I need to declare an array of Vertices of size "no_vertice", and then use its "Length" method to get its size. Why is it not working?
In C++, the [] only goes after the variable name, not after the type (unlike Java or C#).
But that wouldn't work anyway, because you can't assign a pointer-to-first-element-of-an-array (returned by new) to an array. You need to use a pointer:
Vertex* total_vertices = new Vertex[no_vertice];
And make sure to delete[] it after you're done using it.
You say you need to use it's Length method, which has two problems:
Arrays don't have methods like they do in java; they're just blocks of memory in C++. If you want to use an array-like structure that has member functions, check out std::vector
You wouldn't need the Length method of an array even if they did have one (which they don't) because you already have the size in the variable no_vertice.
C++ arrays don't have length methods. You need to look at std::vector.
The right way to do it is.
Vertex *total_vertices = new Vertex[no_vertice];
However, in C++ builtin arrays have no Length method. They have no method at all since they are not classes. The "length" of it would be no_vertice.
You seem to be talking Java or C#...
You want
std::vector<Vertex> total_vertices(no_vertice);
and then use its size() method to get the size.
It's best to avoid using new directly unless there's no alternative - it's very easy to lose track of the object's ownership and end up with a memory leak.
You should probably do something like
boost::shared_array total_vertices( new Vertex[no_vertices] );
or
boost::scoped_array total_vertices( new Vertex[no_vertices] );
that way you don't have to worry about cleaning up after yourself and leaking memory.
http://www.boost.org
In C++, always use a vector rather than an array if a vector can do what you want. Because a vector provides an easy way and some useful methods (such as the size() you want). The most important thing is that a vector is safer than an array when you subscribe an element in it (vector has a end() method to make sure you can't access out of the range of it). So I think you should write this:
#include <vector>
std::vector<Vertex> total_vertices(no_vertice); //vector is a container so you should declare it with a specified type.
You can get more information about vector in the C++ reference of vector.

How to make a global array with variable number of elements?

Is it posible to declare a global array of a struct, and add elements dynamically to it?
Thanks.
If you want to dynamically add elements to something, you might consider using a list. You could create a global list, and dynamically add elements to it as needed. If you really need array type functionality, a vector might be more your speed. In this case, the STL is likely to provide what you need.
It's also good to note that globals aren't always a good idea. If you're using globals a lot, you may want to consider refactoring your code so they won't be necessary. Many people consider global variables to be a code smell.
Avoid using non-PODs as globals. However, you can do this:
std::vector<YourStruct>& global_list()
{
static std::vector<YourStruct> v;
return v;
}
This at least avoids global initialization order problems by enforcing a policy where access is initialization. Otherwise you'll very easily wander into undefined behavior land.
As for what variable-sized container to use, it's hard to tell without more contextual information. Do you need to be able to quickly search for elements in the list, for example? Will you be removing elements from the middle of the list frequently? Do you need random-access, or is sequential iteration fine? Etc. etc.
See std::vector.
Any time you're tempted to use an array, you'd probably do better to use a vector, list, or one of the many other STL containers.
No, not directly. But you may use a STL or self-made vector.
You can use a STL container. Alternatively you can declare of your type and allocate/deallocate memory by yourself. But you should not use the 2nd way.

Avoid making copies with vectors of vectors

I want to be able to have a vector of vectors of some type such as:
vector<vector<MyStruct> > vecOfVec;
I then create a vector of MyStruct, and populate it.
vector<MyStruct> someStructs;
// Populate it with data
Then finally add someStructs to vecOfVec;
vecOfVec.push_back(someStructs);
What I want to do is avoid having the copy constructor calls when pushing the vector. I know this can be accomplished by using a vector of pointers, but I'd like to avoid that if possible.
One strategy I've thought of seems to work, but I don't know if I'm over-engineering this problem.
// Push back an empty vector
vecOfVec.push_back(vector<MyStruct>());
// Swap the empty with the filled vector (constant time)
vecOfVec.back().swap(someStructs);
This seems like it would add my vector without having to do any copies, but this seems like something a compiler would already be doing during optimization.
Do you think this is a good strategy?
Edit: Simplified my swap statement due to some suggestions.
The swap trick is as good as it gets with C++03. In C++0x, you'll be able to use the vector's move constructor via std::move to achieve the same thing in a more obvious way.
Another option is to not create a separate vector<MyStruct>, but instead have the code that creates it accept it a a vector<MyStruct>& argument, and operate on it. Then, you add a new empty element to your outer vector<vector<MyStruct>>, and pass a reference to the code that will fill it.
I know this can be accomplished by
using a vector of pointers, but I'd
like to avoid that if possible.
Why?
That would be the most intuitive/readable/maintainable solution and would be much better than any weird hacks anyone comes up with (such as the swap you show).
Tim,
There's a common pattern to solve this. This is called smart pointers, and the best one to use is boost::shared_ptr.
Then, never pass vector by value or store it. Instead, store boost::shared_ptr >. You don't need to care about allocations/deallocations (when the containing vector is destroyed, so will be the others, just as in your code), and you can access the inner members almost the same way. The copy is, however, avoided by means of the smart pointer object's reference counting mechanism.
Let me show you how.
using boost::shared_ptr;
vector<shared_ptr<vector<MyStruct> > vecOfVecs;
shared_ptr<vector<MyStruct> > someStructs(new vector<MyStruct>);
// fill in the vector MyStructs
MyStructs->push_back(some struct.... as you usually do).
//...
vecOfVecs.push_back(someStructs); // Look! No copy!
If you do not already use boost::shared_ptr, I recommend downloading it from boost.org rather than implementing your own. It is really irreplaceable tool, soon to be in the C++ standard library.
You can either do something like vect.push_back(vector<MyStruct>()); and do vect.back().push_back(MyStruct()); or use smart pointers and have a vector of smart pointers to vector<MyStruct>
I think the swap idea is already fine, but can be written much easier:
vecOfVec.push_back(vector<MyStruct>());
vecOfVec.back().swap(someStructs);