Make Boost Matrix attribute of a class - c++

I want to make a Boost Matrix as an attribute of my class Adsorbate. I know beforehand that it will be (3,2). I want to do:
#include <boost/numeric/ublas/matrix.hpp>
using namespace boost::numeric::ublas;
class Adsorbate {
matrix<double> m(3,2);
};
so that the compiler knows the size of the attribute m and thus my class Adsorbate. This way, I can make a pointer array of 200 of them:
Adsorbate * adsorbates = (Adsorbate *) malloc(200 * sizeof(Adsorbate));
How can I do this?

With regards to how to create an array of matrices, you are asking how to create a C array for a C++ data structure. Calling malloc will not correctly initialize the matrices in the array, nor calling "free" will deallocate dynamic memory if instances of ublas::matrix uses it, both failure to initialize an instance and failure to destroy it are severe bugs because things might seem to work, depending on the contents of the raw memory it can be all zeroes or something the application can handle, but it can also be be garbage that lead to catastrophic failures. Malloc will only give back the memory for instances, but internally, an instance of Adsorbate which has an instance of ublas::matrix might think it has valid pointers to memory or whatever.
To properly initialize the individual members of the array, Adsorbate *adsorbates = new Adsorbate[200];
Will use the default constructor for all the Adsorbate instances.
You can make it so that the default constructor of Adsorbate constructs its member m with 3,2:
struct Adsorbate {
Adsorbate(): m{3, 2}, ... orther instance initializations here ... { ...arbitrary constructor code here.... }
...
}
Arrays are not advised. The advised way is to create an std::vector<Adsorbate>. It might seem more complicated to use std::vector but it isn't, it will keep you from doing apparently simpler things that are potentially catastrophic unbeknownst to you.
If you insist on using naked arrays make sure to delete[] an array instead of delete. The difference is that delete calls only the destructor of one element.

Just initialize it in the constructor:
class Adsorbate {
private:
matrix<double> m;
public:
Adsorbate() : m(3, 2) {}
// ...
};
Also if you want to create an array of 200 Adsorbate, use std::vector:
std::vector<Adsorbate> adsorbates(200);

Related

Declaring struct members that are initialised later (C++)

