1

In c++ I can declare a field as a regular variable of some type, instantiate it in the constructor, and use it later:

private:    Foo field;
...

A::A() {
    // upd: likely i instatiate field wrong ways (see comments)
    field = FieldImpl();
}
....
method(field);

Or alternatively I can use a pointer:

private:    Foo* field;
...

A::A() {
    field = new FieldImpl();
}

A::~A() {
    delete field;
}

...
method(*field);

When declaring a field, how do I decide if I should use a pointer or a regular variable?

Oleg Vazhnev
  • 23,239
  • 54
  • 171
  • 305

3 Answers3

6

You might want to use a pointer if:

  • The referenced object can outlive the parent.
  • Because of size, you want to ensure the referenced object is on the heap.
  • The pointer is provided from outside the class.
  • Null is a possible value.
  • The field can be set dynamically to a different object.
  • The actual object type is determined at runtime. For example, the field might be a base-class pointer to any of a number of subclasses.

You might also want to use a smart pointer.

The last point above applies to your sample code. If your field is of type Foo, and you assign a FieldImpl to it, all that remains is the Foo part of the FieldImpl. This is referred to as the slicing problem.

Community
  • 1
  • 1
Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
  • 1
    why just not everywhere use a pointer (like in C# and Java), why it's bad? – Oleg Vazhnev Apr 18 '13 at 17:49
  • 1
    @javapowered because that's unnecessary complexity in C++. In Java and C# the languages are designed so that using pointers everywhere is easier and some of the problems are taken care of automatically behind the scenes. – bames53 Apr 18 '13 at 17:53
  • regular variables do not need to be deleted by yourself, unlike if you do a new, so less memory leaks – Smash Apr 18 '13 at 17:54
  • @javapowered - Smart pointers address some of the risks, but there are still tradeoffs. One is that a logical object represented without pointers may take less overall memory than one with. – Andy Thomas Apr 18 '13 at 17:57
  • in C++ anything placed on the heap is not automatically cleaned up for you like in c# or java, this can lead to memory leaks. Also, pointers can point to null, try dereferencing a null pointer – Boumbles Apr 18 '13 at 18:01
  • @javapowered Not all .NET variables are of reference types - primitives (integer, bool etc.) are all [Value Types](http://msdn.microsoft.com/en-us/library/34yytbws(v=vs.71).aspx) and can be stored on the stack. Some .NET types (especially for Form Handling and GDI stuff) are also Value Types if they will end up being passed down to Native functions for performance reasons. – VisualMelon Apr 18 '13 at 18:02
  • @VisualMelon i know, i'm talking more about user-defined types. – Oleg Vazhnev Apr 18 '13 at 18:04
  • also I guess that when i do NOT using pointers my class become more processor cache-friendly... – Oleg Vazhnev Apr 18 '13 at 18:07
  • I've always thought that calling slicing a "problem" is awfully heavy-handed. I have code that uses slicing as a legitimate technique. – Ryan Witmer Apr 18 '13 at 18:13
  • @javapowered Every time you use a pointer, you are in effect jumping to a random portion of memory: `std::vector`'s ability to store contiguous instances of data in its free store buffer is one of the reasons why it blows pretty much every other container out of the water, performance-wise. On top of that, pointer lifetime management is difficult; even in garbage controlled languages, the lifetime of data only referenced by pointer is often difficult to determine from its use. Automatic storage defines a relatively simple model of object lifetime that is usually easier to reason about. – Yakk - Adam Nevraumont Apr 18 '13 at 18:16
4

Regular variable if

  • Foo is an integral part of the class, i.e., every instance always has its own Foo and
  • Foo is not too large (it can go on the stack).

Pointer if

  • several instances may share a single Foo,
  • there may be instances that don't have a Foo at some point, or
  • Foo is really large and should always be on the heap.
Elmar Peise
  • 14,014
  • 3
  • 21
  • 40
0

C++ is designed with automatic variables in mind. Critical C++ idioms like RAII depend on automatic variables. Because of C++'s design decisions, using automatic variables is simpler and easier than using pointers. You shouldn't add the complexity of using pointers unless you actually need the capabilities they provide. (And if you have to then use a smart pointer.)

Complexity needs to be justified, and in this example you haven't shown any reason for the extra complexity in your pointer example, so you should use an automatic variable.

well after 10 years of C# and Java pointers are simple and regular variables is complexity for me :) so there should be more serios reasons not to use pointers. for example I guess pointers are not processor-cache friedly

C# and Java are designed differently than C++. Their syntax and runtime are designed to make pointers the simpler (or only) method, and they take care of some of the problems that creates for you behind the scenes. Trying to work around the language to avoid pointers in Java and C# would add complexity.

Furthermore C# and Java rely to a much greater degree on polymophic types, and they don't have the "don't pay for what you don't use" policy C++ has. Pointers are needed for polymorphic types, but C# and Java are happy to make you pay the cost even when you don't need to whereas C++ doesn't do that.

bames53
  • 86,085
  • 15
  • 179
  • 244
  • @javapowered because using regular variables is simpler. There's no reason to add the complexity unless you actually need the special capabilities provided by pointers. – bames53 Apr 18 '13 at 17:51
  • well after 10 years of C# and Java pointers are simple and regular variables is complexity for me :) so there should be more serios reasons not to use pointers. for example I guess pointers are not processor-cache friedly... – Oleg Vazhnev Apr 18 '13 at 17:52
  • 2
    @javapowered Unlike C# and Java, C++ does not have garbage collection. So pointers can cause memory leaks (all pointers to an object are lost) or become dangling (object is destroyed, but pointer persists). Also, heap allocation is *slow* when compared to stack-based allocation. – Angew is no longer proud of SO Apr 18 '13 at 17:54
  • 1
    @javapowered That's because Java and C# are different from C++; they're designed for pointers everywhere. In Java and C# do what's best for Java and C#. In C++ do what's best for C++ – bames53 Apr 18 '13 at 17:54