How would I go about allocating an array of a class without constructing the class, so I could fill up the array later?
I was originally trying to use
Myclass * array = new Myclass[N];
But it tries to construct Myclass to N.
First just declare it without allocating
Myclass * array[N];
when you need it
for(int i=0;i<N;i++){
array[i] = new Myclass(/*params*/);
}
But consider using std::vector/std::list if you must not have to manage memory yourself.
If you really want to do that, (not sure why), you could try
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass()
{ cout << "helo" << endl; }
};
int main(int argc, char *argv[])
{
int size = 4;
// Here is the trick, pointer to pointer.
MyClass **vec = new MyClass *[size];
cout << "before" << endl;
for (int i = 0; i < 4; ++i)
vec[i] = new MyClass;
// remember to free the vec
return 0;
}
Someone suggested placement new, so here it goes:
// allocate space
std::vector<unsigned char> mybuffer(N * sizeof(Myclass));
Myclass *array = reinterpret_cast<Myclass *>(&mybuffer[0]);
// when you're ready to use it
new( &array[0] ) Myclass(2);
new( &array[1] ) Myclass(3);
// etc...
// when you're done with it
array[0].~Myclass();
array[1].~Myclass();
// etc....
Of course, it is undefined behaviour to use array[x] before you have new'd it, or after you called the destructor.
This is generally something you wouldn't use as a solution to a "normal" problem. Consider actually defining a default constructor that does nothing, and having a function you call later which enhances the objects above their default state.
If you can use C++11, the optimal solution for you is probably std::vector<MyClass> with emplace-base insertions:
class MyClass {
public:
MyClass(int a, bool b, char c); // some non-default constructor
MyClass(double d); // another constructor
void bar();
};
void foo(int n) {
std::vector<MyClass> mv;
mv.reserve(n); // not even needed but beneficial if you know the final size.
// emplace_back uses perfect forwarding to call any arbitrary constructor:
mv.emplace_back(2, false, 'a');
mv.emplace_back(3, true, 'b');
mv.emplace_back(3.1415926535);
// can iterate vector easily:
for (auto &i : mv) {
i.bar();
}
// everything destructed automatically when the collection falls of scope ...
}
This creates the values in the collection directly without a copy and defers any construction of elements until you are ready, unlike new[], which makes a bunch of default objects at array-creation time. It is generally better than placement new as well, since it doesn't leave open opportunities for missed destruction or destructing an invalid memory location as well as being just easier to read.
Alternatively, you may use boost::optional.
So in your case:
std::vector<boost::optional<Myclass>> array(N);
Related
Ok, if I want to create a heap object with a custom new operator, I know that I need to overload the new operator like this:
void* operator new(size_t size, int unused)
{
void* ptr = malloc(size);
//some custom code
return ptr;
}
And then, if I want to create a heap object using this overloaded operator I would do this:
SomeClass* a = new(0) SomeClass;
The question is: can I do something like this to create a stack object?
I agree with other answers that you probably don't need this but you could do it. See sample code below, just allocate the memory ahead of time and pass it into placement new. You might want to do this if you are using the array new[] form where you might do something like
void *rawMemory = operator new[](25*sizeof(std::stack));
if you had an array of stacks that you had a factory method that managed the resources or something. Either way it depends on your application and use cases. Below shows a simple example
#include <iostream>
#include <stack>
int main ( int argc, char *argv[])
{
void *rawMemory = operator new(sizeof(std::stack<unsigned int>));
std::stack<unsigned int> *s = new (rawMemory) std::stack<unsigned int>;
s->push(10);
std::cout << s->top() << std::endl;
return 0;
}
Second example using the array version, which seems more useful where you may be managing 25 different stacks and handing them to clients. Also, answering your comment. See that the container is defined in the stack definition this time, in this case I am using a vector for the container. Stack is a container but it has an underlying container that defaults to deque
#include <iostream>
#include <stack>
#include <vector>
int main ( int argc, char *argv[])
{
typedef std::stack<unsigned int,std::vector<unsigned int> > StackType;
void *rawMemory = operator new[](25*sizeof(StackType));
StackType *stacks = static_cast<StackType*> (rawMemory);
// allocate
for ( unsigned int i = 0; i < 25; ++i )
{
new (stacks+i) StackType;
}
stacks[1].push(10);
std::cout << stacks[1].top() << std::endl;
// don't forget to delete or smart resize
for ( int i = 24; i >= 0; --i )
{
StackType x;
std::swap ( x, stacks[i] );
}
return 0;
}
You can define a macro like this:
#define STACK_NEW(T) new (alloca(sizeof(T))) T
that uses placement new and alloca() to allocate a block on the stack and construct an object of type T on top of it. You can also define an array version:
#define STACK_NEW_ARRAY(T, n) new (alloca(n * sizeof(T))) T
You'd use this macro in the following ways:
int * p = STACK_NEW(int);
MyObj * q = STACK_NEW(MyObj) (my, constructor, parameters);
int * r = STACK_NEW_ARRAY(int, 42);
You'll have destruct these objects manually:
q->~MyObj();
Deleting them will have undefined behavior.
WARNING: This whole facility is very unsafe. I'd strongly recommend against having such systematically dangerous tools in your codebase. As far as I can see, there is no safe way to use it and it will cause you pain!
I want to store a dynamic array of structs as a member variable within another struct. Is this the proper way to use the constructor given my example in main?
EDIT
I corrected some of the obvious mistakes I had in the code (was 6am at the time). I also added another member to B to see if the push_back is still correct. I know my life would be a lot easier using vectors for dynamic memory but I need to do it this way as these are structs to be used with thrust::device_vector in the end.
struct A
{
float mem1;
int mem2;
};
struct B
{
A * Aarr1;
A * Aarr2;
B(A * a1, A * a2): Aarr1(a1), Aarr2(a2){}
};
int main()
{
A * test = new A[5];
A * test2 = new A[10];
vector<B> btest;
btest.push_back(B(test, test2));
for(int i=0; i<5; i++)
printf("mem1: %f, mem2: %i \n", btest[0].Aarr[i].mem1, btest[0].Aarr[i].mem2);
}
Taken in isolation, the constructor is fine. However, there are many other problems with the code.
As it stands, your code is leaking memory since the array is never deallocated.
You might want to consider moving away from using C arrays to std::vector or std::array.
There's also a bug in printf() (misspelt as print()): one of the two mem1 should be mem2.
The constructor of B is OK, but the way you invoke push_back() is not:
btest.push_back(B(A));
You should do this:
btest.push_back(B(test));
Moreover, the explicit construction of a B object is not necessary, since your constructor is not marked as explicit:
btest.push_back(test);
Also consider using automatic memory management rather than raw pointers (std::vector<> instead of arrays, smart pointers instead of pointers). This way, you will avoid leaking memory due to forgetting this:
delete test;
Leaking aside, the worst thing is that your code also has Undefined Behavior, because it uses the value of uninitialized variables (the member variables of A within the for loop).
Finally, you shouldn't use : after class names in a class definition. This is how you could rewrite your code in C++11:
#include <vector>
#include <cstdio>
struct A // Do not use ":" here, that's for introducing inheritance,
// which you are not using in your example.
{
float mem1 = 0.0; // In C++11, you can specify default initialization
int mem2 = 0; // for your member variables this way. In C++03 you
// would have to define a default constructor which
// initializes your member variables to the desired
// value.
};
struct B
{
std::vector<A> Aarr;
// ^^^^^^^^^^^^^^
// Prefer using standard containers over dynamically allocated arrays, as
// it saves your from taking care of memory management and avoids leaks.
explicit B(size_t s): Aarr(s) { }
// ^^^^^^^^
// It is usually a good idea to mark constructors which take on argument
// and are not copy constructors as explicit, to avoid awkward implicit
// conversions.
};
int main()
{
std::vector<B> btest;
btest.push_back(B(5));
// ^^^^
// We need to explicitly construct an object of type B,
// because we have marked B's constructor as explicit.
for(int i=0; i<5; i++)
{
std::printf(
"mem1: %f, mem2: %i \n",
btest[0].Aarr[i].mem1,
btest[0].Aarr[i].mem2
// ^
// You had "mem1" here.
);
}
}
There are few minor mistakes and typos in your code. It should look like this:
struct A // <-- no ':' after name type
{
float mem1;
int mem2;
};
struct B // <-- no ':' after name type
{
A * Aarr;
B(A * a): Aarr(a){}
};
int main()
{
A * test = new A[5];
vector<B> btest;
btest.push_back(B(test)); // <-- test, A is name of type
for(int i=0; i<5; i++)
printf("mem1: %f, mem2: %i \n", // <-- printf, not print
btest[0].Aarr[i].mem1, btest[0].Aarr[i].mem1);
}
Also consider using std::vector or std::array instead of C-style arrays as well.
I need to initialize an array of objects of a parametrized constructor . How can i do it in best possible way ?
# include<iostream>
# include<conio.h>
# include<stdio.h>
using namespace std;
class A
{
public:
int a;
A();
A(int x)
{
a=x;
}
};
int main()
{
A *a1,a2(1);
a1 = (A*)malloc(sizeof(A)*10); // equivalent to A[10].
for(int i=0;i<10;i++) a1[i]=a2; // Initialization is important in any program.
for(int i=0;i<10;i++) cout<<a1[i].a;
getch();
return 0;
}
This does work but is there some other way better than this ?
The C++ way would be to use a std::vector.
std::vector<A> a1(10, 1);
creates 10 A's initialized by 1.
This is solved using std::vector constructor taking size and base element :
A a2(1);
std::vector<A> tab(10, a2);
Note that malloc does not construct objects, and so calling a1[i]=a2 is bad form. It probably seems to work fine since they are POD-ish objects, but this is not the proper way to do C++. It is undefined behavior, which is completely unpredictable. It may work ten thousand times in a row, and then erase your bank account. You should use new instead, which also constructs. Or better yet, use a vector, like the other answers suggest. Also, be sure that the default constructor initializes the data, and initialization will be less of a worry.
If you really must use malloc, the "correct way" to initialize is this:
std::uninitialized_copy(a1, a1+10, a2); //constructs and assigns
which is roughly equivalent to:
{
int i=0;
try {
for(i=0; i<10; ++i)
new(a1+i)A(a2); //constructs and initializes in the buffer
} catch(...) {
try {
for(; i>=0; --i)
(a1+i)->~A(); //destroy if an error occured
} catch(...) {
std::terminate();
}
throw;
}
}
In the code below I would like array to be defined as an array of size x when the Class constructor is called. How can I do that?
class Class
{
public:
int array[];
Class(int x) : ??? { }
}
You folks have so overcomplicated this. Of course you can do this in C++. It is fine for him to use a normal array for efficiency. A vector only makes sense if he doesn't know the final size of the array ahead of time, i.e., it needs to grow over time.
If you can know the array size one level higher in the chain, a templated class is the easiest, because there's no dynamic allocation and no chance of memory leaks:
template < int ARRAY_LEN > // you can even set to a default value here of C++'11
class MyClass
{
int array[ARRAY_LEN]; // Don't need to alloc or dealloc in structure! Works like you imagine!
}
// Then you set the length of each object where you declare the object, e.g.
MyClass<1024> instance; // But only works for constant values, i.e. known to compiler
If you can't know the length at the place you declare the object, or if you want to reuse the same object with different lengths, or you must accept an unknown length, then you need to allocate it in your constructor and free it in your destructor... (and in theory always check to make sure it worked...)
class MyClass
{
int *array;
MyClass(int len) { array = calloc(sizeof(int), len); assert(array); }
~MyClass() { free(array); array = NULL; } // DON'T FORGET TO FREE UP SPACE!
}
You can't initialize the size of an array with a non-const dimension that can't be calculated at compile time (at least not in current C++ standard, AFAIK).
I recommend using std::vector<int> instead of array. It provides array like syntax for most of the operations.
Use the new operator:
class Class
{
int* array;
Class(int x) : array(new int[x]) {};
};
I don't think it can be done. At least not the way you want. You can't create a statically sized array (array[]) when the size comes from dynamic information (x).
You'll need to either store a pointer-to-int, and the size, and overload the copy constructor, assignment operator, and destructor to handle it, or use std::vector.
class Class
{
::std::vector<int> array;
Class(int x) : array(x) { }
};
Sorry for necroing this old thread.
There is actually a way to find out the size of the array compile-time. It goes something like this:
#include <cstdlib>
template<typename T>
class Class
{
T* _Buffer;
public:
template<size_t SIZE>
Class(T (&static_array)[SIZE])
{
_Buffer = (T*)malloc(sizeof(T) * SIZE);
memcpy(_Buffer, static_array, sizeof(T) * SIZE);
}
~Class()
{
if(_Buffer)
{
free(_Buffer);
_Buffer = NULL;
}
}
};
int main()
{
int int_array[32];
Class<int> c = Class<int>(int_array);
return 0;
}
Alternatively, if you hate to malloc / new, then you can create a size templated class instead. Though, I wouldn't really recommend it and the syntax is quite ugly.
#include <cstdio>
template<typename T, size_t SIZE>
class Class
{
private:
T _Array[sz];
public:
Class(T (&static_array)[SIZE])
{
memcpy(_Array, static_array, sizeof(T) * SIZE);
}
};
int main()
{
char int_array[32];
Class<char, sizeof(int_array)> c = Class<char, sizeof(int_array)>(int_array);
return 0;
}
Anyways, I hope this was helpful :)
I had the same problem and I solved it this way
class example
{
int *array;
example (int size)
{
array = new int[size];
}
}
Don't you understand there is not need to use vector, if one wants to use arrays it's a matter of efficiency, e.g. less space, no copy time (in such case if handled properly there is not even need to delete the array within a destructor), etc. wichever reasons one has.
the correct answer is: (quoted)
class Class
{
int* array;
Class(int x) : array(new int[x]) {};
};
Do not try to force one to use non optimal alternatives or you'll be confusing unexperienced programmers
Instead of using a raw array, why not use a vector instead.
class SomeType {
vector<int> v;
SomeType(size_t x): v(x) {}
};
Using a vector will give you automatic leak protection in the face of an exception and many other benefits over a raw array.
Like already suggested, vector is a good choice for most cases.
Alternatively, if dynamic memory allocation is to be avoided and the maximum size is known at compile time, a custom allocator can be used together with std::vector or a library like the embedded template library can be used.
See here: https://www.etlcpp.com/home.html
Example class:
#include <etl/vector.h>
class TestDummyClass {
public:
TestDummyClass(size_t vectorSize) {
if(vectorSize < MAX_SIZE) {
testVector.resize(vectorSize);
}
}
private:
static constexpr uint8_t MAX_SIZE = 20;
etl::vector<int, MAX_SIZE> testVector;
uint8_t dummyMember = 0;
};
You can't do it in C++ - use a std::vector instead:
#include <vector>
struct A {
std::vector <int> vec;
A( int size ) : vec( size ) {
}
};
Declare your array as a pointer. You can initialize it in the initializer list later through through new.
Better to use vector for unknown size.
You might want to look at this question as well on variable length arrays.
I am trying to create an array of class objects taking an integer argument. I cannot see what is wrong with this simple little code. Could someone help?
#include <fstream>
#include <iostream>
using namespace std;
typedef class Object
{
int var;
public:
Object(const int& varin) : var(varin) {}
} Object;
int main (int argc, char * const argv[])
{
for(int i = 0; i < 10; i++)
{
Object o(i)[100];
}
return 0;
}
In C++ you don't need typedefs for classes and structs. So:
class Object
{
int var;
public:
Object(const int& varin) : var(varin) {}
};
Also, descriptive names are always preferrable, Object is much abused.
int main (int argc, char * const argv[])
{
int var = 1;
Object obj_array[10]; // would work if Object has a trivial ctor
return 0;
}
Otherwise, in your case:
int main (int argc, char * const argv[])
{
int var = 1;
Object init(var);
Object obj_array[10] = { var, ..., var }; // initialize manually
return 0;
}
Though, really you should look for vector
#include <vector>
int main (int argc, char * const argv[])
{
int var = 1;
vector<Object> obj_vector(10, var); // initialize 10 objects with var value
return 0;
}
dirkgently's rundown is fairly accurate representation of arrays of items in C++, but where he is initializing all the items in the array with the same value it looks like you are trying to initialize each with a distinct value.
To answer your question, creating an array of objects that take an int constructor parameter. You can't, objects are created when the array is allocated and in the absence of a trivial constructor your compiler will complain. You can however initialize an array of pointers to your object but you really get a lot more flexibility with a vector so my following examples will use std::vector.
You will need to initialize each of the object separately if you want each Object to have a distinct value, you can do this one of two ways; on the stack, or on the heap. Lets look at on-the-stack first.
Any constructor that take a single argument and is not marked as explicit can be used as an implicit constructor. This means that any place where an object of that type is expected you can instead use an instance of the single parameter type. In this example we create a vector of your Object class and add 100 Objects to it (push_back adds items to a vector), we pass an integer into push_back which implicitly creates an Object passing in the integer.
#include <vector>
int main() {
std::vector<Object> v;
for(int i = 0; i < 100; i++) {
v.push_back(i);
}
}
Or to be explicit about it:
#include <vector>
int main() {
std::vector<Object> v;
for(int i = 0; i < 100; i++) {
v.push_back(Object(i));
}
}
In these examples, all of the Object objects are allocated on the stack in the scope of the for loop, so a copy happens when the object is pushed into the vector. Copying a large number of objects can cause some performance issues especially if your object is expensive to copy.
One way to get around this performance issue is to allocate the objects on the heap and store pointers to the objects in your vector:
#include <vector>
int main() {
std::vector<Object*> v;
for(int i = 0; i < 100; i++) {
v.push_back(new Object(i));
}
for(int i = 0; i < 100; i++) {
delete v[i];
}
}
Since our objects were created on the heap we need to make sure that we delete them to call their deconstructor and, free their memory, this code does that in the second loop.
Manually calling delete has it's own caveats, if you pass these pointers to other code you can quickly loose track of who owns the pointers and who should delete them. An easier way to solve this problem is to use a smart pointer to track the lifetime of the pointer, see either boost::shared_ptr or tr1::shared_ptr which are reference-counted pointers :
#include <vector>
int main() {
std::vector<shared_ptr<Object> > v;
for(int i = 0; i < 100; i++) {
Object* o = new Object(i);
v.push_back(shared_ptr<Object>(o));
}
}
You'll notice that the shared_ptr constructor is explicit, this is done intentionally to make sure that the developer is intentionally stuffing their pointer into the shared pointer. When all references to an object are released the object will automatically be deleted by the shared_ptr, freeing us of the need to worry about it's lifetime.
If you want to stick to arrays, then you must either initialize manually or use the default constructor. However, you can get some control by creating a constructor with a default argument. This will be treated as a default constructor by the compiler. For example, the following code prints out the numbers 0, ..., 9 in order. (However, I'm not sure that the standard dictates that the objects in the array must be constructed in order. It might be implementation dependent, in which case the numbers may appear in arbitrary order.)
#include <iostream>
using namespace std;
struct A {
int _val;
A(int val = initializer()) : _val(val) {}
static int initializer() { static int v = 0; return v++; }
};
int main()
{
A a[10];
for(int i = 0; i < 10; i++)
cout << a[i]._val << endl;
}