STL container for BIG (>13MB) structure - c++

I have currently a VERY BIG structure >13MB (and it HAS to remain like that, because I can't have pointer). My problem is how to store it into a class.
If it is part of the class, I get stackoverflow. If I use pointers the problem is solved, until I need to start copying the classes.... then the hell starts. (since the class has a lot of members).
I tryed with STL vector and array, but I still get the stackoverflow. Is any STL container that does not put the structure in the stack but it directly allocates the memory?
This way I can have everything properly done.
Thanks.
UPDATE:
Example code:
//HEADER
#include <vector>
struct BigStruct { //This is untouchable or divisible into an array of arrays
char a[1000];
int b[1000][1000];
long c[1000000];
// etc...
};
class Foo
{
std::vector<BigStruct> a; //It has to be here since is related to this instance of the class
public:
Foo();
//All the other funcs and method
// ...
//All the other variables are from STL
// ...
};
//CPP
Foo::Foo(){
a.resize(1);
}

I am just answering my own question. When calling resize() std::vector creates a element of type BigStruct in the stack and then copies it the number of times specified.
This behaviour can be avoided by creating the element in the vector like this:
Foo::Foo(){
BigStruct * temp = new BigStruct;
a.clear();
a.push_back(*temp); //Element is reserved and copied directly from temp.
delete temp;
}
This completely solves the stack issue, and allows portability(copy, move destroy) of the parent class.

Related

C++ polymorphic class pointer in vector

Let's say I have the following code which, in short, has:
a BaseClass with a pointer to a PointerClass
a ChildClass that inherits from BaseClass
a HolderClass that has an std::vector of ChildClasss and an std::vector of BaseClass*s:
The entire code is as follows:
#include <stdlib.h>
#include <time.h>
#include <vector>
class PointerClass {
public:
int num;
double num2;
PointerClass() {
srand(time(NULL));
num = rand() % 100;
num2 = rand() % 100 / 2.0;
}
};
class BaseClass {
public:
PointerClass *pointerClass;
};
class ChildClass: public BaseClass {
public:
ChildClass() {
pointerClass = new PointerClass();
}
};
class HolderClass {
public:
std::vector<BaseClass*> basePointerVec;
std::vector<ChildClass> childVec;
HolderClass() {
}
void addParentClass() {
ChildClass childClass = ChildClass();
childVec.push_back(childClass);
basePointerVec.push_back(&childClass);
}
};
int main(int argc, const char * argv[]) {
HolderClass holderClass = HolderClass();
for (int count = 0; count < 20; count++) {
holderClass.addParentClass();
}
for (int count = 0; count < holderClass.basePointerVec.size(); count++) {
delete holderClass.basePointerVec[count]->pointerClass;
}
return 0;
}
My problem is, after adding a pointer to the ChildClass into the std::vector<BaseClass*> basePointerVec and the actual ChildClass into the std::vector<ChildClass> childVec in the addParentClass() method in HolderClass, the data in basePointerVec andchildVec are completely different.
Furthermore, when I try to free the PointerClasses from the childVec, everything works fine. But when I try to free them from the basePointerVec instead, I get an error telling my I'm trying to free a pointer I have not allocated memory for.
And sure enough, when I use breakpoints to inspect everything, I find some funky behavior. It seems that every time I call ChildClass childClass = ChildClass(); in addParentClass(), every pointer in basePointerVec gets changed to point to the newly created ChildClass's BaseClass.
The point of me doing this in my actual program is to take advantage of polymorphism and have multiple classes inherit from BaseClass.
So my question is, why is every pointer in the vector being changed to point to the newly created class and how can I fix it?
P.S. sorry for the length of this question, it's as short as I could possibly make it
childVec.push_back(childClass);
The push_back method of the class vector copies the object. So the added object is not the same as childClass in this case.
You can't delete the pointers from basePointerVec because they were not allocated with new but they were allocated locally and they are deleted at the end of addParentClass. So, the code of addParent is wrong because the pointer you push in the vector is no longer valid after the end of the method and may cause segmentation faults(in best case). Here is a suggestion of improvement:
void addParentClass() {
ChildClass* childClass = new ChildClass();
childVec.push_back(*childClass);
basePointerVec.push_back(childClass);
}
The memory is now allocated dynamically, you should make sure to free these pointers with delete.
EDIT:
void addParentClass() {
childVec.push_back(ChildClass());
basePointerVec.push_back(&childVec.back());
}
And if you are using C++11:
void addParentClass() {
childVec.emplace_back();
basePointerVec.push_back(&childVec.back());
}
The other answers already addressed the specific problem in your code. Here are two general points about your program above that will help you IMHO avoid all sorts of problems in the future:
When you define a class, esp. one which can be subclassed, always make the dtor public virtual except if you have a specific reason not too.
Always store resources in classes with the RAII principle:
Except for a good reason, you should never have a naked member pointer. Use a shared_ptr member instead.
Except for a good reason, you should never have a vector of naked pointers. Again use a vector of shared pointers.
Using this, hopefully, you won't need to track in your head what got destroyed when before something was copied to whatever, etc. It will make it harder to mix up heap objects and stack objects.
Look here:
void addParentClass() {
ChildClass childClass = ChildClass();
childVec.push_back(childClass);
basePointerVec.push_back(&childClass);
}
Your objects are not allocated on the heap. They are values and in basePointerVec you put their addresses (which don't make sense anyway after addParentClass() returns). Don't try to delete those, that will crash your program. They will be automatically deleted when childVec goes out of scope.
When addParentClass returns, the childClass object is destroyed. Therefore, the pointer to that object, that you put into basePointerVec cannot be used anymore.
You are creating a local variable that is destroyed as soon addParentClass goes out of scope. Also see the answers to this question which explains what happens when you don't use new. So the vector of BaseClass pointers are pointing to an object that is destroyed, and the childVec vector of objects are creating new copies when you use push_back, from this page:
The new element is initialized as a copy of value.
This is why the two vectors are pointing to different objects. You could create a destructor for the classes and add debugging prints to the destructor and the constructor to see when the objects are created/destroyed, this should give you a better idea of what is happening in what order.

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.

Correct use of std::map as class member

In the past I always created a map like this:
class TestClass
{
private:
std::map<int,int> *mapA;
};
TestClass::TestClass
{
mapA = new std::map<int,int>();
}
TestClass::~TestClass
{
mapA->clear(); // not necessary
delete mapA;
}
So, now I read all over the place at Stackoverflow: avoid pointers as often as possible
Currently I want to create the map without pointer and new (no need to delete the object by myself and less danger of getting some memory leak)!
class TestClass
{
public:
TestClass() : mapA() // this is also needed?
{};
private:
std::map<int,int> mapA;
};
Any further steps for correct creation of the map necessary?
Thanks for any help and/or clarification!
Nope that's it, and you don't need to explicitly initialize it in the constructor.
As zennehoy says, it is not necessary to initialize the map in the TestClass constructor.
Let me note a difference between the two implementations:
In the first one, the TestClass, as it is currently written, is not copyable without undesirable effects because the raw pointer to the dynamically allocated map is copied:
TestClass *A = new TestClass; // A has a map
TestClass *B = new TestClass(A); // B shares the map with A!
delete A; // this deletes A's map (in destructor)
delete B; // this deletes A's map again! wrong
In your second implementation, that does not happen because the map, and not just its address, is copied completely.
To solve that issue in your first implementation, you should use a shared pointer, or do the work yourself by implementing the operator= and the copy constructor. Or, if you want to really share the map between copied instances, you should implement a reference counting mechanism.

c++ pointer (to an array) inside of a class object initialization

Let's say I have a class that includes an array of some struct, and a pointer to that array.
struct Box {
//stuff
};
class Foo {
private:
Box *boxPtr //pointer to an array of Box structs
int max; //the size of the partially filled array
int boxCounter; //the current number of non-NULL elements in the array
public:
Foo(); //constructor
Foo(const Foo &obj); //copy constructor
~Foo(); //destructor
bool newBoxInsert(Box newBox){
//adds another Box to my array of Box structs
boxCounter++;
}
//etc
};
and in my int main(), I somehow must create a brand new object of class Foo.
I'm going to need to partially fill that array of indeterminate size, whose pointer is boxPtr.
How would I go about initializing that array? Should the constructor do it? Or should I let newBoxInsert handle it?
In either case, how would I achieve that? I'm guessing I would have to dynamically allocate the array. If that's the case, then it's good to have the pointer as a class member... right?
For example, when adding the very first element to my array, should I use
boxCounter = 1;
boxPtr = new Box[boxCounter];
then continue on to keep adding elements to the array?
Perhaps this is just better done with vectors. They're much more... flexible (?) when adding elements. Can vectors contain structs as elements?
[/n00b]
private:
Box *boxPtr
replace this by:
private:
std::vector<Box> mbox;
It saves you all the manual memory management. And you are less likely to go wrong.
Yes, std::vector can contain structs as elements. In fact it is a template class so it can store whatever data type you want.
In C++ if you need dynamic array, the simplest and most obvious choice us std::vector.

C++ vector on heap or stack?

I just noticed in my code that I declared a vector on the stack (instead of the heap) and then used my "set"-function to set the member variable of another class to this vector. The only problem is that after exiting my function (myFunction) the vector should be destroyed (because it is on the stack) and the reference to this vector should point to "nothing meaningful". But my code is working correctly and so I was asking myself why. Am I just lucky because the portion of the memory where the vector was, is existing because nobody deleted it until now? So it is a matter of luck if my code is not crashing?
Here is the code:
void myFunction() {
std::vector<std::vector<double>> vDoubleVector = MyUtils::CreateDoubleVector(); //Creates a
double vector (but not on heap)
MyClass mC;
mC.SetDoubleVector(vDoubleVector);
}
class MyClass {
std::vector<std::vector<double>> mDoubleVector;
void SetDoubleVector(std::vector<std::vector<double>>& aDoubleVector) {
mDoubleVector = aDoubleVector;
}
}
Since Luchian was faster than me, I'm going to add sensible improvement to this code:
void SetDoubleVector(std::vector<std::vector<double>> aDoubleVector) {
mDoubleVector = std::move(aDoubleVector);
}
Citing "rule of thumb" - If you need to copy, do it in the interface.
//EDIT to make the answer complete.
Your code did copy the vector by use of its operator= in SetDoubleVector.
There is no reference to the vector, the class has a copy of it.