I'm currently trying to program an array of objects in a c++ program. However it keeps giving me errors when trying to create the arrays.
So on top of my code I have the following code:
#define sensNumber 4
ros::Publisher pub_range2 [sensNumber];
this gives the error:
multisone2.ino:19:38: error: no matching function for call to βros::Publisher::Publisher()β
So it's trying to call the constructor for Publisher, why? And how do I stop it?
Now I know this can also be done with Vectors but I'm trying to optimize the code esp. for reading speed so I would rather avoid vectors(yes I know that it remains linair but accessing this array represents a significant portion of my code).
As you're trying to stack-allocate sensNumber instances of ros::Publisher, the default constructor must be called.
An alternative would be to allocate an array of pointers to ros::Publisher. Better still, an array of std::unique_ptr or std::shared_ptr.
When you declare an array of c++ objects you're actually instantiating each element. This means that the default parameterless constructor is called for each array element. If you don't want to instantiate all elements when declaring your array, you should declare an array of pointers instead and then initialize each element whenever required.
Related
The dynamically created array of objects need to use a non-default constructor, and the problem I'm running into I think is the syntax. In my mind, the fact that I'm able to do this
int * somePtr = new int[5];
means that I should be able to do this
IntegerSet* someSet = new IntegerSet(this->getLength())[5];
where IntegerSet is a class I have made that represents an integer set. this code is happening inside one of IntegerSets member function. When I try this I get a syntax error
"cannot convert from IntegerSet to IntegerSet*"
I understand what this means, the two types aren't equivalent, but I can't see the difference between doing what I did in part 1 and part 2, besides the fact that part 2 has to have an argument list passed as the constructor. So it is in that part of the code that I suspect I have the syntax wrong
new expression allows only default initialization, you can not do this within single new expression. What you could do is allocate raw memory and construct objects one by one using placement new (see this answer in Object array initialization without default constructor)
Or yet even better, don't use C-style arrays. Instead, use some STL container such as std::vector and it's constructor, where the 2nd argument is a value that will be used to initialize elements:
std::vector<IntegerSet> integers(5, IntegerSet(this->getLength()) );
There is an easy way out of this problem: add a default constructor to IntegerSet that does not acquire memory and any other resources. This way you can allocate an array of IntegerSet with new and then fill each element of the array on the next step.
Even better solution: use std::vector<IntegerSet> and emplace_back() to initialize each element of the array using a non-default constructor.
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.
The dynamically created array of objects need to use a non-default constructor, and the problem I'm running into I think is the syntax. In my mind, the fact that I'm able to do this
int * somePtr = new int[5];
means that I should be able to do this
IntegerSet* someSet = new IntegerSet(this->getLength())[5];
where IntegerSet is a class I have made that represents an integer set. this code is happening inside one of IntegerSets member function. When I try this I get a syntax error
"cannot convert from IntegerSet to IntegerSet*"
I understand what this means, the two types aren't equivalent, but I can't see the difference between doing what I did in part 1 and part 2, besides the fact that part 2 has to have an argument list passed as the constructor. So it is in that part of the code that I suspect I have the syntax wrong
new expression allows only default initialization, you can not do this within single new expression. What you could do is allocate raw memory and construct objects one by one using placement new (see this answer in Object array initialization without default constructor)
Or yet even better, don't use C-style arrays. Instead, use some STL container such as std::vector and it's constructor, where the 2nd argument is a value that will be used to initialize elements:
std::vector<IntegerSet> integers(5, IntegerSet(this->getLength()) );
There is an easy way out of this problem: add a default constructor to IntegerSet that does not acquire memory and any other resources. This way you can allocate an array of IntegerSet with new and then fill each element of the array on the next step.
Even better solution: use std::vector<IntegerSet> and emplace_back() to initialize each element of the array using a non-default constructor.
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.
I have a struct defined as
struct Point {
int x, int y
}
I am getting an array of Points passed into a function, as well as an integer i that tells me how many elements the array contains. How in the world can I just add an element into the array? I realize there is no method to just add new elements, as arrays can't be dynamically resized, so I need to create a new one and copy each element over...but when I try to do the following:
Point newPoints[i+1];
I am told that it expects a constant value, which of course I can't give it since I need i+1, and i is variable. C++ makes me sad. (If it isn't obvious, I come from a land where some divine being manages all your objects for you...)
P.S. I must use arrays...forgot to mention that.
In standard C++, you cannot create an array with a run-time-set size. You will need to do one of:
Declare newPoints as a pointer and then allocate the value using new Point[i+1], applying delete [] to it later.
Declare newPoints using something like boost::scoped_array, which manages cleanup automatically.
Use a non-array, such as an std::vector; you can use &v[0] to get a pointer from that.
Use a non-standard extension, such as the one provided by GCC.
Afraid you're going to have to use a new/malloc on this one. i is only determined at runtime, so there's no way it can statically allocate the memory it needs on the stack at compile time.
The reason you must use a constant value is that the newPoints array is being created on the stack, and to do that the compiler must know how big it is going to be at compile time. To be able to specify a dynamic size you must use either new[] and delete[], or a dynamic data structure class (like from the STL).