I'm constructing a struct with one of the member being a map.
First question is this allowed? The compiler did not complain.
struct A {
map<int, float> B;
}
Later I declare an array of such data type.
A *C = (A *)INTERNAL_CALLOC(..., sizeof(A));
Here the function INTERNAL_CALLOC is a functional wrapper of MALLOC.
Later on in the code when I try to first time insert an item into the array's first element's map, I got a core dump.
C[0].B[0] = 0.001;
Any idea why is this the case?
Thanks!
Yes, a map in a struct is fine.
Allocating with malloc is definitely not fine; the constructor is not called. So your map will most likely do something terrible when you attempt to use it.
General rule of thumb: don't use malloc/calloc/realloc/free in C++. Avoid dynamic allocation wherever possible, and use new/delete when unavoidable.*
* And read up on smart pointers.
If you really must allocate with INTERNAL_CALLOC, then use placement new.
First, you must define a constructor and a destructor for the type A, or define A as a class:
struct A {
A(){}
~A(){}
map<int, float> B;
};
Then you can simply call:
//Allocate an A, uninitialized
A *C = (A *)INTERNAL_CALLOC(..., sizeof(A));
//Initialize the newly allocated A
new (C) A();
later when you free the object you must explicitly call the destructor:
//A *C;
C->~A();
INTERNAL_free(C);
A *C = (A *)INTERNAL_CALLOC(..., sizeof(A));
Here you are lying to the compiler. You are telling it that the return value from INTERNAL_CALLOC points to an A, but it doesn't, it just points to zeroes. Use new.
You don't get a valid std::map<whatever...> by filling memory with zero bytes.
To a certain extent, it's possible with POD types (approximately, "pure C" data structures).
Since you use std::map as a member,
I recommend to use std::vector instead of plain array to be the container.
You can do as follow:
struct A
{
std::map<int, int> B;
};
std::vector<A> vecofmap;
A elem0;
A elem1;
A elem2;
vecofmap.push_back(elem0);
vecofmap.push_back(elem1);
vecofmap.push_back(elem2);
vecofmap[0].B[0] = 100;
std::cout << vecofmap[0].B[0] <<std::endl;
Then no needs to bother with memory allocation.
Allocating memory using malloc does not initialize the array elements.
Related
#include <iostream>
class A {
public:
A(int d) : y(d) {}
int y;
};
int main(void) {
A d[3] = {A(0), A(1), A(2)};
std::cout << d[1].y << std::endl;
};
I'm working on a project for university. I'm instructed not to use an object array and instantiate each element with a temporary object of my class - so something like the above code is a no-no. Instead, it's recommended we use a an array of type A* and then use new on each element so that we create an object and make each element point to it.
So we'd have something like this:
A* d[3];
for (int i=0;i<3;i++)
d[i]=new A(i);
However, I don't quite understand the difference in practice when compared to the first version. As far as I understand in the first version we we create the three temporary objects (which are rvalues) using the constructor and then assign them to the array. After the assignment ends, the temporary is destroyed and its values are copied to the array. In the second version, we have the advantage of being able to delete what d[] points to but disregarding that, what is the drawback of using the first method?
EDIT:
class B{
public:
A a1[3];
}
Assuming my initial definition is followed by this (A isn't default constructible, is something like this impossible? So in that case I can't an array of objects and I instead have to resort to a pointer array of type A* and then use new, as my only resort.
Array of pointers -> memory allocation when you create an object and assign it to the pointer. Array of 1000 pointers with 1 element inside = 1x the memory.
Array of objects -> memory allocation when you create an array. Array of 1000 with 1 element inside = 1000x the memory.
1 ) A d[3], it creates a built-in array (or C-style, plain, naked array...) which contains (three) elements of type A, these elements live on the stack (according to your code).
2 ) A* d[3];, it creates a built-in array which contains (three) pointers to elements of type A (or they should). It doesn't mean that the pointed element is of type A, it's developer's task to create those elements, and you can do it in two ways, using the stack (as before):
A element;
...
d[0] = &element;
or using the heap (with new/new[] and delete/delete[]):
d[0] = new A;
...
delete d[0];
Side effects of the second option; you may point to an already destroyed element (i.e. the element is out of scope), hence potential seg fault; you may loose the pointer to the allocated memory (i.e. the array of pointers is out of scope and the allocated memory has not been released), hence memory leak.
However, an advantage is that you can use lazy initialisation (you don't pay for what you don't use). If you don't need an A object in d[2] (or pointed by), why should you create it and waste memory? And here smart pointers arise, they make your life easier allowing you to allocate memory only when you need it, reducing the risk of seg faults (worth it to mention std::weak_ptr), memory leaks, etc:
std::unique_ptr<A> d[3];
d[0] = std::make_unique<A>(); // Call make_unique when you need it
But still a bit nasty, the built-in arrays are good but may be much better under some circumstances. It is hard to add or remove elements, iterate, get the size, access to the tail/head, etc... And that's why containers are quite useful, i.e. std::array or std::vector (where its size doesn't have to be known at compilation time):
std::vector<std::unique_ptr< A> > d(3);
std::array<std::unique_ptr<A,3> > d;
There are no advantages whatsoever to the following code in C++:
A* d[3];
for (int i=0;i<3;i++)
d[i]=new A(i);
In fact, you shouldn't write it at all.
Your solution with a locally-declared temporary array is valid, but has the significant limitation of requiring that the number of elements in the array be a compile-time constant (i.e., known ahead of time).
If you need to have an array with a dynamic number of elements, known only at run time, then you should use a std::vector, which performs the new allocation automatically. That is the idiomatic way of working with dynamically-allocated arrays in C++.
Suppose in C++, I have the following code:
class Foo {
private:
double* myData;
public:
Foo(double data[]) {
myData = data;
}
}
int main() {
double mainData[] = {1.0};
Foo myfoo(mainData);
}
As far as my knowledge can tell, mainData is treated as a pointer when passed into the Foo constructor, so the line myData = data only assigns the pointer address. So no extra memory is allocated here, right? But then, is the Foo class responsible for providing a destructor that deallocates myData's memory? Or do we have a dynamic array pointer that actually points to stack memory?
Also, if I want to protect Foo's myData from changing when mainData is changed, is there a simple way to force the Foo constructor to copy it? Ideally myData would be a simple array, not a pointer, but changing the line double* myData to double myData[] doesn't seem to work because the size of the array is unknown until runtime.
The parameter here is not a dynamic array:
Foo(double data[])
In fact the declaration is equivalent to this:
Foo(double * data)
Even decltype will tell you they are the same thing, and those two signatures will conflict as overloads.
So, there is no allocation. You are only passing a pointer to the first element of the array.
Also, the only place where C++ will automatically copy an array is when it is a member of a class, and the empty bracket [] syntax for indeterminate size is not allowed for members. (Or if it is, the size is already determined by the time the class type is complete, before the copy constructor or assignment operator is generated.)
Also, if I want to protect Foo's myData from changing when mainData is changed, is there a simple way to force the Foo constructor to copy it? Ideally myData would be a simple array, not a pointer, but changing the line double* myData to double myData[] doesn't seem to work because the size of the array is unknown until runtime.
You can keep a copy of the data, but you will need a pointer if its size (or at least an upper bound) is unknown at compile time. I would recommend std::vector over a naked pointer, or at least std::unique_ptr< double[] >.
In this case myData points to an address on the stack, which calls the destructor for Foo when the function goes out of scope. Generally arrays are described as being dynamic when you use the keyword new to allocated them.
As for your second question, you're probably going to have to pass into the constructor a pointer to the array and the length of the array. You then need to dynamically create a double array (pointed to by myData), using the length that was passed in, and then make a copy.
Don't forget to delete the memory in the destructor.
A pointer only holds a memory address, without new or delete involved a pointer has nothing to do with allocation or deallocation. Thus your code wont invoke any memory allocation.
In order to delete an (dynamically allocated) array you have to do delete[] foo;
Only dynamically allocated objects must be deleted, if you class takes ownership (it manages the array, calls delete on destruction) passing an array with automatic storage duration is a very bad idea.
Yes, it does not allocate additional memory.
No, the destructor won't do anything with the class field if it hadn't been told so.
in Foo class instances will have pointer to data that is allocated/managed by other classes this is very bad design. The best thing is to make the Foo constructor make a copy and store it in the pointer. Then in the desctructor free that one. This would require passing the length of the array to the Foo constructor. I hope that helps.
I wonder whether memory for array member of a class be allocated in c++.
In my class, I defined array member like this:
class A
{
public:
B* B_array[1000];
}
and, in the constructor, I want to use it:
A::A()
{
for(int i = 0; i < 1000; i++)
{
B_array[i] = new B;//can i use B_array[0...999]???
}
}
B* B_array[1000];
What you have is an array of 1000 pointers to the type B.
for(int i = 0; i < 1000; i++)
{
B_array[i] = new B;//can i use B_array[0...999]???
}
Allocates memory to each pointer in the array, after this statement each pointer points to a memory on heap.
So yes you can use each of them, once this code is executed.
Yes, you can. When you enter the body of constructor, there are 1000 uninitialized pointers waiting for you to initialize them.
What you should do, though, is use std::vector<B>
class A
{
public:
std::vector<B> array;
}
A::A() : array(1000) {}
and be done with it. Vector allocates its elements dynamically.
Yes you can. Memory for 1000 pointers will be allocated always. However those pointers will not be initialised unless you do that yourself (as you are in your contructor code).
I wonder whether memory for array member of a class be allocated in c++
Yes, why not. If your doubt is about allocating an array the way you are doing, it is possible. If your doubt is about calling B's constructor while still being in A's constructor, then also there is absolutely no issues with that.
In general, however there are several things that I would take care in the code shown e.g. not hard coding the value 1000, checking for exception from new etc.. you get the idea.
And you should also be bothered about releasing the memory resource in the destructor of A explicitly.
Yes, the memory for 1000 pointers of B class instances will be allocated. You have defined an array B_array[1000] of B* objects. It's the same as int integerArray [1000]. You just store pointers in the array, not values.
However you will need to initialize them to point to the actual objects on the heap.
What happens in the following code?
I guess it doesn't work since I get a segmentation fault if I want to add something to the b array, but what exactly did I do here?
Is there no way of specifying the size of an array inside the constructor?
class A {
public:
A() {
b[3];
}
private:
B b[];
};
B b[] here is a "flexible array member", a non-standard extension in your compiler (taken from C99) that allows you to declare an unbounded array as the last member in a type. It's only of use when allocating your object the old-fashioned C way (when you pad your argument to malloc to make space for the array), and ought to be avoided. In this case, you haven't allocated any extra memory for the array, so in your constructor body when you're trying to access something that occurs 3 'elements' past this nothingness, you're invoking UB. I'll ignore the extension for the rest of my answer, as it really has no place in C++ code.
Is there no way of specifying the size of an array inside the constructor?
No, there isn't.
Array bounds must be known at compile-time, so there is no case where you know more in your ctor body than you do in the class definition; you are required to write the dimension in the member's declaration itself:
class A {
B b[3];
};
If the dimension is a run-time quantity in your program, you'll need to instead store a pointer and, in your constructor, point it at a dynamic block of memory:
class A {
public:
A() : b(new B[3]) {}
~A() { delete[] b; }
private:
B* b; // same as `B b[]`! but far clearer
};
Instead, though, I suggest a std::vector:
class A {
public:
A() : b(3) {}
private:
std::vector<B> b;
};
Yes. Using operator new: b = new B[3];. Declare b as B *b for that.
Of course, you need to delete[] it in the destructor.
But a better way would be using std::vector instead of the array, and then you don't need to worry about preallocating memory.
C++ doesn't support any types with size determined at runtime. Therefore you have only the options to determine the array size at compile time (possible through a non-type template parameter) or move the array out of the object by making b a pointer and allocating memory for it with new (or, better, let the standard library do that for you by using a vector).
This is not possible - what would you expect sizeof(A) to evaluate to?! If you really need such functionality, use dynamic allocation, i.e. a private member variable B *b, b(new B[3]) in the constructors initializer list, and delete[] b; in the destructor.
So I have a couple of structs...
struct myBaseStruct
{
};
struct myDerivedStruct : public myBaseStruct
{
int a, b, c, d;
unsigned char* ident;
};
myDerivedStruct* pNewStruct;
...and I want to dynamically allocate enough space so that I can 'memcpy' in some data, including a zero-terminated string. The size of the base struct is apparently '1' (I assume because it can't be zero) and the size of the derived is 20, which seems to make sense (5 x 4).
So, I have a data buffer which is a size of 29, the first 16 bytes being the ints and the remaining 13 being the string.
How can I allocate enough memory for pNewStruct so that there is enough for the string? Ideally, I just want to go:
allocate 29 bytes at pNewStruct;
memcpy from buffer into pNewStruct;
Thanks,
You go back to C or abandon these ideas and actually use C++ as it's intended.
Use the constructor to allocate memory and destructor to delete it.
Don't let some other code write into your memory space, create a function that will ensure memory is allocated.
Use a std:string or std::vector to hold the data rather than rolling your own container class.
Ideally you should just say:
myDerivedClass* foo = new myDerivedClass(a, b, c, d, ident);
In the current C++ standard, myDerivedStruct is non-POD, because it has a base class. The result of memcpying anything into it is undefined.
I've heard that C++0x will relax the rules, so that more classes are POD than in C++98, but I haven't looked into it. Also, I doubt that very many compilers would lay out your class in a way that's incompatible with PODs. I expect you'd only have trouble with something that didn't do the empty base class optimisation. But there it is.
If it was POD, or if you're willing to take your chances with your implementation, then you could use malloc(sizeof(myStruct)+13) or new char[sizeof(myStruct)+13] to allocate enough space, basically the same as you would in C. The motivation presumably is to avoid the memory and time overhead of just putting a std::string member in your class, but at the cost of having to write the code for the manual memory management.
You can overallocate for any class instance, but it implies a certain amount of management overhead. The only valid way to do this is by using a custom memory allocation call. Without changing the class definition, you can do this.
void* pMem = ::operator new(sizeof(myDerivedStruct) + n);
myDerivedStruct* pObject = new (pMem) myDerivedStruct;
Assuming that you don't overload operator delete in the hierarchy then delete pObject will be a correct way to destroy pObject and deallocate the allocated memory. Of course, if you allocate any objects in the excess memory area then you must correctly free them before deallocating the memory.
You then have access to n bytes of raw memory at this address: void* p = pObject + 1. You can memcpy data to and from this area as you like. You can assign to the object itself and shouldn't need to memcpy its data.
You can also provide a custom memory allocator in the class itself that takes an extra size_t describing the amount of excess memory to allocate enabling you to do the allocation in a single new expression, but this requires more overhead in the class design.
myDerivedStruct* pObject = new (n) myDerivedStruct;
and
struct myDerivedStruct
{
// ...
void* operator new(std::size_t objsize, std::size_t excess storage);
// other operator new and delete overrides to make sure that you have no memory leaks
};
You can allocate any size you want with malloc:
myDerivedStruct* pNewStruct = (myDerivedStruct*) malloc(
sizeof(myDerivedStruct) + sizeof_extra data);
You have a different problem though, in that myDerivedStruct::ident is a very ambigous construct. It is a pointer to a char (array), then the structs ends with the address where the char array starts? ident can point to anywhere and is very ambigous who owns the array ident points to. It seems to me that you expect the struct to end with the actual char array itself and the struct owns the extra array. Such structures usualy have a size member to keep track of teir own size so that API functions can properly manage them and copy them, and the extra data starts, by convention, after the structure ends. Or they end with a 0 length array char ident[0] although that creates problems with some compilers. For many reasons, there is no place for inheritance in such structs:
struct myStruct
{
size_t size;
int a, b, c, d;
char ident[0];
};
Mixing memcpy and new seems like a terrible idea in this context. Consider using malloc instead.
You can dynamically allocate space by doing:
myDerivedStruct* pNewStruct = reinterpret_cast<myDerivedStruct*>(new char[size]);
however
Are you sure you want to do this?
Also, note that if you are intending to use ident as the pointer to the start of your string, that would be incorrect. You infact need &ident, since the ident variable is itself at the start of your unused space, interpreting what is at that space as a pointer is most likely going to be meaningless. Hence, it would make more sense if ident were unsigned char or char rather than unsigned char*.
[edit again]
I'd just like to emphasise that what you're doing is really a really really bad idea.
char* buffer = [some data here];
myDerivedStruct* pNewStruct = new myDerivedStruct();
memcpy(buffer,pNewStruct,4*sizeof(int));
pNewStruct->ident = new char[ strlen(buffer+(4*sizeof int)) ];
strcpy(pNewStruct->ident,buffer+(4*sizeof int));
Something like that.
Is the buffer size known at compile time? A statically allocated array would be an easier solution in that case. Otherwise, see Remus Rusanu's answer above. That's how the win32 api manages variable sized structs.
struct myDerivedStruct : public myBaseStruct
{
int a, b, c, d;
unsigned char ident[BUFFER_SIZE];
};
Firstly, I don't get what's the point of having a myBaseStruct base. You proivided no explanation.
Secondly, what you declared in your original post will no work with the data layout you described. For what you described in the OP, you need the last member of the struct to be an array, not a pointer
struct myDerivedStruct : public myBaseStruct {
int a, b, c, d;
unsigned char ident[1];
};
Array size doesn't matter, but it should be greater than 0. Arrays of size 0 are explicitly illegal in C++.
Thirdly, if you for some reason want to use new specifically, you'll have to allocate a buffer of char objects of required size and then convert the resultant pointer to your pointer type
char *raw_buffer = new char[29];
myDerivedStruct* pNewStruct = reinterpret_cast<myDerivedStruct*>(raw_buffer);
After that you can do your memcpy, assuming that the size is right.