2

I have two versions of a class named 'vertex', one that uses direct accessors for the coordinates:

struct vertex
{
    // Coordinates
    std::array<double, 3> coords;

    // Direct accessors
    double & x;
    double & y;
    double & z;

    // Constructor
    template<typename... T> vertex(T &&... coordinates) :
        coords{{ std::forward<T>(coordinates)... }},
        x( coords[0] ), y( coords[1] ), z( coords[2] )
    { }
};

and other that uses access functions:

struct vertex
{
    // Coordinates
    std::array<double, 3> coords;

    // Access functions
    double & x() { return coords[0]; }
    double & y() { return coords[1]; }
    double & z() { return coords[2]; }

    // Constructor
    template<typename... T> vertex(T &&... coordinates) :
        coords{{ std::forward<T>(coordinates)... }}
    { }
};

Which approach is better for this specific case? I would appreciate any other suggestions. Thanks!

rogerlga
  • 23
  • 4
  • 5
    What would "better" be in this case? – mfontanini Aug 09 '12 at 18:08
  • Just saying: 1 vertex, many vertices. – anthonyvd Aug 09 '12 at 18:10
  • See also: [Why use getters and setters](http://stackoverflow.com/questions/1568091/why-use-getters-and-setters). – DCoder Aug 09 '12 at 18:14
  • thanks @pwny! Sorry for my bad english – rogerlga Aug 09 '12 at 18:41
  • @rogerlga Oh that wasn't the point, it's not my first language either. It was more of a tip in case someone else reads your code so they have an easier time understanding. We can never stop learning! – anthonyvd Aug 09 '12 at 18:44
  • @pwny: this is actually just one vertex, not many of them, read the code. – sharvey Aug 09 '12 at 19:22
  • @sharvey The question was edited, the class name used to be vertice. Thanks for your completely relevant comment assuming I didn't read the code. Maybe if you had followed your own advice, you'd have realized I must have read it, considering I wrote an answer. – anthonyvd Aug 09 '12 at 19:26
  • @mfontanini mainly better performance, i.e. a call to an inline function would behave pretty much the same as a direct access? – rogerlga Aug 09 '12 at 19:43
  • @rogerlga: there never isn't the better solution. All depends on what you are actually using vertices for. – Heisenbug Aug 09 '12 at 20:27

6 Answers6

2

I think getters are better. First approach creates objects of bigger size for no real benefit.

Roman Saveljev
  • 2,544
  • 1
  • 21
  • 20
  • This! Assuming you're on a 64-bit machine, those reference members double the size of each vertex. This counts double as vertices are something you typically have a lot of. – Xavier Holt Aug 09 '12 at 18:16
2

I normally would go through functions, for encapsulation purposes.

But this is a quite particular case, because you are dealing with vertices. If you plan to manipulate a lot of those objects (rendering or trasforming meshes), then direct access has some benefits in term of performances.

Some graphic libraries use direct access (and some books suggests too) for vector-like operations in real-time environments where efficiency it's a must.

Have a look at Ogre::Vector3 for example.

Despite that I wouldn't do what you are doing in your first solution. Like other said you are doubling the used space for no reason (for eventually a lot of vertices). From my point of view, in a context of high performance this could be the best vertex:

class Vertex
{
public:
   double X;
   double Y;
   double Z;
};
Heisenbug
  • 38,762
  • 28
  • 132
  • 190
1

I'd go with the function - it allows you to change your mind more easily in the future. Furthermore, you can't do this:

double & x() { return coords[0]; }
double & y() { return coords[1]; }
double & z() { return coords[2]; }

double x() const { return coords[0]; }
double y() const { return coords[1]; }
double z() const { return coords[2]; }

with the accessors.

Andrea Bergia
  • 5,502
  • 1
  • 23
  • 38
1

Well, I'd say the first one is better for a few reasons:

  • You're unlikely to be performing additional processing mid-get or mid-set on a vertex coordinate.
  • Since operations on vertices are usually done very often in loops and vertices are often related to rendering, the first option (direct access) is likely to give you better performance.
  • Encapsulation isn't a must if you're going to be directly accessing members with trivial getters and setters. It's just Object Orientation by dogma.

That being said, the second approach has advantages too, such as an unchanging interface more resilient to change. I'd still stick with the first one.

anthonyvd
  • 7,329
  • 4
  • 30
  • 51
0

If you really want direct write access to the members (which it appears you do and may be appropriate in this case), then I would suggest the inline functions. This gives you flexibility to profile and inject extra capability into the accesses in the future should you desire to do so.

Mark B
  • 95,107
  • 10
  • 109
  • 188
0

I think the best solution would be to remove the reference of the second option and add setters. But if these are the only choices the second would be slightly better.

drakon
  • 125
  • 9