468,771 Members | 1,600 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,771 developers. It's quick & easy.

initializing table in class

Hi,

Please look at the code bellow

/*******************/
class ctab
{
private:
static const unsigned n=48;

public:
int tab[n];
//int tab[n]={0}; //error, but outside class is good

ctab();
};
/*******************/

I would like to initialize each element of tab to zero.

It can be done in constructor (in a loop or by memset), but the perfect
would be if I will be able to declare and initialize table like in
commented line.

So two questions:
1.Why it is imposible to do that in class, what is a reason for that?
2.What is a best way to solve my problem? In real code I have several
arrays, each has several dimensions, so loops will slow down program and
extend code. Is memset the only choice?

Thanks in advance,
--
jimmij
Feb 21 '06 #1
12 2678

jimmij wrote:
Hi,

Please look at the code bellow

/*******************/
class ctab
{
private:
static const unsigned n=48;

public:
int tab[n];
//int tab[n]={0}; //error, but outside class is good

ctab();
};
2.What is a best way to solve my problem? In real code I have several
arrays, each has several dimensions, so loops will slow down program and
extend code. Is memset the only choice?


Implement ctab() as so:

ctab::ctab() : tab(0) { /* code */ }

Feb 21 '06 #2
jimmij wrote:
Please look at the code bellow

/*******************/
class ctab
{
private:
static const unsigned n=48;

public:
int tab[n];
//int tab[n]={0}; //error, but outside class is good

ctab();
};
/*******************/

I would like to initialize each element of tab to zero.

It can be done in constructor (in a loop or by memset), but the perfect
would be if I will be able to declare and initialize table like in
commented line.
You cannot. The language does not allow that.
So two questions:
1.Why it is imposible to do that in class, what is a reason for that?
Because initialisation of non-static members is the task for the
constructor. It's done in the initialiser list of the constructor for
all members except arrays. For arrays you need to do it inside the
constructor's body.
2.What is a best way to solve my problem?
Use memset.
In real code I have several
arrays, each has several dimensions, so loops will slow down program and
extend code. Is memset the only choice?


You could also have a static instance of your file with all those arrays
initialised (to zero), and construct your objects by copying them from the
static instance. Under the covers the compiler will still probably make
a call to memcpy (or memset).

V
--
Please remove capital As from my address when replying by mail
Feb 21 '06 #3
TB
ro**********@gmail.com skrev:
jimmij wrote:
Hi,

Please look at the code bellow

/*******************/
class ctab
{
private:
static const unsigned n=48;

public:
int tab[n];
//int tab[n]={0}; //error, but outside class is good

ctab();
};
2.What is a best way to solve my problem? In real code I have several
arrays, each has several dimensions, so loops will slow down program and
extend code. Is memset the only choice?


Implement ctab() as so:

ctab::ctab() : tab(0) { /* code */ }


class A {
int a[40];
A() : a(0) {}
};

Comeau C/C++ 4.3.3 (Aug 6 2003 15:13:37) for ONLINE_EVALUATION_BETA1
Copyright 1988-2003 Comeau Computing. All rights reserved.
MODE:strict errors C++

"ComeauTest.c", line 3: error: only "()" is allowed as initializer for
array member
"A::a"
A() : a(0) {}
^

1 error detected in the compilation of "ComeauTest.c".

--
TB @ SWEDEN
Feb 21 '06 #4
Victor Bazarov <v.********@comAcast.net> writes:
2.What is a best way to solve my problem?


Use memset.


I afraid of memset and trying to avoid it because afaik it is not save in
other then int (e.g. float) type. I consider std:vector instead of
array. Can it be a solution?

--
jimmij
Feb 21 '06 #5
jimmij wrote:
Victor Bazarov <v.********@comAcast.net> writes:
2.What is a best way to solve my problem?


Use memset.


I afraid of memset and trying to avoid it because afaik it is not
save in other then int (e.g. float) type. I consider std:vector
instead of array. Can it be a solution?


Well.. I am not the one to help you overcome your fears. You have to
deal with them on your own. However, 'memset' is safe with 'float'.
It's not necessarily safe with arrays of pointers, you'd need to use
'generate' or 'generate_n' for them. It is definitely not good for
arrays of objects, but those must have their own constructors.

V
--
Please remove capital As from my address when replying by mail
Feb 22 '06 #6

"jimmij" <ji****@jj.jj> wrote in message news:rh*************@jj.jj...
| Hi,
|
| Please look at the code bellow
|
| /*******************/
| class ctab
| {
| private:
| static const unsigned n=48;
|
| public:
| int tab[n];
| //int tab[n]={0}; //error, but outside class is good
|
| ctab();
| };
| /*******************/
|
| I would like to initialize each element of tab to zero.

Then you are using the wrong container. Primitive arrays must be valid
at compile time with a known fixed size. All the features you seek and
more have already been invented. Here is a simple class composed of a
templated std:vector.

