user1899020
user1899020

Reputation: 13575

Put a pointer or object in a class?

Assume a class has a component of an object with a fixed type. There are two ways to make the component an attribute of the class. One is to use a pointer pointing to ab object of this type, the other is to use directly the object. When using pointer, I don't need to include the header file of the component's type declaration but use forward declaration only. And it is more extensible. My question is this: how about its performance when accessing and using it? Can the modern compilers optimize it to have the same or similar performance as the direct use? What's your strategy to decide it?

A stupid example

// Use pointer.
class A1 { ... };
class A2 { A1* a1; ... };
class A3 { A2* a2; ... };
class A4 { A3* a3; ... };
class A5 { A4* a4; ... };

// Direct use.
class B1 { ... };
class B2 { B1 b1; ... };
class B3 { B2 b2; ... };
class B4 { B3 b3; ... };
class B5 { B4 b4; ... };

May go more levels. Does the performance have a big difference? Thanks a lot!

Upvotes: 2

Views: 178

Answers (3)

tp1
tp1

Reputation: 1207

Let's focus on performance:

  1. Pointer is always an indirection, two operations needed, one fetches the address, and another dereferences the address to fetch the value.
  2. Object inside object is handled by compile-time calculation of offset. Asm code has directly 888[eax] style offsets from beginning of the whole object. The 888 will be calculated on compile-time. So it's just one operation to access the values.

Upvotes: 2

Fred Foo
Fred Foo

Reputation: 363517

Just store an instance instead of a pointer to an object unless you need a pointer for some reason, e.g. structure sharing or other custom ownership semantics. It will usually be faster and it will simplify your program, as you don't need to explicitly allocate/deallocate the pointee.

(You could of course use smart pointers to prevent explicit resource management, but that kind of beats your purpose of skipping a #include, since smart pointers drag in a lot of template code.)

Upvotes: 1

Mats Petersson
Mats Petersson

Reputation: 129314

I would generally ignore performance when deciding on a design. Yes, of course, you don't want to store your data in a completely unreasonable way, but design should not be thinking "does it take three clock-cycles more to access this object if I do X than if I do Y?" - it should be thinking about "What do I need to do to make this software work correctly, be maintainable".

As mentioned in the comments, references are another solution, which avoids the problem of "my pointer points to rubbish" that can happen with pointers [although it's possible, with some "creativity" to come up with a scenario where a reference isn't valid, you can't create a reference without setting it to something valid].

Performance: Well, any indirect object will need one more memory read. So if you are storing something very basic, like an integer, there will be at least one extra memory read to read out the actual pointer/reference content, to get to the proper object. However, for objects that are more complex than just one integer, other things tend to be what takes most of the time anyways. Compilers will definitely optimise so that if you do several things to the same reference/pointer, it only loads the pointer once, so the overhead is spread over many objects. [Once compiled, references and pointers are nearly indistinguishable].

When someone asked about the overhead of virtual functions [which has about the same overhead as pointer/reference], I wrote some test-code that measured the performance of using virtual vs. non-virtual functions. From memory, the difference was less than 1 clock-cycle per call. [Because the processor overlaps instructions, so the overhead is sometimes less than one instruction].

Upvotes: 4

Related Questions