Standard for returning character arrays?

J

Justin Naidl

class Foo
{
protected:
char foo_stuff[16];

public:
char* get_foo_stuff();
}

Given the above example. What I want to know is the "proper/standard" way
of returning foo_stuff in an accessor function without giving the user
access to the data directly. The way I currently have it set up is to creat
an entirely new char array and strcpy foo_stuff into it and return the
address of the new array. I don't particularly like that method as it
requires that the caller manually delete the data that is returned. So, I
guess at this point I will leave it to the experts.


Thanks,

~Justin
 
V

Victor Bazarov

Justin said:
class Foo
{
protected:
char foo_stuff[16];

public:
char* get_foo_stuff();
} ;

Given the above example. What I want to know is the "proper/standard" way
of returning foo_stuff in an accessor function without giving the user
access to the data directly.

As long as the pointer is still valid after you return it, there is no
problem with returning 'foo_stuff' directly.
The way I currently have it set up is to creat
an entirely new char array and strcpy foo_stuff into it and return the
address of the new array.

That's just another way. You charge the user with having to delete the
array after they are done with it.
I don't particularly like that method as it
requires that the caller manually delete the data that is returned. So, I
guess at this point I will leave it to the experts.

There is nothing special the expert will tell you except, maybe, to use
'std::string'. Of course, to be sure an expert would know what the
meaning of 'foo_stuff' is and how the user is supposed to use the return
value of 'get_foo_stuff'...

V
 
J

John Carson

Justin Naidl said:
class Foo
{
protected:
char foo_stuff[16];

public:
char* get_foo_stuff();
}

Given the above example. What I want to know is the
"proper/standard" way of returning foo_stuff in an accessor function
without giving the user access to the data directly. The way I
currently have it set up is to creat an entirely new char array and
strcpy foo_stuff into it and return the address of the new array. I
don't particularly like that method as it requires that the caller
manually delete the data that is returned. So, I guess at this point
I will leave it to the experts.

There is no "proper/standard" way. It depends on what you are trying to
achieve, which will partly depend on how you see the data being used by the
caller.

One approach would be to return a pointer to const char. This gives the
caller "read only" access to the data. If the user wants their own
modifiable copy of the data, then the user can make a copy and assume full
responsibility for managing that copy. Generally speaking, there are less
problems if whoever allocates the memory has the responsibility for deleting
it.

Another possibility would be to define an operator[] to give access to data
one element at a time. This operator could return a char and no dynamic
memory allocation would be needed.
 
R

Rolf Magnus

Victor said:
Justin said:
class Foo
{
protected:
char foo_stuff[16];

public:
char* get_foo_stuff();
} ;

Given the above example. What I want to know is the "proper/standard"
way of returning foo_stuff in an accessor function without giving the
user access to the data directly.

As long as the pointer is still valid after you return it, there is no
problem with returning 'foo_stuff' directly.

There is one problem: The user is now able to modify it, even though it's
not a public member. The get_foo_stuff() function exposes it, which btw.
means that this function now serves no purpose at all anymore. Just make
the member public and you have the same functionality without the need for
an additional function.
That's just another way. You charge the user with having to delete the
array after they are done with it.

Other ways would be to store the pointer internally and delete [] the array
on use of the next function that modifies the object. I think some
implementations of std::string do this. Another way is to return some type
of smart pointer instead of a raw pointer.
 
V

Victor Bazarov

Rolf said:
Victor Bazarov wrote:

Justin said:
class Foo
{
protected:
char foo_stuff[16];

public:
char* get_foo_stuff();
}
;

Given the above example. What I want to know is the "proper/standard"
way of returning foo_stuff in an accessor function without giving the
user access to the data directly.

As long as the pointer is still valid after you return it, there is no
problem with returning 'foo_stuff' directly.


There is one problem: The user is now able to modify it, even though it's
not a public member. The get_foo_stuff() function exposes it, which btw.
means that this function now serves no purpose at all anymore. Just make
the member public and you have the same functionality without the need for
an additional function.

That's nonsense. The function _always_ serves a purpose. If you need to
register the fact of accessing the private member, or do anything else for
that matter, you do it in a function.

V
 
J

jdibling

Be mindful of semantics when mixing the use of char[] and char*. Since
this appears to be entirely your code, it's probably a non-issue.
But I have noticed in production code that very often fixed-length char
arrays (eg, char[x]) are not null-terminated - which means they aren't
really strings in the common sense.

In particular, you cannot perform string operations like strcpy() on a
non-null-terminated char array (because strcpy works by looking for the
null-terminator). In this case, I have found that very often the
simplest way to get a 'real' string out of the non-null-term char array
is to use std::string's ctor specifying a char* substring:

class Foo
{
protected:
char foo_stuff[16];

public:
std::string get_foo_stuff() const;

} ;

std::string
Foo::get_foo_stuff()
const
{
return std::string(&foo_stuff[0],sizeof(foo_stuff));
}

Depending on the application, this solution may or may not be
appropriate for you.

Take care,

