Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

initializing table in class

10 views
Skip to first unread message

jimmij

unread,
Feb 21, 2006, 3:44:11 PM2/21/06
to
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

robert...@gmail.com

unread,
Feb 21, 2006, 4:06:06 PM2/21/06
to

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 */ }

Victor Bazarov

unread,
Feb 21, 2006, 4:07:23 PM2/21/06
to
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

TB

unread,
Feb 21, 2006, 4:10:47 PM2/21/06
to
robert...@gmail.com skrev:

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

jimmij

unread,
Feb 21, 2006, 6:23:11 PM2/21/06
to
Victor Bazarov <v.Aba...@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

Victor Bazarov

unread,
Feb 21, 2006, 9:24:33 PM2/21/06
to

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.

Peter_Julian

unread,
Feb 21, 2006, 11:36:26 PM2/21/06
to

"jimmij" <jim...@jj.jj> wrote in message news:rhwbqx0...@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...

BobR

unread,
Feb 22, 2006, 3:17:20 AM2/22/06
to

jimmij wrote in message ...

#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


Dietmar Kuehl

unread,
Feb 23, 2006, 1:15:41 PM2/23/06
to
robert...@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:dietma...@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence

Dietmar Kuehl

unread,
Feb 23, 2006, 1:20:12 PM2/23/06
to
jimmij wrote:

> Victor Bazarov <v.Aba...@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.

Marcus Kwok

unread,
Feb 23, 2006, 2:52:02 PM2/23/06
to
Dietmar Kuehl <dietma...@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

TB

unread,
Feb 23, 2006, 2:59:12 PM2/23/06
to
Marcus Kwok skrev:

> Dietmar Kuehl <dietma...@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

Dietmar Kuehl

unread,
Feb 23, 2006, 9:16:06 PM2/23/06
to
Marcus Kwok wrote:

> Dietmar Kuehl <dietma...@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.

0 new messages