Board index » cppbuilder » return struct

return struct


2005-03-01 08:25:12 PM
cppbuilder62
Hi All,
I have a "typedef struct X". I have created a function that returns the
typedef struct X, but the values returned are all initialized. Do I have to
create a copy function for the structure?
Thanks
Simeon
 
 

Re:return struct

Simeon wrote:
Quote
I have a "typedef struct X". I have created a function that returns
the typedef struct X, but the values returned are all initialized. Do
I have to create a copy function for the structure?
Well firstly you don't need the 'typedef' prefix in mosts cases these
days.
But on to your main question:It depends on the structure members. If
they are all POD "Plain Old Data" then no. POD is simple types like
'int' and 'float' and the compiler can generate code to copy those
without any problem.
Where it gets more complicated is if you have pointers. These will
still be copied correctly but the result is two pointers pointing to
the same thing. That opens the door for unanticipated side-effects and
raises a question about who owns what they point to and who should
deallocate it.
An example of very questionable ownership:
struct TWibble
{
char * aString;
};
void wibbler()
{
TWibble wibble;
wibble.aString=new char[ 6 ];
strcpy( wibble.aString, "Hello" );
TWibble wibbleToo;
wibbleToo=wibble;
strcpy( wibbleToo.aString, "Oink" ); // Side effect.
}
This is legal C++ and should compile and run just fine. The two
problems this raises are:
* The final strcpy() affects both structures.
* (Most important) who should deallocate the character array?
The situation is even more complicated with classes since often the
compiler can't generate any code for them and your source just won't
compile.
In either case the solution is to overload the assignment operator
and/or copy constructor.
For the above structure:
struct TWibble
{
char * aString;
TWibble & operator=( TWibble const & rhs )
{
aString=new char[ strlen( rhs.aString )+1 ];
strcpy( aString, rhs.aString );
return *this;
}
TWibble( TWibble const & rhs )
{
*this=rhs;
}
};
Note that you don't always need both of them although implementing both
is usually a good idea. Also note that making the copy ctor rely on the
assignment operator as above is not always appropriate. In fact the
above is a bit dodgy because it doesn't address the issue of assigning
from an initialised struct. As it stands the above code will leak
whatever is already allocated prior to the call of operator=().
It would be better written as:
struct TWibble
{
char * aString;
TWibble & operator=( TWibble const & rhs )
{
delete[] aString;
aString=new char[ strlen( rhs.aString )+1 ];
strcpy( aString, rhs.aString );
return *this;
}
TWibble( TWibble const & rhs )
{
aString=NULL;
*this=rhs;
}
};
..and it's little gotchas like that that often mean it's better to have
separate private functions that take care of initialisation, cleanup
and assignment and just have the copy ctor and assignment operators
call them.
..in fact although it's now better it's not exception safe. If the
'new' fails the class is left in a half finished state. You could
improve that by sticking 'aString=NULL' after the delete but you now
destroy the object despite failing to assign to it. A better solution
is:
TWibble & operator=( TWibble const & rhs )
{
char * tmpString=new char[ strlen( rhs.aString )+1 ];
strcpy( tmpString, rhs.aString );
std::swap( tmpString, aString );
delete[] tmpString;
return *this;
}
In some cases it may be too much work to implement these so make them
private to ensure that should anyone try to call them they'll get a
compilation error instead of dodgy behaviour at runtime.
struct TWibble
{
private:
TWibble( TWibble const & rhs );
TWibble & operator=( TWibble const & rhs );
};
You don't need to implement any code for the above as it exists simply
to ensure that the compiler will squawk if anyone tries to use it.
--
Andrue Cope [TeamB]
[Bicester, Uk]
info.borland.com/newsgroups/guide.html
 

Re:return struct

Simeon wrote:
Quote
I have a "typedef struct X". I have created a function that returns
the typedef struct X, but the values returned are all initialized. Do
I have to create a copy function for the structure?
Oops and as an example of gotchas I forgot an important addition:
TWibble & operator=( TWibble const & rhs )
{
if( &rhs!=this )
{
}
// Else do nothing (assigning ourselves to ourselves).
}
--
Andrue Cope [TeamB]
[Bicester, Uk]
info.borland.com/newsgroups/guide.html
 

{smallsort}

Re:return struct

Thanks Andrue, you have been more than clear
Simeon
"Andrue Cope [TeamB]" < XXXX@XXXXX.COM >wrote in message
Quote
Simeon wrote:

>I have a "typedef struct X". I have created a function that returns
>the typedef struct X, but the values returned are all initialized. Do
>I have to create a copy function for the structure?

Oops and as an example of gotchas I forgot an important addition:

TWibble & operator=( TWibble const & rhs )
{
if( &rhs!=this )
{
}
// Else do nothing (assigning ourselves to ourselves).
}

--
Andrue Cope [TeamB]
[Bicester, Uk]
info.borland.com/newsgroups/guide.html
 

Re:return struct

Simeon wrote:
Quote

"Andrue Cope [TeamB]" < XXXX@XXXXX.COM >wrote in message
news:42247642$ XXXX@XXXXX.COM ...
>Simeon wrote:
>
>>I have a "typedef struct X". I have created a function that returns
>>the typedef struct X, but the values returned are all initialized.
>>Do I have to create a copy function for the structure?
>
>Oops and as an example of gotchas I forgot an important addition:
>
>TWibble & operator=( TWibble const & rhs )
>{
>if( &rhs!=this )
>{
>}
>// Else do nothing (assigning ourselves to ourselves).
>}

Thanks Andrue, you have been more than clear

Simeon
I agree. The TeamB folks really do a great job, and I appreciate every
bit of help I got from them (Mainly Remy in my case, but Andrue did a
gret job here too.)
I'm just saying you gys are great appreciated by many here I'm sure :-)
 

Re:return struct

Segal wrote:
Quote
I'm just saying you gys are great appreciated by many here I'm sure
:-)
<blushing>
Well we do what we can :)
--
Andrue Cope [TeamB]
[Bicester, Uk]
info.borland.com/newsgroups/guide.html
 

Re:return struct

Hahahah. I just realised I forgot to implement the destructor for
TWibble. It should have course have been:
~TWibble()
{
delete aString;
}
--
Andrue Cope [TeamB]
[Bicester, Uk]
info.borland.com/newsgroups/guide.html
 

Re:return struct

"Andrue Cope [TeamB]" < XXXX@XXXXX.COM >writes:
Quote
Hahahah. I just realised I forgot to implement the destructor for
TWibble. It should have course have been:

~TWibble()
{
delete aString;
delete [] aString;
 

Re:return struct

Thomas Maeder [TeamB] wrote:
Quote
delete [] aString;
Oops, thanks.
--
Andrue Cope [TeamB]
[Bicester, Uk]
info.borland.com/newsgroups/guide.html