6

I just started learning about pointers in C++, and I'm not very sure on when to use pointers, and when to use actual objects.

For example, in one of my assignments we have to construct a gPolyline class, where each point is defined by a gVector. Right now my variables for the gPolyline class looks like this:

private:
vector<gVector3*> points;

If I had vector< gVector3 > points instead, what difference would it make? Also, is there a general rule of thumb for when to use pointers? Thanks in advance!

Mel
  • 1,075
  • 1
  • 14
  • 24
  • Memory copies are the biggest impact. Negligible if you're talking about three ints. – pestilence669 Jan 30 '10 at 20:40
  • 2
    @mloskot - if you'd bothered to check you would have seen that Alice has only asked four questions and accepted answers on the other three. So she clearly knows how SO works and is presumably evaluating the answers to work out which answers her question the best. – ChrisF Jan 30 '10 at 22:42
  • 1
    @Neil & @ChrisF - I'm not saying there are any requirements. You're right about waiting longer than 1-2 hrs. Regards to Alice. – mloskot Jan 30 '10 at 23:08

5 Answers5

2

The general rule of thumb is to use pointers when you need to, and values or references when you can.

If you use vector<gVector3> inserting elements will make copies of these elements and the elements will not be connected any more to the item you inserted. When you store pointers, the vector just refers to the object you inserted.

So if you want several vectors to share the same elements, so that changes in the element are reflected in all the vectors, you need the vectors to contain pointers. If you don't need such functionality storing values is usually better, for example it saves you from worrying about when to delete all these pointed to objects.

sth
  • 222,467
  • 53
  • 283
  • 367
1

Pointers are generally to be avoided in modern C++. The primary purpose for pointers nowadays revolves around the fact that pointers can be polymorphic, whereas explicit objects are not.

When you need polymorphism nowadays though it's better to use a smart pointer class -- such as std::shared_ptr (if your compiler supports C++0x extensions), std::tr1::shared_ptr (if your compiler doesn't support C++0x but does support TR1) or boost::shared_ptr.

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • I don't know what you mean by "modern C++" but on many huge projects that I've worked on, I've had to migrate code from `STL_Struct` to `STL_Struct` :) Sometimes you *need* a pointer to the object instead of the object itself for reasons I clarify in my above answer... But I'll grant you that usually there is no need for pointers. – Mahmoud Al-Qudsi Jan 30 '10 at 20:39
  • By "Modern C++" I mean the C++03 standard, or ANSI/ISO standardized C++. Several older compilers do not completely implement the standard, and pointers are needed to patch over such compilers' inconsistencies. – Billy ONeal Jan 30 '10 at 20:40
1

Generally, it's a good idea to use pointers when you have to, but references or alternatively objects objects (think of values) when you can.

First you need to know if gVector3 fulfils requirements of standard containers, namely if the type gVector3 copyable and assignable. It is useful if gVector3 is default constructible as well (see UPDATE note below). Assuming it does, then you have two choices, store objects of gVector3 directly in std::vector

std::vector<gVector3> points;
points.push_back(gVector(1, 2, 3)); // std::vector will make a copy of passed object

or manage creation (and also destruction) of gVector3 objects manually.

std::vector points; points.push_back(new gVector3(1, 2, 3)); //...

When the points array is no longer needed, remember to talk through all elements and call delete operator on it.

Now, it's your choice if you can manipulate gVector3 as objects (you can assume to think of them as values or value objects) because (if, see condition above) thanks to availability of copy constructor and assignment operator the following operations are possible:

gVector3 v1(1, 2, 3);
gVector3 v2;
v2 = v1; // assignment
gVector3 v3(v2); // copy construction

or you may want or need to allocate objects of gVector3 in dynamic storage using new operator. Meaning, you may want or need to manage lifetime of those objects on your own.

By the way, you may be also wondering When should I use references, and when should I use pointers?

UPDATE: Here is explanation to the note on default constructibility. Thanks to Neil for pointing that it was initially unclear. As Neil correctly noticed, it is not required by C++ standard, however I pointed on this feature because it is an important and useful one. If type T is not default constructible, what is not required by the C++ standard, then user should be aware of potential problems which I try to illustrate below:

#include <vector>
struct T
{
    int i;
    T(int i) : i(i) {}
};
int main()
{
    // Request vector of 10 elements
    std::vector<T> v(10); // Compilation error about missing T::T() function/ctor
}
mloskot
  • 37,086
  • 11
  • 109
  • 136
  • 1
    You are right about the copyable and assignable requirements - you are wrong about default constructible - there is no such requirement. –  Jan 30 '10 at 21:53
  • +1 for very good point. I've updated my answer to make it more clear. Thanks! – mloskot Jan 30 '10 at 23:17
  • You can say: std::vector v(10, T(0)); I also made this mistake - you can see it my blog entry on the default constructor at http://punchlet.wordpress.com/2009/12/03/letter-the-third. –  Jan 30 '10 at 23:30
  • Yes, that's correct but tightly related to this particular example of type T (or the type from your blog which is similar). However, sometimes a type is more complex and it's not easy or even possible to mimic dummy or default constructibility. – mloskot Jan 30 '10 at 23:55
0

You can use pointers or objects - it's really the same at the end of the day.

If you have a pointer, you'll need to allocate space for the actual object (then point to it) any way. At the end of the day, if you have a million objects regardless of whether you are storing pointers or the objects themselves, you'll have the space for a million objects allocated in the memory.

When to use pointers instead? If you need to pass the objects themselves around, modify individual elements after they are in the data structure without having to retrieve them each and every time, or if you're using a custom memory manager to manage the allocation, deallocation, and cleanup of the objects.

Putting the objects themselves in the STL structure is easier and simpler. It requires less * and -> operators which you may find to be difficult to comprehend. Certain STL objects would need to have the objects themselves present instead of pointers in their default format (i.e. hashtables that need to hash the entry - and you want to hash the object, not the pointer to it) but you can always work around that by overriding functions, etc.

Bottom line: use pointers when it makes sense to. Use objects otherwise.

Mahmoud Al-Qudsi
  • 28,357
  • 12
  • 85
  • 125
  • Still not a good idea to use pointers here. Better would be to use the STL's iterators and iterate over collections that way. If you're concerned about object space, you're better off using some form of `shared_ptr`. Finally, using raw pointers breaks every one of the standard algorithms with remove semantics, such as `std::remove`, `std::remove_if`, `std::unique`, `std::replace`, `std::replace_if`, etc. – Billy ONeal Jan 30 '10 at 20:44
0

Normally you use objects.
Its easier to eat an apple than an apple on a stick (OK 2 meter stick because I like candy apples).

In this case just make it a vector<gVector3>

If you had a vector<g3Vector*> this implies that you are dynamically allocating new objects of g3Vector (using the new operator). If so then you need to call delete on these pointers at some point and std::Vector is not designed to do that.

But every rule is an exception.

If g3Vector is a huge object that costs a lot to copy (hard to tell read your documentation) then it may be more effecient to store as a pointer. But in this case I would use the boost::ptr_vector<g3Vector> as this automatically manages the life span of the object.

Martin York
  • 257,169
  • 86
  • 333
  • 562