The container can be initialized with any size with any value using any
type and grows as required dynamically. I could have provided a
operator[], push_back(...) and pop_back() member functions as an
interface to the private std::vector.

#include <iostream>
#include <ostream>
#include <algorithm> // for std::copy
#include <iterator> // for std::ostream_iterator
#include <vector>

template< class T >
class Container
{
std::vector< T > v;
public:
Container() : v() { }
Container(unsigned sz, T t) : v(sz, t) { }
~Container() { }

friend std::ostream& operator<<(std::ostream&, Container< T >&);
};

/* overload operator<< */
template< class T >
std::ostream& operator<<(std::ostream& os, Container< T >& cont)
{
os << "size = " << cont.v.size();
os << "\n";
std::copy( cont.v.begin(),
cont.v.end(),
std::ostream_iterator<T>(os, " ") );
os << std::endl;
return os;
}

int main()
{
// ie: type integer, 10 elements, all initialized to 0
Container<int> container(10, 0);

std::cout << container; // done !

return 0;
}

/*
size = 10
0 0 0 0 0 0 0 0 0 0
*/

And if i need a container of std::string, long, char, or for that matter
*any* user-type i need not modify a single line of class code (except
for perhaps a #include ).

Try doing that with an array. By the way, its entirely pheasable to
complete the project with just a primitive array. Its just that the
amount of extra work and extra code required to duplicate the features
here would be reinventing the wheel.

Additionally, a std::vector is the simplest of the dynamic STL
containers available. Others include std::list, std::queue, std::deque,
etc...

|
| It can be done in constructor (in a loop or by memset), but the
perfect
| would be if I will be able to declare and initialize table like in
| commented line.
|
| So two questions:
| 1.Why it is imposible to do that in class, what is a reason for that?
| 2.What is a best way to solve my problem? In real code I have several
| arrays, each has several dimensions, so loops will slow down program
and
| extend code. Is memset the only choice?
|
| Thanks in advance,
| --
| jimmij
Feb 22 '06 #7

jimmij wrote in message ...
Victor Bazarov <v.********@comAcast.net> writes:
2.What is a best way to solve my problem?


Use memset.


I afraid of memset and trying to avoid it because afaik it is not save in
other then int (e.g. float) type. I consider std:vector instead of
array. Can it be a solution?
--
jimmij


#include <iostream>
#include <ostream>
#include <vector>

class VecArray{
std::vector<double> vDbl;
public:
VecArray(): vDbl(4, 077.14150){}
double GetNum(size_t indx){
if( indx > vDbl.size()-1){ return 0.0;}
return vDbl.at(indx);
}
size_t GetSize(){ return vDbl.size();}
};

int main(){
VecArray Varr;
size_t vaSize = Varr.GetSize();
for(size_t i(0); i < vaSize; ++i){
std::cout<<" Varr.GetNum( "<<i<<" )="<<Varr.GetNum( i )<<std::endl;
} //for(i)
return 0;
} // main() end

--
Bob R
POVrookie
Feb 22 '06 #8
ro**********@gmail.com wrote:
Implement ctab() as so:

ctab::ctab() : tab(0) { /* code */ }


Nope. This is illegal syntax for an array. However, the following
*is* legal and does what the original author intended, i.e. it
default initializes every element which in the case of built-in
types means zero initialization:

ctab::ctab(): tab() { /* other initialization */ }

It is worth noting that all POD struct types can be initialized
this way and go uninitialized if neither default- nor
copy-initialization is used.
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
Feb 23 '06 #9
jimmij wrote:
Victor Bazarov <v.********@comAcast.net> writes:
2.What is a best way to solve my problem?
Use memset.


I afraid of memset


This is the wrong attitude towards programming: you need to use
what is in order. If this requires "scary" interfaces, this is
what it requires. Of course, the given situation does not require
'memset()' nor use of a 'std::vector': you can just default-initialize
the array member which will initialize all built-in types with zero:

ctab::ctab(): tab() {}

It is quite interesting that this simple solution does elide some
of the more knowledgable authors in this forum...
and trying to avoid it because afaik it is not save in
other then int (e.g. float) type. I consider std:vector instead of
array. Can it be a solution?


'std::vector' might be a solution but it might as well be overkill.
It is hard to tell whether your class requires flexibility in the
number of elements but if it does, 'std::vector' is probably the
better solution. If it does not, however, a built-in array is likely
to be the most appropriate solution.
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
Feb 23 '06 #10
Dietmar Kuehl <di***********@yahoo.com> wrote:
you can just default-initialize
the array member which will initialize all built-in types with zero:

ctab::ctab(): tab() {}

It is quite interesting that this simple solution does elide some
of the more knowledgable authors in this forum...


So then does this mean that VC++ .NET 2003 (7.1) is not compliant in
this regard, or did I make a stupid mistake in my program?

#include <iostream>
#include <iterator>
#include <cstdlib>

const std::size_t Size = 4;

class UnInit {
int ai[Size];
bool bi[Size];
public:
friend std::ostream& operator<<(std::ostream& o, const UnInit& u);
};

std::ostream&
operator<<(std::ostream& o, const UnInit& u)
{
o << "UnInit:\n";
o << "ai = {";
std::copy(u.ai, u.ai + Size, std::ostream_iterator<int>(o, ", "));
o << "\b\b}\n";

o << "bi = {";
std::copy(u.bi, u.bi + Size, std::ostream_iterator<bool>(o, ", "));
o << "\b\b}";

return o;
}

class Init {
int ai[Size];
bool bi[Size];
public:
Init() : ai(), bi() { }
friend std::ostream& operator<<(std::ostream& o, const Init& i);
};

std::ostream&
operator<<(std::ostream& o, const Init& in)
{
o << "Init:\n";
o << "ai = {";
std::copy(in.ai, in.ai + Size, std::ostream_iterator<int>(o, ", "));
o << "\b\b}\n";

o << "bi = {";
std::copy(in.bi, in.bi + Size, std::ostream_iterator<bool>(o, ", "));
o << "\b\b}";

return o;
}

int main()
{
UnInit u;
Init i;

std::cout << u << "\n\n";
std::cout << i << '\n';

return 0;
}
Output:

UnInit:
ai = {4225084, 4260716, 4260606, 4260716}
bi = {160, 103, 64, 0}

Init:
ai = {4225084, 4260716, 4260606, 4260716}
bi = {160, 103, 64, 0}

--
Marcus Kwok
Feb 23 '06 #11
TB
Marcus Kwok skrev:
Dietmar Kuehl <di***********@yahoo.com> wrote:
you can just default-initialize
the array member which will initialize all built-in types with zero:

ctab::ctab(): tab() {}

It is quite interesting that this simple solution does elide some
of the more knowledgable authors in this forum...
So then does this mean that VC++ .NET 2003 (7.1) is not compliant in
this regard, or did I make a stupid mistake in my program?


<snip>

Output:

UnInit:
ai = {4225084, 4260716, 4260606, 4260716}
bi = {160, 103, 64, 0}

Init:
ai = {4225084, 4260716, 4260606, 4260716}
bi = {160, 103, 64, 0}


Borland doesn't default-initialize either.

--
TB @ SWEDEN
Feb 23 '06 #12
Marcus Kwok wrote:
Dietmar Kuehl <di***********@yahoo.com> wrote:
you can just default-initialize
the array member which will initialize all built-in types with zero:

ctab::ctab(): tab() {}

It is quite interesting that this simple solution does elide some
of the more knowledgable authors in this forum...


So then does this mean that VC++ .NET 2003 (7.1) is not compliant in
this regard, or did I make a stupid mistake in my program?


Yes, I think this an appropriate conclusion! Actually, there is
another thing in which it is non-conforming: Boolean values shall
be output as either '0' for 'false' or '1' for 'true'. Arriving
at values different than these is also not permitted. Of course,
it could be argued that the program has undefined behavior beginning
at the point where uninitialized memory is first accessed: maybe it
would be worth swapping the two output statements to avoid this
situation, too.

To back-up my claim that the above constructor should indeed result
in proper initialization, here are the relevant quotes from the
standard:

8.5 (dcl.init) paragraph 5:

To zero-initialize storage for an object of type T means:
- if T is a scalar type (3.9), the storage is set to the value of 0
(zero) converted to T
[...]
To default-initialize an object of type T means:
- if T is a non-POD class type (clause 9), the default constructor
for T is called (and the initialization is ill-formed if T has no
accessible default constructor);
- if T is an array type, each element is default-initialized;
- otherwise, the storage for the object is zero-initialized
12.6.2 (class.base.init) paragraph 3:

[...] The semantics of a mem-initializer are as follows:
- if the expression-list of the mem-initializer is omitted, the base
class or member subobject is default-initialized (see 8.5).
[...]

I think there was some clean-up in the TC for section 8.5 which
explicitly introduced value-initialization but I don't think that
the overall effect of requiring zero initialization of members is
affected by this change.

BTW, the output resulting from using g++ on a Linux platform is

UnInit:
ai = {1076252660, 134515504, 0, 1076252660}
bi = {0, 0, 0, 0}

Init:
ai = {0, 0, 0, 0}
bi = {0, 0, 0, 0}

which is roughly the same as for icc (Intel's C++ compiler based
on the EDG front-end), except that the values in the uninitialized
values of 'ai' are different.
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
Feb 24 '06 #13

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

50 posts views Thread by Dan Perl | last post: by
17 posts views Thread by Calle Pettersson | last post: by
6 posts views Thread by alacrite | last post: by
2 posts views Thread by eriwik | last post: by
1 post views Thread by subramanian | last post: by
8 posts views Thread by John | last post: by
2 posts views Thread by Brad Pears | last post: by
3 posts views Thread by Reckoner | last post: by
13 posts views Thread by WaterWalk | last post: by
1 post views Thread by CARIGAR | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.