In C++ how initialize all values of a member array for a class?
#define MAX_MATRIX 20
Class Matrix {
public:
Matrix(); //constructor
protected:
int n[MAX_MATRIX]; // note cannot do = { 0} or w/e here
};
Matrix::Matrix()
{
// how to set all n to -1?
}
You can use std::fill:
std::fill(begin(n), end(n), -1);
(These begin and end functions can be found in namespace std in C++11, or you can easily implement them yourself in C++03)
This was a glaring shortcoming of C++03. In C++11 this has been fixed, and you can now initialize everything, including arrays:
class Matrix
{
public:
Matrix() : n { } { }
protected:
static const unsigned int MAX_MATRIX = 20;
int n[MAX_MATRIX];
};
(The nasty preprocessor macro is also not needed in C++.)
In C++03, you simply cannot initialize an array member, but you can set it to something meaningful in the constructor body, e.g. via std::fill(n, n + MAX_MATRIX, 0);.
(Of course it would be a lot nicer to say std::array<int, MAX_MATRIX> n;.)
There's a type for this:
class Matrix {
public:
Matrix() : n() { n.fill(-1); }
protected:
std::array<int, 20> n;
};
for (unsigned i = 0; i < MAX_MATRIX; ++i) n[i] = -1;
#include <cstring>
...
Matrix::Matrix()
{
static bool init=false;
static int n_init[MAX_MATRIX];
if (!init){
for(int i=0; i<MAX_MATRIX; i++){
n_init[i] = -1;
}
init = true;
}
memcpy(n,n_init,MAX_MATRIX*sizeof(int));
}
The array n_init is initialized exactly once and stored in memory, then all subsequent constructions are a quick memory copy with no loops. You should not see much decrease in speed if you increase the size of MAX_MATRIX as you would when looping through the index, particularly if you are calling Matrix::Matrix() many times.
Related
I have a class that needs to use some big arrays, initialized via some complex functions, that will be the same for every instance and will only be read after initialization.
I searched on SO and found some answers on initializing static arrays like this:
char A::a[6] = {1,2,3,4,5,6};
But in my case I need to calculate the arrays at runtime via some function.
(How) can I do it?
Re
” will be the same for every instance and will only be read after initialization
Producing a value is the job of a function.
Just define a function that returns the data you need.
You can use it to initialize a static data member (or whatever). For a header only module, if that's relevant, you will need to employ solution to the "inline data" problem, e.g. a Meyers' singleton (a function that returns a reference to a local static variable). Like this:
#include <vector>
namespace my {
using std::vector;
inline
auto squares()
-> vector<int>
{
vector<int> result;
for( int i = 1; i <= 12; ++i ) { result.push_back( i*i ); }
return result;
}
class A
{
private:
static
auto a()
-> const vector<int>&
{
static const vector<int> the_values = squares();
return the_values;
}
public:
A(){}
};
} // namespace my
You can't use {} sintaxis in execution time, you can use a method:
class A
{
static vector<char> a;
//...
public:
static void initStatic();
}
void A::initStatic()
{
a.resize( /*put the size here... */);
for (auto& x : a)
x = //something...
}
vector reference: http://en.cppreference.com/w/cpp/container/vector
If you aren't using vectors, this works. The reason I let A::initialize do the work, rather than just calling one of these externally defined functions, is that we can and should expect the data member a to be private.
//Declare a function pointer type, so you can pass it into A's
//an initialization function takes in the array and its size
typedef void (*initFunction) (char A[], int arraySize);
//see http://www.cprogramming.com/tutorial/function-pointers.html
// for more on function pointers
class A
{
public:
void initialize (initFunction myInitFunction);
...
private:
char a[ARRAYSIZE];
};
void A::initialize (initFunction myInitFunction)
{
(*myInitFunction) (a, ARRAYSIZE);
}
...
A myA;
myA.initialize (yourArrayInitializingFunction);
Or maybe your initialization functions don't take in arrays and initialize them, but return arrays:
class A
{
public:
void initialize (const char* aInit);
...
};
void A::initialize (const char* aInit)
{
for (int i = 0; i < ARRAYSIZE: ++i)
a[i] = aInit[i];
}
...
A myA;
myA.initialize (yourArrayReturningFunction ());
If you're using vectors, code is simpler:
class A
{
public:
void initialize (const vector<char>& aInit) { a = aInit; }
...
private:
vector<char> a;
};
My suggestion:
Instead of using a static member variable, use a static member function to provide access to the array.
In the static member function, create a static function variable that can be populated the first time it is needed.
Here's what I am thinking of:
char* A::getArray()
{
static char a[6] = {0};
static bool inited = false;
if ( !inited )
{
// Initialize the array elements
a[0] = ... ;
...
a[5] = ... ;
inited = true;
}
return a;
}
Beginner in C++
I have a class, say
class A
{
public:
int N;
double .....
};
But I would like the ..... to define a matrix of size depending on N. In case that changes the approach, it is a non-identical function of N and not just N itself, say N^3+1.
In case that is the approach, I have never written a constructor of an object in C++. Therefore, if this is the approach could you please give some detail. I don't understand how it might work. When the class is instanciated, maybe the property N hasn't been even initialized.
I am not clear how to get a matrix or array (I am still not clear of the basic data types of C++) of size determined in execution.
Edit: The value of N is determined later in the code. It is something like:
A InstanceOfA; //The variable InstanceOfA is declared of type A.
...
Some other stuff happens, e.g. other properties of InstanceOfA are initialized
and some of the functions are used. And then:
...
A.setN(4);
I didn't understand from the answer below. Would I need to do
A InstanceOfA(4);
?
You can use std::vector
class A
{
public:
int N; // you should use int for size
double std::vector<std::vector<double>> matrix; //define the matrix
//initialize it in the constructor
A( int size ):N(size), matrix(size*3+3)// or you can use any expression that evaluates an integral value
{
//you can initialize the values in matrix here
}
};
Note
the expression matrix(size*3+3) initializes the matrix such that, there are size*3+3 rows, the number of columns in each row are not specified yet. You can also specify column sizes in the constructor like
for( int i=0;i< N*3+3; ++i) //for each row
{
matrix[i].resize(N*2);// resize each col to hold N*2 cells,
}
Edit
As per the modification in question, you can then leave the constructor empty (or initialize any other members), and provide a setSize method in class A, which will later initialize the size.
void setSize(int size){
N= size;
matrix.resize( size*3+3);
for( int i=0;i< N*3+3; ++i) //for each row
{
matrix[i].resize(N*2);// resize each col to hold N*2 cells,
}
}
Then you can use it like:
A instanceOfA;
//other code
//
instanceOfA.setSize(N);
You can use an std::vector<std::vector<double>> to capture the matrix. Also, change the type of N to int.
class A
{
public:
int N;
std::vector<std::vector<double>> matrix;
};
Define a constructor and initialize the data in the constructor.
class A
{
public:
A(int n) : N(n)
{
int matrixSize = N*N*N+1;
for (int i = 0; i < matrixSize; ++i )
{
matrix.push_back(std::vecotr<double>(matrixSize));
}
}
double N;
std::vector<std::vector<double>> matrix;
};
One possible way is to do it with a pointer. If you only allocate your array in constructor and its size will not change during the lifetime of your object, that could be done in this way:
class A
{
public:
double N;
double* arr;
A(double aN):N(aN)
{ arr = new double[3*N+1]; // allocate your array in constructor
... // do whatever else you need to initialize your object
}
...
~A() { delete[] arr;} // free it in destructor
...
}
See also the tutorial on Dynamic Memory.
You will then instantiate your class in one of two ways:
A a(aN);
// this object will be automatically destroyed when it gets out of scope, for example at the end of the function where it was created
A* a = new A(aN);
// this object will have to be deleted by yourself when it's no longer needed:
...
delete a;
If you don't know N at the moment when you create your object, you can postpone the allocation :
class A
{
public:
double N;
double* arr = NULL;
A() { ... } // do whatever you need in your constructor
setN(double aN)
{
N = aN;
arr = new double[3*N+1]; // allocate your array
}
...
~A() { if(arr) delete[] arr;} // free your array in destructor if needed
...
}
then you can call your object as:
A a;
I come from Java and Ruby so I have a hard time coding simple stuff in c++, c++ being harder to tame...
I want to initialize an array in the class constructor with predefined values that can be accessed by all methods in the class. Yeah, basic stuff.
In other words, I want to do something like this:
Box.h
class SomeClass
{
public:
SomeClass(int something);
SomeMethod();
DoSomething(int thing);
protected:
int _something;
int[] arr;
};
Box.cpp
SomeClass::SomeClass(int something) : something(_something)
{
arr ={16,2,45,65,45};
for (int x = 0; x < 5; x++)
arr[i] = arr[i] * _something;
}
SomeClass::SomeMethod(){
for (int x = 0; x < 5; x++)
DoSomething(arr[i]);
}
SomeClass::DoSomething(int thing){
//whatever
}
How?
#include <iostream>
//#include <initializer_list>
#include <array>
#include <algorithm>
class foo
{
public:
foo() : values({{16,2,45,65,45}})
{
// I left the below commented out in case you want to research more and use other kinds of types for doing it.
//std::initializer_list<int> list = {16,2,45,65,45};
//std::copy(std::begin(list), std::end(list), std::begin(values));
}
void print()
{
std::for_each(std::begin(values), std::end(values),
[](int v) { std::cout << v << ' '; });
}
private:
static const int SIZE = 5;
std::array<int, 5> values;
};
int main()
{
foo fooInstance;
fooInstance.print();
return 0;
}
The above is the best that I could do in a short period of time. I tested with the following compiler. You could use that as a starting point and see if you can learn other ways of doing it. Algorithms such as generate can also be used with lamda expressions in order to generate a controlled set of values (as opposed to a hard coded list as in our examples).
http://www.compileonline.com/compile_cpp11_online.php
You have options for initializing array data members, and two types or array you can use:
Using a C-style array,
struct Foo
{
int a[5] = {1,2,3,4,5}; // initialization at point of declaration
};
struct Bar
{
int a[5];
Bar() : a{1,2,3,4,5} {} // initialization in constructor initialization list
};
Or using an std::array:
struct Foo
{
std::array<int,5> a = {{1,2,3,4,5}}; // initialization at point of declaration
};
struct Bar
{
std::array<int,5> a;
Bar() : a{{1,2,3,4,5}} {} // initialization in constructor initialization list
};
If you can use C++11, there is support for uniform initialization which allows you to assign brace-enclosed lists of values in more contexts than the special case in C.
I'm writing a class for the Arduino. It's been going well so far, but I'm sort of stuck now...
I have declared an int array in my class
class myClass
{
public: MyClass(int size);
private:
int _intArray[];
};
When I initialize the class MyClass myClass1(5) I need the array to look like this {0,0,0,0,0}.
My question: what do I need to do so that the array contains 'size' amount of zeros?
MyClass::MyClass(int size)
{
//what goes here to dynamically initialize the array
for(int i=0; i < size; i++) _intArray[i] = 0;
}
Edit: Following up on various replies below, Arduino does not include the standard library so unfortunately std::vector is not an option
Your code as I'm writing this:
class myClass
{
public: MyClass(int size);
private:
int _intArray[];
};
The declaration of _intArray is not valid C++: a raw array needs to have a size specified at compile time.
You can instead instead use a std::vector:
class myClass
{
public:
MyClass( int size )
: intArray_( size ) // Vector of given size with zero-valued elements.
{}
private:
std::vector<int> intArray_;
};
Note 1: some compilers may allow your original code as a language extension, in order to support the "struct hack" (that's a C technique that's not necessary in C++).
Note 2: I've changed the name of your member. Generally underscores at the start of names can be problematic because they may conflict with names from the C++ implementation.
Cheers & hth.,
You should use a std::vector.
class myCLass {
public:
myClass(int size)
: intarray(size) {
for(int i = 0; i < size; i++) intarray[i] = 0;
}
private:
std::vector<int> intarray;
};
You should really use vectors as others have suggested. A work-around could be as shown (in case you do not want to use memcpy or a loop).
This would be useful if you have a really huge array. Note that it would add a level of indirection to access the array.
class myClass
{
public:
myClass(){
mt = T(); // value initialize.
}
private:
struct T{
int _intArray[10];
} mt;
};
int main(){
myClass m;
}
I'll try the following:
class myClass
{
public:
MyClass(int size);
~MyClass();
private:
int* _intArray;
};
MyClass::MyClass(int size) {
_intArray = new int[size];
for (int i=0; i<size; ++i) _intArray[i] =0; // or use memset ...
}
MyClass::~MyClass() {
delete[] _intArray;
}
Or, even better, use a STL vector instead ...
you can use another hack basing on a string value and then populate a limited size array
check this :
https://github.com/Riadam/ViewPort-Array-Shifter-for-Arduino-Uno.git
I have the following class in C++:
class a {
const int b[2];
// other stuff follows
// and here's the constructor
a(void);
}
The question is, how do I initialize b in the initialization list, given that I can't initialize it inside the body of the function of the constructor, because b is const?
This doesn't work:
a::a(void) :
b([2,3])
{
// other initialization stuff
}
Edit: The case in point is when I can have different values for b for different instances, but the values are known to be constant for the lifetime of the instance.
With C++11 the answer to this question has now changed and you can in fact do:
struct a {
const int b[2];
// other bits follow
// and here's the constructor
a();
};
a::a() :
b{2,3}
{
// other constructor work
}
int main() {
a a;
}
Like the others said, ISO C++ doesn't support that. But you can workaround it. Just use std::vector instead.
int* a = new int[N];
// fill a
class C {
const std::vector<int> v;
public:
C():v(a, a+N) {}
};
It is not possible in the current standard. I believe you'll be able to do this in C++0x using initializer lists (see A Brief Look at C++0x, by Bjarne Stroustrup, for more information about initializer lists and other nice C++0x features).
std::vector uses the heap. Geez, what a waste that would be just for the sake of a const sanity-check. The point of std::vector is dynamic growth at run-time, not any old syntax checking that should be done at compile-time. If you're not going to grow then create a class to wrap a normal array.
#include <stdio.h>
template <class Type, size_t MaxLength>
class ConstFixedSizeArrayFiller {
private:
size_t length;
public:
ConstFixedSizeArrayFiller() : length(0) {
}
virtual ~ConstFixedSizeArrayFiller() {
}
virtual void Fill(Type *array) = 0;
protected:
void add_element(Type *array, const Type & element)
{
if(length >= MaxLength) {
// todo: throw more appropriate out-of-bounds exception
throw 0;
}
array[length] = element;
length++;
}
};
template <class Type, size_t Length>
class ConstFixedSizeArray {
private:
Type array[Length];
public:
explicit ConstFixedSizeArray(
ConstFixedSizeArrayFiller<Type, Length> & filler
) {
filler.Fill(array);
}
const Type *Array() const {
return array;
}
size_t ArrayLength() const {
return Length;
}
};
class a {
private:
class b_filler : public ConstFixedSizeArrayFiller<int, 2> {
public:
virtual ~b_filler() {
}
virtual void Fill(int *array) {
add_element(array, 87);
add_element(array, 96);
}
};
const ConstFixedSizeArray<int, 2> b;
public:
a(void) : b(b_filler()) {
}
void print_items() {
size_t i;
for(i = 0; i < b.ArrayLength(); i++)
{
printf("%d\n", b.Array()[i]);
}
}
};
int main()
{
a x;
x.print_items();
return 0;
}
ConstFixedSizeArrayFiller and ConstFixedSizeArray are reusable.
The first allows run-time bounds checking while initializing the array (same as a vector might), which can later become const after this initialization.
The second allows the array to be allocated inside another object, which could be on the heap or simply the stack if that's where the object is. There's no waste of time allocating from the heap. It also performs compile-time const checking on the array.
b_filler is a tiny private class to provide the initialization values. The size of the array is checked at compile-time with the template arguments, so there's no chance of going out of bounds.
I'm sure there are more exotic ways to modify this. This is an initial stab. I think you can pretty much make up for any of the compiler's shortcoming with classes.
ISO standard C++ doesn't let you do this. If it did, the syntax would probably be:
a::a(void) :
b({2,3})
{
// other initialization stuff
}
Or something along those lines. From your question it actually sounds like what you want is a constant class (aka static) member that is the array. C++ does let you do this. Like so:
#include <iostream>
class A
{
public:
A();
static const int a[2];
};
const int A::a[2] = {0, 1};
A::A()
{
}
int main (int argc, char * const argv[])
{
std::cout << "A::a => " << A::a[0] << ", " << A::a[1] << "\n";
return 0;
}
The output being:
A::a => 0, 1
Now of course since this is a static class member it is the same for every instance of class A. If that is not what you want, ie you want each instance of A to have different element values in the array a then you're making the mistake of trying to make the array const to begin with. You should just be doing this:
#include <iostream>
class A
{
public:
A();
int a[2];
};
A::A()
{
a[0] = 9; // or some calculation
a[1] = 10; // or some calculation
}
int main (int argc, char * const argv[])
{
A v;
std::cout << "v.a => " << v.a[0] << ", " << v.a[1] << "\n";
return 0;
}
Where I've a constant array, it's always been done as static. If you can accept that, this code should compile and run.
#include <stdio.h>
#include <stdlib.h>
class a {
static const int b[2];
public:
a(void) {
for(int i = 0; i < 2; i++) {
printf("b[%d] = [%d]\n", i, b[i]);
}
}
};
const int a::b[2] = { 4, 2 };
int main(int argc, char **argv)
{
a foo;
return 0;
}
You can't do that from the initialization list,
Have a look at this:
http://www.cprogramming.com/tutorial/initialization-lists-c++.html
:)
A solution without using the heap with std::vector is to use boost::array, though you can't initialize array members directly in the constructor.
#include <boost/array.hpp>
const boost::array<int, 2> aa={ { 2, 3} };
class A {
const boost::array<int, 2> b;
A():b(aa){};
};
How about emulating a const array via an accessor function? It's non-static (as you requested), and it doesn't require stl or any other library:
class a {
int privateB[2];
public:
a(int b0,b1) { privateB[0]=b0; privateB[1]=b1; }
int b(const int idx) { return privateB[idx]; }
}
Because a::privateB is private, it is effectively constant outside a::, and you can access it similar to an array, e.g.
a aobj(2,3); // initialize "constant array" b[]
n = aobj.b(1); // read b[1] (write impossible from here)
If you are willing to use a pair of classes, you could additionally protect privateB from member functions. This could be done by inheriting a; but I think I prefer John Harrison's comp.lang.c++ post using a const class.
interestingly, in C# you have the keyword const that translates to C++'s static const, as opposed to readonly which can be only set at constructors and initializations, even by non-constants, ex:
readonly DateTime a = DateTime.Now;
I agree, if you have a const pre-defined array you might as well make it static.
At that point you can use this interesting syntax:
//in header file
class a{
static const int SIZE;
static const char array[][10];
};
//in cpp file:
const int a::SIZE = 5;
const char array[SIZE][10] = {"hello", "cruel","world","goodbye", "!"};
however, I did not find a way around the constant '10'. The reason is clear though, it needs it to know how to perform accessing to the array. A possible alternative is to use #define, but I dislike that method and I #undef at the end of the header, with a comment to edit there at CPP as well in case if a change.