Sign in to follow this  

Smart pointers and Iterators

This topic is 3842 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

No. Different.

Smart Pointer: A wrapper to a pointer that operates such that when the thing being pointed to is deleted, all smart pointers pointing to that object will be set to NULL

Iterator: Iterators are used to iterate the contents of a container; a handle to an object in a STL container. When the thing the iterator is pointing to is modified/deleted/whatever the iterator will *not* set it's reference to NULL so you will crash if you access what's inside it.

-me

Share this post


Link to post
Share on other sites
Okay thanks for that. The reason I ask is because of something I read in Thinking in C++, chapter 12 about operator overloading and overloading the -> operator.

Operator->

The operator–> is generally used when you want to make an object appear to be a pointer. Since such an object has more “smarts” built into it than exist for a typical pointer, an object like this is often called a smart pointer. These are especially useful if you want to “wrap” a class around a pointer to make that pointer safe, or in the common usage of an iterator, which is an object that moves through a collection /container of other objects and selects them one at a time, without providing direct access to the implementation of the container. (You’ll often find containers and iterators in class libraries, such as in the Standard C++ Library, described in Volume 2 of this book.)


A pointer dereference operator must be a member function. It has additional, atypical constraints: It must return an object (or reference to an object) that also has a pointer dereference operator, or it must return a pointer that can be used to select what the pointer dereference operator arrow is pointing at. Here’s a simple example:


//: C12:SmartPointer.cpp
#include <iostream>
#include <vector>
#include "../require.h"
using namespace std;

class Obj {
static int i, j;
public:
void f() const { cout << i++ << endl; }
void g() const { cout << j++ << endl; }
};

// Static member definitions:
int Obj::i = 47;
int Obj::j = 11;

// Container:
class ObjContainer {
vector<Obj*> a;
public:
void add(Obj* obj) { a.push_back(obj); }
friend class SmartPointer;
};

class SmartPointer {
ObjContainer& oc;
int index;
public:
SmartPointer(ObjContainer& objc) : oc(objc) {
index = 0;
}
// Return value indicates end of list:
bool operator++() { // Prefix
if(index >= oc.a.size()) return false;
if(oc.a[++index] == 0) return false;
return true;
}
bool operator++(int) { // Postfix
return operator++(); // Use prefix version
}
Obj* operator->() const {
require(oc.a[index] != 0, "Zero value "
"returned by SmartPointer::operator->()");
return oc.a[index];
}
};

int main() {
const int sz = 10;
Obj o[sz];
ObjContainer oc;
for(int i = 0; i < sz; i++)
oc.add(&o[i]); // Fill it up
SmartPointer sp(oc); // Create an iterator
do {
sp->f(); // Pointer dereference operator call
sp->g();
} while(sp++);
} ///:~




The class Obj defines the objects that are manipulated in this program. The functions f( ) and g( ) simply print out interesting values using static data members. Pointers to these objects are stored inside containers of type ObjContainer using its add( ) function. ObjContainer looks like an array of pointers, but you’ll notice there’s no way to get the pointers back out again. However, SmartPointer is declared as a friend class, so it has permission to look inside the container. The SmartPointer class looks very much like an intelligent pointer – you can move it forward using operator++ (you can also define an operator– –), it won’t go past the end of the container it’s pointing to, and it produces (via the pointer dereference operator) the value it’s pointing to. Notice that the SmartPointer is a custom fit for the container it’s created for; unlike an ordinary pointer, there isn’t a “general purpose" smart pointer. You will learn more about the smart pointers called “iterators" in the last chapter of this book and in Volume 2 (downloadable from www.BruceEckel.com).


In main( ), once the container oc is filled with Obj objects, a SmartPointer sp is created. The smart pointer calls happen in the expressions:


sp->f(); // Smart pointer calls
sp->g();
Here, even though sp doesn’t actually have f( ) and g( ) member functions, the pointer dereference operator automatically calls those functions for the Obj* that is returned by SmartPointer::operator–>. The compiler performs all the checking to make sure the function call works properly.


Although the underlying mechanics of the pointer dereference operator are more complex than the other operators, the goal is exactly the same: to provide a more convenient syntax for the users of your classes.


A nested iterator

It’s more common to see a “smart pointer" or “iterator" class nested within the class that it services. The previous example can be rewritten to nest SmartPointer inside ObjContainer like this:


//: C12:NestedSmartPointer.cpp
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include "../require.h"
using namespace std;

class Obj {
static int i, j;
public:
void f() { cout &lt;&lt; i++ &lt;&lt; endl; }
void g() { cout &lt;&lt; j++ &lt;&lt; endl; }
};

// Static member definitions:
int Obj::i = 47;
int Obj::j = 11;

// Container:
class ObjContainer {
vector&lt;Obj*&gt; a;
public:
void add(Obj* obj) { a.push_back(obj); }
class SmartPointer;
friend class SmartPointer;
class SmartPointer {
ObjContainer& oc;
unsigned int index;
public:
SmartPointer(ObjContainer& objc) : oc(objc) {
index = 0;
}
// Return value indicates end of list:
bool operator++() { // Prefix
if(index &gt;= oc.a.size()) return false;
if(oc.a[++index] == 0) return false;
return true;
}
bool operator++(int) { // Postfix
return operator++(); // Use prefix version
}
Obj* operator-&gt;() const {
require(oc.a[index] != 0, "Zero value "
"returned by SmartPointer::operator-&gt;()");
return oc.a[index];
}
};
// Function to produce a smart pointer that
// points to the beginning of the ObjContainer:
SmartPointer begin() {
return SmartPointer(*this);
}
};

int main() {
const int sz = 10;
Obj o[sz];
ObjContainer oc;
for(int i = 0; i &lt; sz; i++)
oc.add(&o[i]); // Fill it up
ObjContainer::SmartPointer sp = oc.begin();
do {
sp-&gt;f(); // Pointer dereference operator call
sp-&gt;g();
} while(++sp);
} ///:~




I take it smart pointer in the above has nothing to do with the smart pointers that you are talking about?

Share this post


Link to post
Share on other sites
"Smart Pointer" may be one of those terms that means different things to different people. It seems that the author defines a smart pointer as any kind of object who's purpose is to point to other stuff but which also contains additional "smart" logic to act on the pointer.

-me

Share this post


Link to post
Share on other sites

This topic is 3842 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this