I need to have a variable that is declared in a struct to be initialised with a value later. It's basically because its initialisation depends on another member of the structure, which only has a value after some functions have been done.
This sounds a bit weird, so I'll show my code:
struct frame
{
Mat thresholded;
vector<vector<Point> > contrs;
vector<Moments> momts;
};
frame obj_detect(frame img)
{
// Get contours from image
findContours(img.thresholded, img.contrs, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
// Initialise moments vector big enough for all contours' moments
img.moments(img.contrs.size());
...
return img;
}
int main()
{
frame frame1;
frame1 = obj_detect(frame1);
...
}
Currently this code throws this error:
error: no match for call to ‘(std::vector<cv::Moments>) (std::vector<std::vector<cv::Point_<int> > >::size_type)’
How should I initialise the moments vector array so that it has enough space for all the contours?
There's nothing wrong or weird about what you're trying to do. This is an example of an initializer function (or what would be called a constructor for a class).
What isn't entirely clear is whether struct1 is meant to be the struct you are initializing or if it is an input that you are using to return a new struct (since your function does define its return type as my_struct as well). In either case, it is generally recommended to pass your structs by reference rather than by value or as return values.
You could try something like this:
void my_function(const my_struct& input_struct, my_struct& output_struct)
{
...
output_struct.size = ...;
output_struct.my_array = new char[output_struct.size];
...
}
Of course, if you really are using C++, you should question why you are using a struct to represent what seems to be a string?
Once you've allocated memory this way, it is important that you free the memory as well in order to avoid memory leaks. A single object can be deallocated using delete, but an array should be deallocated using delete [], for example:
delete [] some_struct.my_array;
Additionally, it is considered good practice to set pointers to null after deallocating them to avoid referencing stale memory segments. This can be done like this:
some_struct.my_array = nullptr;
Finally, this all gets a bit tedious to manage, particularly if the lifetime and ownership of the object is more complex. To deal with this, the standard library has unique_ptr and shared_ptr objects that will automatically deallocate an object when it is no longer being used.
I don't think it makes sense to go into detail about the differences and uses of each since there are innumerable resources here and elsewhere on the topic.
Seems to me this is very simple question
my_struct my_function(my_struct struct1)
{
...
struct1.my_array = malloc(struct1.size); // Initialise the array
...
}
You have to use malloc()
char* struct1.my_array = new char[struct1.size];
Edited:
Actually you can use malloc or new. In this case - doesn't matter. If you prefer malloc you have to free memory with free(), otherwise you have to use new/delete. Usually new/delete is good to be used while creating objects, when you are dealing with structs and primitive type stick to malloc.
New/Delete operator are usually invokes constructors/destructors and they are a little bit slower than malloc/free. So why you have to pay (even a little) performance cost for nothing?

C++ : Allocation of an array attribute in a class

I would like to know, if I have a class with an array attribute whose size is not the same for all instances :
class myObject{
private:
int size;
int* array;
// other methods/attributes
};
Is it obligatory allocated using new ?
explicit myObject(int size = 0):size(size){
array = new int[size];
}
Even if in the main(), I always use constant parameters to create the instances of the class ? (Meaning I know every array size at compile time).
int main{
myObject object (5);
return 0;
}
Apparently something like :
private:
int size;
int array[size];
wont work, no ?
That means that array attribute whose size are not constant of the class are obligatory on the heap ?
Thank you for your answers,
That class contains no array. What you called array is a pointer; you cannot store any ints in it. If you really do just store a pointer, you'll have to allocate the memory yourself somehow; it can't magically appear. You'll also have to deallocate it yourself, and make sure that copying and assigning myObject objects doesn't cause any issues.
However, it's unlikely that a pointer is really the best way to do things. The standard library provides the std::vector class template which lets you use almost exactly the syntax you want:
class myObject {
std::vector<int> vector;
public:
myObject() {};
explicit myObject(std::size_t n) : vector(n) {}
};
With this in place you can create myObjects and they'll have the right amount of storage ready for them. It'll likely be dynamically allocated using operator new[], just like if you'd do it manually, but you don't have to worry about copying or deleting it.
int main() {
myObject a; // default-constructed, vector is empty.
myObject b(10); // std::size_t constructor, vector has 10 elements.
} // scope exit, b and a destroyed.
You can use the vector member much like if it was an array; the only thing it does not support is implicit decay to pointer, but the data member function makes up for even that.
As an alternative, if you always know the size at compile-time you can change the class into a class template and make the size a template parameter:
template<std::size_t N>
class myObject{
std::array<int, N> array;
// other methods/attributes
};
However, note that you now cannot use myObject<10> to a function expecting myObject<20>.
It is unlikely that you want more control than the above possibilities provide -- std::vector can be given an allocator, so it can do almost all work for you -- you could use std::unique_ptr<int[]> and make_unique together to make things work for you. However, if you need this kind of power, you probably know it yourself.
As a closing note, if you're just learning C++ and your book doesn't cover std::vectors somewhere early on, perhaps it's best to get a different book; they're one of the most commonly-useful data structures in the standard library and definitely not something to be left in an appendix.
If you need a variable sized array as a member of a class, don't use built-in arrays directly. Instead, use std::vector<T>, e.g.:
class myObject {
std::vector<int> array;
public:
explicit myObject(int size = 0): array(size){}
};
You can get the std:vector<int>'s size using array.size(), i.e., there is no need to store the size separately. Also, the content is automatically default initialized.

How to test for vector initialization success/failure in C++

I have a C++ class with vector<float> members which are initialized in the constructor to a size determined by one of the constructor's arguments.
summingBuffer = vector<float>(requiredSize);
How do I check whether the vector constructor has successfully allocated the the required space? The instance vars aren't pointers (should they be?) so if (NULL==myVector) doesn't work. Does vector throw an exception on allocation error? How about checking .size() afterwards?
Thank you...
Default allocator throws std::bad_alloc on failed allocation, just like new T does. So, no, no size checking is necessary. This isn't C.
The vector constructor will raise bad_alloc if it couldn't allocate enough storage, no need for extra checks.
Using pointers is not a good idea if you don't absolutely need them.
Also, looks like you could initialize your vectors directly rather than how you're doing it by using your constructor's initializer list. Something like:
struct foo {
std::vector<float> things;
foo(int vsize) : things(vsize) {
// rest of constructor code
}
};

C++ New vs Malloc for dynamic memory array of Objects

I have a class Bullet that takes several arguments for its construction. However, I am using a dynamic memory array to store them. I am using C++ so i want to conform to it's standard by using the new operator to allocate the memory. The problem is that the new operator is asking for the constructor arguments when I'm allocating the array, which I don't have at that time. I can accomplish this using malloc to get the right size then fill in form there, but that's not what i want to use :) any ideas?
pBulletArray = (Bullet*) malloc(iBulletArraySize * sizeof(Bullet)); // Works
pBulletArray = new Bullet[iBulletArraySize]; // Requires constructor arguments
Thanks.
You can't.
And if you truly want to conform to C++ standards, you should use std::vector.
FYI, it would probably be even more expensive than what you're trying to achieve. If you could do this, new would call a constructor. But since you'll modify the object later on anyway, the initial construction is useless.
1) std::vector
A std::vector really is the proper C++ way to do this.
std::vector<Bullet> bullets;
bullets.reserve(10); // allocate memory for bullets without constructing any
bullets.push_back(Bullet(10.2,"Bang")); // put a Bullet in the vector.
bullets.emplace_back(10.2,"Bang"); // (C++11 only) construct a Bullet in the vector without copying.
2) new [] operator
It is also possible to do this with new, but you really shouldn't. Manually managing resources with new/delete is an advanced task, similar to template meta-programming in that it's best left to library builders, who'll use these features to build efficient, high level libraries for you. In fact to do this correctly you'll basically be implementing the internals of std::vector.
When you use the new operator to allocate an array, every element in the array is default initialized. Your code could work if you added a default constructor to Bullet:
class Bullet {
public:
Bullet() {} // default constructor
Bullet(double,std::string const &) {}
};
std::unique_ptr<Bullet[]> b = new Bullet[10]; // default construct 10 bullets
Then, when you have the real data for a Bullet you can assign it to one of the elements of the array:
b[3] = Bullet(20.3,"Bang");
Note the use of unique_ptr to ensure that proper clean-up occurs, and that it's exception safe. Doing these things manually is difficult and error prone.
3) operator new
The new operator initializes its objects in addition to allocating space for them. If you want to simply allocate space, you can use operator new.
std::unique_ptr<Bullet,void(*)(Bullet*)> bullets(
static_cast<Bullet*>(::operator new(10 * sizeof(Bullet))),
[](Bullet *b){::operator delete(b);});
(Note that the unique_ptr ensures that the storage will be deallocated but no more. Specifically, if we construct any objects in this storage we have to manually destruct them and do so in an exception safe way.)
bullets now points to storage sufficient for an array of Bullets. You can construct an array in this storage:
new (bullets.get()) Bullet[10];
However the array construction again uses default initialization for each element, which we're trying to avoid.
AFAIK C++ doesn't specify any well defined method of constructing an array without constructing the elements. I imagine this is largely because doing so would be a no-op for most (all?) C++ implementations. So while the following is technically undefined, in practice it's pretty well defined.
bool constructed[10] = {}; // a place to mark which elements are constructed
// construct some elements of the array
for(int i=0;i<10;i+=2) {
try {
// pretend bullets points to the first element of a valid array. Otherwise 'bullets.get()+i' is undefined
new (bullets.get()+i) Bullet(10.2,"Bang");
constructed = true;
} catch(...) {}
}
That will construct elements of the array without using the default constructor. You don't have to construct every element, just the ones you want to use. However when destroying the elements you have to remember to destroy only the elements that were constructed.
// destruct the elements of the array that we constructed before
for(int i=0;i<10;++i) {
if(constructed[i]) {
bullets[i].~Bullet();
}
}
// unique_ptr destructor will take care of deallocating the storage
The above is a pretty simple case. Making non-trivial uses of this method exception safe without wrapping it all up in a class is more difficult. Wrapping it up in a class basically amounts to implementing std::vector.
4) std::vector
So just use std::vector.
It's possible to do what you want -- search for "operator new" if you really want to know how. But it's almost certainly a bad idea. Instead, use std::vector, which will take care of all the annoying details for you. You can use std::vector::reserve to allocate all the memory you'll use ahead of time.
Bullet** pBulletArray = new Bullet*[iBulletArraySize];
Then populate pBulletArray:
for(int i = 0; i < iBulletArraySize; i++)
{
pBulletArray[i] = new Bullet(arg0, arg1);
}
Just don't forget to free the memory using delete afterwards.
The way C++ new normally works is allocating the memory for the class instance and then calling the constructor for that instance. You basically have already allocated the memory for your instances.
You can call only the constructor for the first instance like this:
new((void*)pBulletArray) Bullet(int foo);
Calling the constructor of the second one would look like this (and so on)
new((void*)pBulletArray+1) Bullet(int bar);
if the Bullet constructor takes an int.
If what you're really after here is just fast allocation/deallocation, then you should look into "memory pools." I'd recommend using boost's implementation, rather than trying to roll your own. In particular, you would probably want to use an "object_pool".

