Connecting Tech Pros Worldwide Help | Site Map

problem about array of object

Sowen
Guest
 
Posts: n/a
#1: Jul 23 '05
Hi,

I have an object "elem", there are only simple functions inside, like
setName, getName, and three constructors

Now I have another class "Base", need an array of elem to initialize

class Base
{
public:
Base( elem **elements, int count );

protected:
elem **_elements;

}

I don't want to use outside pointer, which means I don't want _elements =
elements, actually, it works well except the problem of security

Therefore, in the Base constructor, I want to allocate a new space for the
array

Base::Base(elem **elements, int count)
{
// _elements = elements; // do not use this

_elements = new elem[count];

for (int i=0; i< count; i++)
{
assert(elements[i]!=NULL);
_elements[i] = new elem(elements[i]->getName());
cout << elements[i]->getName() << endl;
}
}

But, a strange problem is here, there are some elements lose "Name" !

What I mean is when I print elements[i]->getName(), which returns a char,
some of them are missed, become empty

even I move this line before "assert"

If I just set _elements = elements, and then print, nothing will be missed

Now I am really clueless, anyone has an idea?

Thank you very much!

--
Best Regards!
Sowen Cheung
http://com.angGoGo.com
http://www.angGoGo.com
http://biz.angGoGo.com


davidrubin@warpmail.net
Guest
 
Posts: n/a
#2: Jul 23 '05

re: problem about array of object



Sowen wrote:[color=blue]
> Hi,
>
> I have an object "elem", there are only simple functions inside, like[/color]
[color=blue]
> setName, getName, and three constructors
>
> Now I have another class "Base", need an array of elem to initialize
>
> class Base
> {
> public:
> Base( elem **elements, int count );
>
> protected:
> elem **_elements;
>
> }[/color]

How about taking const reference to 'std::vector'?

Base(const std::vector<elem>& elements);

If elem has value-semantics, (in particular a copy constructor), this
works quite well for you: it's easy for clients to create such a
vector, the vector length ('count') comes for free, and memory
management comes for free.
[color=blue]
> I don't want to use outside pointer, which means I don't want[/color]
_elements =[color=blue]
> elements, actually, it works well except the problem of security[/color]

If you have a data member 'std::vector<elem> d_elements' in your 'Base'
class, all you have to do is assign 'd_elements = elements' in your
constructor.
[color=blue]
> Therefore, in the Base constructor, I want to allocate a new space[/color]
for the[color=blue]
> array[/color]

You probably don't "want" to, but your implementation is forcing you
to. Use 'std::vector'.

BTW, the name 'Base' hints at polymorphism, but your class is not a
polymorphic base class. You should consider changing the name.

/david

Sowen
Guest
 
Posts: n/a
#3: Jul 23 '05

re: problem about array of object


Hi,
thanks for your reply

my class is not named as "Base", I just use it for question

