C++ shared_ptr and STL Collections

In a previous post I introduced shared pointers as a way for automatic reference counting (ARC) in C++. This post will conclude the series by showing how to store shared pointers with STL containers like vector.

Let’s use the same MyClass class as the previous post.

class MyClass {
public:
	MyClass(){
		cout << "Creating MyClass object" << endl;
	}
	virtual ~MyClass(){
		cout << "Destroying MyClass object" << endl;
	}
	void method(){
		cout << "Called method of MyClass object" << endl;
	}
};

This shows how to store shared pointers in a vector.

#include <iostream>
#include <memory>
#include <vector>

using namespace std;

int main() {
	vector<shared_ptr <MyClass> > v;
	//Create a bunch of shared pointers
	shared_ptr<MyClass>
		m1(new MyClass), //Object #1
		m2(new MyClass), //Object #2
		m3(new MyClass); //Object #3

	//The vector will add one reference to each added object
	v.push_back(m1);
	v.push_back(m2);
	v.push_back(m3);
	//Every object now has 2 references

	m2.reset(); //Object #2 has 1 reference left
	v.erase(v.begin() + 1); //Object #2 has no reference left

	for (unsigned int i = 0; i <v.size(); ++i) {
		v[i]->method();
	}
	return 0;
}

The size of a shared_ptr<MyClass> is only about 8 bytes. Storing it by copy in a container has very little overhead. The way reference counting works here is very intuitive and exactly as I expected. I threw in a reset() and erase() call to see what will happen. As expected, object #2 gets destroyed after the erase() call above. The output from the program is:

Creating MyClass object
Creating MyClass object
Creating MyClass object
Destroying MyClass object
Called method of MyClass object
Called method of MyClass object
Destroying MyClass object
Destroying MyClass object

Advertisements

Automatic Reference Counting (ARC) Envy in C++

Many old C++ hacks like me who later learned to do programming in Objective-C watched with envy the introduction of ARC. Well, there is no need for that. C++ has shared_ptr that pretty much mimics ARC. Now, I haven’t tested all possibilities. Certainly, I will like to learn more about circular references and what happens when you store a shared_ptr in a vector or map. But, simple cases certainly work like a charm.

Let’s say we have a class called MyClass.

class MyClass {
public:
	MyClass(){
		cout << "Creating MyClass object" << endl;
	}
	virtual ~MyClass(){
		cout << "Destroying MyClass object" << endl;
	}
	void method(){
		cout << "Called method of MyClass object" << endl;
	}
};

Below is how we can manage an object of MyClass using automatic reference counting.

#include <memory>

using namespace std;

shared_ptr<MyClass> returnTest() {
	shared_ptr<MyClass> m(new MyClass);

	m->method();

	return m;
}

int main() {
	shared_ptr<MyClass> m2 = returnTest();

	m2->method();

	return 0;
}

This is a pretty good test. An object is created from a method and returned from there. The return value is assigned to a variable. The output from this program will be:

Creating MyClass object
Called method of MyClass object
Called method of MyClass object
Destroying MyClass object

The behavior is no different from Objective-C. Except that in Objective-C, the returned object will be put on an auto release pool.

On another note, I had to add the –std=c++0x option to GNU++ compiler for shared_ptr to work.