Which of these is better practice?

Let's say I have a class FOO.
I want to have a std::vector of FOO.
Is it better if I do something like this:
FOO foo;
foo.init();
foo.prop = 1;
std::vector<FOO> myvec;
myvec.push_back(foo);
foo.prop = 2;
myvect.push_back(foo);
or is it better practice to do:
std::vector<FOO> myvec;
FOO foo;
myvec.push_back(foo);
myvec.back().init();
myvec.back().prop = 1;
myvec.push_back(foo);
myvec.back().init();
myvec.back().prop = 2;
I'm basically not sure if its better to make a model and push in the model instead of making an instance, pushing it, then modifying it from the vector. Also, which one is safer and least likely to result in memory leaks?
Thanks
Best practice is not to have an init() function - you want a constructor. If you always need to set prop, give the constructor a parameter to do it. This has nothing specifically to do with vectors - it's the way that all C++ code should be written.
Neither method has any memory issues as you're dealing with values and aren't dynamically allocating any objects manually.
I would favour giving FOO a constructor which does whatever init does and sets prop to the appropriate value. Then you can just push the values you want:
myvec.push_back(FOO(1));
myvec.push_back(FOO(2));
I think the best is to:
myvec.push_back(FOO(1));
myvec.push_back(FOO(2));
The answer depends on what your FOO class does. If it's a simple structure with no pointers etc., then both your approaches are fine and do the same.
Note that push_back inserts a copy of the object into the vector. If your class allocates memory on the heap, you need a copy constructor that creates a deep copy of your objects, otherwise you'll end up with memory leaks. Also, if your objects are quite large, it may be inefficient to create copies. In such cases, what I generally do is allocate the object itself on the heap externally and insert the pointer into the vector:
std::vector<FOO *> myvec;
FOO *foo;
foo = new FOO();
foo->init();
foo->val = 1;
myvec.push_back(foo);
foo = new FOO();
foo->init();
foo->val = 2;
myvec.push_back(foo);
However, in this case, you need to remember to free the objects before destroying the vector.
Besides what others have said about initializing your objects in the constructor, I would add this:
In your second example, where you put objects in the vector and then initialize them, you risk leaving your vector in an unusable state.
If for example, the init() method can throw an exception, you'll have a non/partially initialized object in your vector.
Of course, these problems goes away with a constructor that makes sure the objects are properly initialized.
In general: Don't start doing stuff with objects before they're in a usable state.