and I can't use "vector" in here, otherwise, I won't use array :(

I think even I don't use "vector", this should be done. I just don't
understand why I allocate a new space for a local variable, but the
parameter loses data

--
Best Regards!
Sowen Cheung
http://com.angGoGo.com
http://www.angGoGo.com
http://biz.angGoGo.com
<davidrubin@warpmail.net> wrote in message
news:1110728115.468582.92710@g14g2000cwa.googlegro ups.com...[color=blue]
>
> Sowen wrote:[color=green]
>> Hi,
>>
>> I have an object "elem", there are only simple functions inside, like[/color]
>[color=green]
>> setName, getName, and three constructors
>>
>> Now I have another class "Base", need an array of elem to initialize
>>
>> class Base
>> {
>> public:
>> Base( elem **elements, int count );
>>
>> protected:
>> elem **_elements;
>>
>> }[/color]
>
> How about taking const reference to 'std::vector'?
>
> Base(const std::vector<elem>& elements);
>
> If elem has value-semantics, (in particular a copy constructor), this
> works quite well for you: it's easy for clients to create such a
> vector, the vector length ('count') comes for free, and memory
> management comes for free.
>[color=green]
>> I don't want to use outside pointer, which means I don't want[/color]
> _elements =[color=green]
>> elements, actually, it works well except the problem of security[/color]
>
> If you have a data member 'std::vector<elem> d_elements' in your 'Base'
> class, all you have to do is assign 'd_elements = elements' in your
> constructor.
>[color=green]
>> Therefore, in the Base constructor, I want to allocate a new space[/color]
> for the[color=green]
>> array[/color]
>
> You probably don't "want" to, but your implementation is forcing you
> to. Use 'std::vector'.
>
> BTW, the name 'Base' hints at polymorphism, but your class is not a
> polymorphic base class. You should consider changing the name.
>
> /david
>[/color]


Jeff Schwab
Guest
 
Posts: n/a
#4: Jul 23 '05

re: problem about array of object


Sowen wrote:[color=blue]
> Hi,
>
> I have an object "elem", there are only simple functions inside, like
> setName, getName, and three constructors
>
> Now I have another class "Base", need an array of elem to initialize
>
> class Base
> {
> public:
> Base( elem **elements, int count );
>
> protected:
> elem **_elements;
>
> }[/color]

Missing semicolon (;).
[color=blue]
>
> I don't want to use outside pointer, which means I don't want _elements =
> elements, actually, it works well except the problem of security
>
> Therefore, in the Base constructor, I want to allocate a new space for the
> array
>
> Base::Base(elem **elements, int count)
> {
> // _elements = elements; // do not use this
>
> _elements = new elem[count];[/color]

This should be a compile-time error. You're assigning a pointer-to-elem
to a variable of type pointer-to-pointer-to-elem.
[color=blue]
>
> for (int i=0; i< count; i++)
> {
> assert(elements[i]!=NULL);
> _elements[i] = new elem(elements[i]->getName());
> cout << elements[i]->getName() << endl;
> }
> }
>
> But, a strange problem is here, there are some elements lose "Name" !
>
> What I mean is when I print elements[i]->getName(), which returns a char,
> some of them are missed, become empty
>
> even I move this line before "assert"
>
> If I just set _elements = elements, and then print, nothing will be missed
>
> Now I am really clueless, anyone has an idea?[/color]

Please post real code that demonstrates the problem.
Sowen
Guest
 
Posts: n/a
#5: Jul 23 '05

re: problem about array of object


hi, thx for your reply

pls forget the semicolon mistake

they are real code

elem ** _elements is an object array

I don't understand why you say > This should be a compile-time error.
You're assigning a pointer-to-elem[color=blue]
> to a variable of type pointer-to-pointer-to-elem.[/color]

my program can compile
I can post again

_elements = elements;

Base::Base(elem **elements, int count)
{
// _elements = elements;

*_elements = new elem[count];

cout << "start copying..." << endl;

for (int i=0; i< count; i++)
{
cout << elements[i]->getName() << endl;
assert(elements[i]!=NULL);
_elements[i] = new elem(elements[i]->getName());
}

}

I try different constructors, copy, defaultt, and my own constructor, they
will have the same problem
even I don't assign _elements[i] = new elem(elements[i]->getName());

before this line, if I call "*_elements = new elem[count]; ", the parameter
"elements" has been changed, some of them lost data, that means when I print
elements[i]->getName() , they are empty

--
Best Regards!
Sowen Cheung
http://com.angGoGo.com
http://www.angGoGo.com
http://biz.angGoGo.com
"Jeff Schwab" <jeffrey.schwab@rcn.com> wrote in message
news:1b6dnc6RerHQG6nfRVn-hw@rcn.net...[color=blue]
> Sowen wrote:[color=green]
>> Hi,
>>
>> I have an object "elem", there are only simple functions inside, like
>> setName, getName, and three constructors
>>
>> Now I have another class "Base", need an array of elem to initialize
>>
>> class Base
>> {
>> public:
>> Base( elem **elements, int count );
>>
>> protected:
>> elem **_elements;
>>
>> }[/color]
>
> Missing semicolon (;).
>[color=green]
>>
>> I don't want to use outside pointer, which means I don't want _elements =
>> elements, actually, it works well except the problem of security
>>
>> Therefore, in the Base constructor, I want to allocate a new space for
>> the array
>>
>> Base::Base(elem **elements, int count)
>> {
>> // _elements = elements; // do not use this
>>
>> _elements = new elem[count];[/color]
>
> This should be a compile-time error. You're assigning a pointer-to-elem
> to a variable of type pointer-to-pointer-to-elem.
>[color=green]
>>
>> for (int i=0; i< count; i++)
>> {
>> assert(elements[i]!=NULL);
>> _elements[i] = new elem(elements[i]->getName());
>> cout << elements[i]->getName() << endl;
>> }
>> }
>>
>> But, a strange problem is here, there are some elements lose "Name" !
>>
>> What I mean is when I print elements[i]->getName(), which returns a char,
>> some of them are missed, become empty
>>
>> even I move this line before "assert"
>>
>> If I just set _elements = elements, and then print, nothing will be
>> missed
>>
>> Now I am really clueless, anyone has an idea?[/color]
>
> Please post real code that demonstrates the problem.[/color]


yilled_fred
Guest
 
Posts: n/a
#6: Jul 23 '05

re: problem about array of object


Hi,

Questions:

What is the value of "_elements[i]->getName()" right after

"_elements[i] = new elem(elements[i]->getName());" ?

is it NULL?

-if not, do you make a copy of the return string while building a new
"elem" object? Or do you simply make pointer-to-pointer assignment? In
case of the latter, check to see if the objects in the array
"elements" are not destroyed anywhere else...

-if yes, there may be something wrong with the array argument...

regards,

f.

"Sowen" <sowen@anggogo.com> wrote in message news:<d11mr4$b2b$1@canopus.cc.umanitoba.ca>...[color=blue]
> Hi,
> thanks for your reply
>
> my class is not named as "Base", I just use it for question
>
> and I can't use "vector" in here, otherwise, I won't use array :(
>
> I think even I don't use "vector", this should be done. I just don't
> understand why I allocate a new space for a local variable, but the
> parameter loses data
>
> --
> Best Regards!
> Sowen Cheung
> http://com.angGoGo.com
> http://www.angGoGo.com
> http://biz.angGoGo.com
> <davidrubin@warpmail.net> wrote in message
> news:1110728115.468582.92710@g14g2000cwa.googlegro ups.com...[/color]
Sowen
Guest
 
Posts: n/a
#7: Jul 23 '05

re: problem about array of object




"yilled_fred" <yilledfred@gmail.com> wrote in message
news:4317d8b.0503131109.6af690f4@posting.google.co m...[color=blue]
> Hi,
>
> Questions:
>
> What is the value of "_elements[i]->getName()" right after
>
> "_elements[i] = new elem(elements[i]->getName());" ?
>
> is it NULL?[/color]

some of them (elements) can keep the same, but some of them become empty
char ' '

For example, elements have five elem objects { new elem('a'); new elem('b');
new elem('c'); new elem('d'); new elem('e'); }

they can be copied to _elements, the "copy" means re-allocate a new space
for the new object

but, 'c' disappears, I can only print 'a', 'b' ,'d' , and 'e'


[color=blue]
>
> -if not, do you make a copy of the return string while building a new
> "elem" object? Or do you simply make pointer-to-pointer assignment? In
> case of the latter, check to see if the objects in the array
> "elements" are not destroyed anywhere else...[/color]

no no, I don't simply make pointer-to-pointer assignment

the elem object has only one char, and 'getName()' 'setName(const char c)'
methods, and other three constructors
[color=blue]
>
> -if yes, there may be something wrong with the array argument...
>
> regards,
>
> f.
>
> "Sowen" <sowen@anggogo.com> wrote in message
> news:<d11mr4$b2b$1@canopus.cc.umanitoba.ca>...[color=green]
>> Hi,
>> thanks for your reply
>>
>> my class is not named as "Base", I just use it for question
>>
>> and I can't use "vector" in here, otherwise, I won't use array :(
>>
>> I think even I don't use "vector", this should be done. I just don't
>> understand why I allocate a new space for a local variable, but the
>> parameter loses data
>>
>> --
>> Best Regards!
>> Sowen Cheung
>> http://com.angGoGo.com
>> http://www.angGoGo.com
>> http://biz.angGoGo.com
>> <davidrubin@warpmail.net> wrote in message
>> news:1110728115.468582.92710@g14g2000cwa.googlegro ups.com...[/color][/color]


Andrew Koenig
Guest
 
Posts: n/a
#8: Jul 23 '05

re: problem about array of object


"Sowen" <sowen@anggogo.com> wrote in message
news:d11lnl$9h0$1@canopus.cc.umanitoba.ca...
[color=blue]
> Now I have another class "Base", need an array of elem to initialize
>
> class Base
> {
> public:
> Base( elem **elements, int count );
>
> protected:
> elem **_elements;
>
> }[/color]
[color=blue]
> Base::Base(elem **elements, int count)
> {
> // _elements = elements; // do not use this
>
> _elements = new elem[count];
>
> for (int i=0; i< count; i++)
> {
> assert(elements[i]!=NULL);
> _elements[i] = new elem(elements[i]->getName());
> cout << elements[i]->getName() << endl;
> }
> }[/color]

Your constructor allocates memory? Where is that memory freed?

Is there a destructor you didn't show us?

If so, what are your copy constructor and copy-assignment operators?


Jeff Schwab
Guest
 
Posts: n/a
#9: Jul 23 '05

re: problem about array of object


Sowen wrote:[color=blue]
> hi, thx for your reply
>
> pls forget the semicolon mistake
>
> they are real code
>
> elem ** _elements is an object array
>
> I don't understand why you say > This should be a compile-time error.
> You're assigning a pointer-to-elem
>[color=green]
>>to a variable of type pointer-to-pointer-to-elem.[/color]
>
>
> my program can compile
> I can post again
>
> _elements = elements;
>
> Base::Base(elem **elements, int count)
> {
> // _elements = elements;
>
> *_elements = new elem[count];[/color]

You've added an asterisk ('*') to what you posted earlier, but this is
still not what you want. This ought to compile, but you're likely to
get a run-time error, since you are dereferencing the uninitialized
pointer _elements.
[color=blue]
>
> cout << "start copying..." << endl;
>
> for (int i=0; i< count; i++)
> {
> cout << elements[i]->getName() << endl;
> assert(elements[i]!=NULL);
> _elements[i] = new elem(elements[i]->getName());
> }
>
> }[/color]

My best guess is that your "element" class stores names as char const *,
and does only a shallow copy of the char const* being passed to its
constructor. I think the original, copied elements are going out of
scope, and their destructors are deleting their member char const*.
Some of the names are hanging around in memory for your new elements to
print, while others are getting overwritten. What you see as "space" in
each deleted name is actually a sequnce of unprintable characters that
happen to be followed by a null byte.

Can you use std::string instead of const char* for element names? Then
your implementation could look something like this:

#include <string>

struct Element
{
Element( char const* name ): m_name( name ) { }
char const* getName( ) { return m_name.c_str( ); }
private:
std::string m_name;
};

class Base
{
public:
Base( Element **elements, int count );
virtual ~Base( );

private:
Element **m_elements;
int m_count;
};

#include <cassert>
#include <iostream>
#include <iomanip>

Base::Base( Element **orig, int count ):
m_elements( new Element* [ count ] ),
m_count( count )
{
// m_Elements = Elements; // do not use this

Element** copy = m_elements;
Element** end = orig + count;

for( ; orig < end; ++orig, ++copy )
{
assert( *orig );

*copy = new Element( (*orig)->getName( ) );

std::cout << (*copy)->getName( ) << std::endl;
}
}

Base::~Base( )
{
Element** elem = m_elements;
Element** end = m_elements + m_count;

for( ; elem < end; ++elem )
{
delete *elem;
}

delete [ ] m_elements;
}

int main( )
{
Element hello( "Hello" );
Element world( "World" );
Element* elems[ ] = { &hello, &world };

Base( elems, 2 );
}


Closed Thread