Ideal way to return a member array

J

Jeff Schwab

How can you tell with a toy example?

I can't. That's what I meant by "you are correct."
I can envision examples where
iterators would be appropriate (like for a container),

Right, agreed.
where raw
arrays would be appropriate (like for a 3D vector returning
coordinates to be rendered)

The reason to use raw arrays in such a case is to enable rapid I/O by
allowing very low-level data access. In such a case, the client code
probably should (and generally does) own the array, and pass down a
pointer-to-buffer; as an example, see the fread function. The OP
included a "getArr" function with similar semantics.

The common use case for returning a pointer to a private array is to
provide the caller with occasional access to a buffer that may be (but
is not necessarily) populated already with whatever data the client
wants. Examples include std::string::c_str and strerror. I'm not
personally a big fan of this technique, because there is the danger that
the client will hang onto the pointer after the array's contents have
been invalidated, but continue to use it as though it still pointed to
the original data. There is no way for us to warn the client when they
make such a mistake; all we can do is shrug, and point to the
documentation. The raw pointer is just too low-level a data type to
serve as a reliable handle.
and for complete encapsulation. The
example provided didn't give enough detail to determine which course
to take, so I defaulted to protecting encapsulation.

What do you mean by "protecting encapsulation?" I'm not arguing with
you, I just don't understand what you mean by that phrase.
 
D

dave_mikesell

The reason to use raw arrays in such a case is to enable rapid I/O by
allowing very low-level data access. In such a case, the client code
probably should (and generally does) own the array, and pass down a
pointer-to-buffer; as an example, see the fread function. The OP
included a "getArr" function with similar semantics.

The way I've seen it used (and used it) is to have a vector3d or
matrix class that holds the array and performs vector and matrix ops
on it. A renderer will later get the vertices and send them to
OpenGL.

What do you mean by "protecting encapsulation?" I'm not arguing with
you, I just don't understand what you mean by that phrase.

Sorry, bad choice of words. "Preserving" encapsulation would have
been better, as in hiding impl details.
 
J

James Kanze

[...]
The reason to use raw arrays in such a case is to enable rapid
I/O by allowing very low-level data access.

Except, of course, that that doesn't work. Normally, in such
cases, you encapsulate still more, with a specific type for the
information, and various << and >> operators for output and
input (e.g. to whatever data stream types you want to support).

I'm not too sure what the application is; the statement above
seems ambiguous (or contradictory). If all that is being
returned is a coordinate, there should be a coordinate class
(which might contain a double[3]). If what is being returned is
a set of 3D coordinates, then an std::vector< Coordinate > is
the obvious solution; if member templates aren't a problem, then
having the user pass in an output iterator is also a good
solution. If what is being returned is actually a 3D vector,
i.e. something accessed by [][][], then this should also be a
user defined type; how you would write a getter would depend
somewhat on the type. (Just returning it via a copy constructor
would be the obvious solution for deep copy; if performance is
an issue, returning a const reference instead would allow the
client code to avoid the deep copy in cases where it isn't
necessary.)
 
J

Jeff Schwab

The way I've seen it used (and used it) is to have a vector3d or
matrix class that holds the array and performs vector and matrix ops
on it. A renderer will later get the vertices and send them to
OpenGL.

That's interesting. I've seen the OpenGL side, in which the matrices
(in the form of raw arrays) are filled/pushed/popped by various
procedures, and I've seen and written matrix classes for numeric
processing, but I've never seen a "matrix" class specifically built on
top of Gl. Do you know of any open source examples I could take a peek at?
Sorry, bad choice of words. "Preserving" encapsulation would have
been better, as in hiding impl details.

Got it. That approach still smells bad to me, but I can't point to any
good reason why. Maybe I'm just accustomed to classes, with private
members, being used for high-level abstractions, whereas raw pointers
are used when bit-for-bit memory layout is critical (when abstraction
becomes more dangerous than helpful). It's not a juxtaposition that
comes naturally to my mind.
 
J

Jeff Schwab

James said:
[...]
The reason to use raw arrays in such a case is to enable rapid
I/O by allowing very low-level data access.

Except, of course, that that doesn't work. Normally, in such
cases, you encapsulate still more, with a specific type for the
information, and various << and >> operators for output and
input (e.g. to whatever data stream types you want to support).

I'm not too sure what the application is; the statement above
seems ambiguous (or contradictory). If all that is being
returned is a coordinate, there should be a coordinate class
(which might contain a double[3]). If what is being returned is
a set of 3D coordinates, then an std::vector< Coordinate > is
the obvious solution; if member templates aren't a problem, then
having the user pass in an output iterator is also a good
solution. If what is being returned is actually a 3D vector,
i.e. something accessed by [][][], then this should also be a
user defined type; how you would write a getter would depend
somewhat on the type. (Just returning it via a copy constructor
would be the obvious solution for deep copy; if performance is
an issue, returning a const reference instead would allow the
client code to avoid the deep copy in cases where it isn't
necessary.)

Insightful take. Agreed on all counts, particularly using a UDT to
represent the 3D vector.
 
J

James Kanze

James said:
[...]
where raw arrays would be appropriate (like for a 3D vector
returning coordinates to be rendered)
The reason to use raw arrays in such a case is to enable rapid
I/O by allowing very low-level data access.
Except, of course, that that doesn't work. Normally, in such
cases, you encapsulate still more, with a specific type for the
information, and various << and >> operators for output and
input (e.g. to whatever data stream types you want to support).
How do you implement << and >>? At some point, don't you have to deal
with buffers full of bytes?

At some point, yes. You have to format the data into a char[],
since that's all the lower levels (e.g. streambuf or the O/S
level) actually understand. If you're using streambuf, at
least, you'll generally push the bytes out one by one, however,
and if you're not, you'll design a class with a more or less
similar interface.
 

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,774
Messages
2,569,596
Members
45,144
Latest member
KetoBaseReviews
Top