John Dibling
(e-mail address removed)
 
V

Victor Bazarov

Rolf said:
Victor Bazarov wrote:

Rolf said:
Victor Bazarov wrote:



Justin Naidl wrote:


class Foo
{
protected:
char foo_stuff[16];

public:
char* get_foo_stuff();
}

;


Given the above example. What I want to know is the "proper/standard"
way of returning foo_stuff in an accessor function without giving the
user access to the data directly.

As long as the pointer is still valid after you return it, there is no
problem with returning 'foo_stuff' directly.


There is one problem: The user is now able to modify it, even though it's
not a public member. The get_foo_stuff() function exposes it, which btw.
means that this function now serves no purpose at all anymore. Just make
the member public and you have the same functionality without the need
for an additional function.

That's nonsense. The function _always_ serves a purpose.


No. It directly exposes the member to the outside world (i.e. makes it
possible for a user of the class to modify the member without the object
having control over it). You can do that in a simpler way by just making
the member public.

"Simpler" doesn't make it better.
You mean that the object notices the access and can do something in the
function? Well, the problem is that it doesn't.
It registers that someone takes a pointer to the data, but it doesn't
register at all whether that 'someone' uses the pointer to read the data,
to write it (maybe several times), to store it for later acces, or to just
do nothing at all with it.

So damn what? The mere fact that somebody requests the pointer is
important. It is _impossible_ to register *that* without a function.

Besides, if later you decide to change the implementation and so whatever
else you might deem necessary, it is _impossible_ without a function, and
with a function, you just change the implementation and not the interface
or the layout of the class. Making the data member public will definitely
be worse. That's my point.

V
 
R

Rolf Magnus

Victor said:
Rolf said:
Victor Bazarov wrote:

Justin Naidl wrote:

class Foo
{
protected:
char foo_stuff[16];

public:
char* get_foo_stuff();
}

;

Given the above example. What I want to know is the "proper/standard"
way of returning foo_stuff in an accessor function without giving the
user access to the data directly.

As long as the pointer is still valid after you return it, there is no
problem with returning 'foo_stuff' directly.


There is one problem: The user is now able to modify it, even though it's
not a public member. The get_foo_stuff() function exposes it, which btw.
means that this function now serves no purpose at all anymore. Just make
the member public and you have the same functionality without the need
for an additional function.

That's nonsense. The function _always_ serves a purpose.

No. It directly exposes the member to the outside world (i.e. makes it
possible for a user of the class to modify the member without the object
having control over it). You can do that in a simpler way by just making
the member public.
If you need to register the fact of accessing the private member,
or do anything else for that matter, you do it in a function.

You mean that the object notices the access and can do something in the
function? Well, the problem is that it doesn't.
It registers that someone takes a pointer to the data, but it doesn't
register at all whether that 'someone' uses the pointer to read the data,
to write it (maybe several times), to store it for later acces, or to just
do nothing at all with it.
 
V

Victor Bazarov

Rolf said:
Victor Bazarov wrote:
[...]
Making the data member public will definitely b worse. That's my point.


Making the data member private is a good idea, but giving away pointers to
it to anyone who wants destroys the advantages of that idea. That's my
point.

Your point is valid, but when choosing whether to make it public or wrap
that public access in a public member function, the latter is much more
preferable. Read more about abstraction.

V
 
R

Rolf Magnus

Victor said:
"Simpler" doesn't make it better.

If there are two ways of doing the same thing, I'd choose the simpler way.
So damn what? The mere fact that somebody requests the pointer is
important.

It is?
It is _impossible_ to register *that* without a function.

Right. But I don't see any advantage.
Besides, if later you decide to change the implementation and so whatever
else you might deem necessary, it is _impossible_ without a function, and
with a function, you just change the implementation and not the interface
or the layout of the class.

You can't, since the function exposes private data directly to the outside
world.
Making the data member public will definitely b worse. That's my point.

Making the data member private is a good idea, but giving away pointers to
it to anyone who wants destroys the advantages of that idea. That's my
point.
 
J

Justin Naidl

It doesn't give the user access to the member variable guys.

"The way I currently have it set up is to creat
an entirely new char array and strcpy foo_stuff into it and return the
address of the new array. "

The wrapper function creates a new string and copys the existing string to
it. Then returns the address of this newly created string. The private
data member is still not accessible. The problem was that the newly created
string must be deleted by whoever uses it and cannot be set up to be cleaned
nicely in the class itself.

~Justin
 
K

Karl Heinz Buchegger

Justin said:
It doesn't give the user access to the member variable guys.

"The way I currently have it set up is to creat
an entirely new char array and strcpy foo_stuff into it and return the
address of the new array. "

The wrapper function creates a new string and copys the existing string to
it. Then returns the address of this newly created string. The private
data member is still not accessible. The problem was that the newly created
string must be deleted by whoever uses it and cannot be set up to be cleaned
nicely in the class itself.

The question is:
Why do you use plain vanilla character arrays and not a full blown string
class like std::string. Then you wouldn't have all those problems.
 

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

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top