problem about array of object

S

Sowen

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!=NULL);
_elements = new elem(elements->getName());
cout << elements->getName() << endl;
}
}

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

What I mean is when I print elements->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
 
D

davidrubin

Sowen said:
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;

}

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.
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

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.
Therefore, in the Base constructor, I want to allocate a new space for the
array

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
 
J

Jeff Schwab

Sowen said:
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;

}

Missing semicolon (;).
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];

This should be a compile-time error. You're assigning a pointer-to-elem
to a variable of type pointer-to-pointer-to-elem.
for (int i=0; i< count; i++)
{
assert(elements!=NULL);
_elements = new elem(elements->getName());
cout << elements->getName() << endl;
}
}

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

What I mean is when I print elements->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?


Please post real code that demonstrates the problem.
 
S

Sowen

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
to a variable of type pointer-to-pointer-to-elem.

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->getName() << endl;
assert(elements!=NULL);
_elements = new elem(elements->getName());
}

}

I try different constructors, copy, defaultt, and my own constructor, they
will have the same problem
even I don't assign _elements = new elem(elements->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->getName() , they are empty

--
Best Regards!
Sowen Cheung
http://com.angGoGo.com
http://www.angGoGo.com
http://biz.angGoGo.com
Jeff Schwab said:
Sowen said:
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;

}

Missing semicolon (;).
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];

This should be a compile-time error. You're assigning a pointer-to-elem
to a variable of type pointer-to-pointer-to-elem.
for (int i=0; i< count; i++)
{
assert(elements!=NULL);
_elements = new elem(elements->getName());
cout << elements->getName() << endl;
}
}

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

What I mean is when I print elements->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?


Please post real code that demonstrates the problem.
 
Y

yilled_fred

Hi,

Questions:

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

"_elements = new elem(elements->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.
 
S

Sowen

yilled_fred said:
Hi,

Questions:

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

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

is it NULL?


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'


-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...

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
 
A

Andrew Koenig

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

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

protected:
elem **_elements;

}
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!=NULL);
_elements = new elem(elements->getName());
cout << elements->getName() << endl;
}
}


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?
 
J

Jeff Schwab

Sowen said:
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
to a variable of type pointer-to-pointer-to-elem.


my program can compile
I can post again

_elements = elements;

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

*_elements = new elem[count];

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.
cout << "start copying..." << endl;

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

}


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 );
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,139
Latest member
JamaalCald
Top