C++ Blog

C++ Weak Pointers

Posted in boost by Umesh Sirsiwal on January 5, 2009

C++ TR1 has added concept of weak pointers. Most of the C++ developers understand use of shared pointers but they don’t understand use of weak pointers very well.

Weak Pointer Definition

According to boost:

The weak_ptr class template stores a “weak reference” to an object that’s already managed by a shared_ptr. To access the object, a weak_ptr can be converted to a shared_ptr using the shared_ptr constructor or the member function lock. When the last shared_ptr to the object goes away and the object is deleted, the attempt to obtain a shared_ptr from the weak_ptr instances that refer to the deleted object will fail: the constructor will throw an exception of type boost::bad_weak_ptr, and weak_ptr::lock will return an empty shared_ptr.

There is no way to directly access underlying resources managed by the weak_ptr. In order to access the underlying pointer the weak pointer must be converted to a shared_ptr using lock or shared_ptr constructor.


shared_ptr<int> p(new int(5));

weak_ptr<int> q(p);

// some time later

if(shared_ptr<int> r = q.lock()) {

// use *r

}

Weak Pointer Usage

This all looks interesting but where will one use it. DDJ covered this subject in one of its articles. Consider an application where thread reads messages from a queue operators on it and then sends response back to the queue. This is tricky if the processing of the message can take a significant time. In order to correctly send back the response the message must hold a reference to the queue. The problem is that the queue may close before the response is ready to be sent. One possible solution is to store shared pointer to queue in the message structure:

shared_ptr<QueueType> q;

struct {

shared_ptr<QueueType> q;

} MessageType;

MessageType m;

m = q->Get();

m.q = q; //m.q holds a shared reference to the queue

...

...

m.q.Send(data);

If the queue is closed after putting a reference to the queue in the message, the queue cannot be destroyed since it is shared pointer. In some of the applications number of messages may be 1000s and can significantly delay queue destruction. A far better alternative is to put a weak_pointer to the queue in the message structure and check the queue state before calling the send. The modified code looks like the following:

shared_ptr<QueueType> q;

struct {

weak_ptr<QueueType> q;

} MessageType;

MessageType m;

m = q->Get();

m.q = q; //m.q holds a  weak reference to the queue. If the queue is closed, the underlying object can be destroyed and resources reclaimed.

...

...

if (shared_ptr<QueueType> realq = m.q.lock() ) {

realq.Send(data);

}

This code segment allows early destruction of queue to reclaim resources.

Static Assert in C++0x

Posted in c++0x by Umesh Sirsiwal on January 5, 2009

This is post in the C++ Reference series on this site.

All the C++ programmers have used static asserts some have used Loki version, others have used Boost version or created their own. However, in all cases the error messages generated by Static Assert are incomplete. A language level support is needed to correctly support Static Assert.

The C++0x adds Static Assert to solve this specific issue. The synatx for static assert is something like:

static_assert(sizeof(int) == 4, "Size of int is not 4 bytes.") ;

On any machine where the sizeof(int) is not 4, the compilers should correctly generate error message “Size of int is not 4 bytes”. Sweet.

Null Pointer and C++

Posted in c++0x by Umesh Sirsiwal on January 5, 2009

This is part of C++ Reference series.

C++ is a strongly typed language except when it comes to null pointers. 0 is used both to represent a null pointer and integer value zero. This can cause nasty issues since 0’s type cannot be determined. C++0x adds a new reserved word nullptr to solve this issue.

nullptr is zero pointer that can be converted to any pointer type.

C++0x Auto Types

Posted in c++0x by Umesh Sirsiwal on January 5, 2009

This is part of C++ Reference series.

Several OO languages including SmallTalk, Python, Ruby, etc have a way to creating new variables with the type of existing variables. In C++ to create a variable, the program always had to know the type.

Starting C++0x this restriction goes away. C++0x adds support for auto-types. For example it is now possible to code:

auto a = b->c;
auto a(b->c);

Both these statements will create a variable ‘a’ with type b->c and assign it value of b->c.

No need to  know the type of b->c. Why do we need autotypes. We thought type safety is important. Let us consider the following code segment:
for (std::vector<int>::iterator it= vi.begin(); it!=vi.end(); ++it)

with auto types this simplifies to:
for(auto vi::iterator it = vi.begin(); it  != vi.end; ++it)

Significantly less verbose and more maintainable code. We can change type of vi from vector to list, deque, etc. without changing type of every iterator.

The code no longer cares about type of vi. It just declares an iterator of the type vi::iterator.

In addition, for memory allocation it is now possible to say:

auto* a = new auto(b->c); // new object of the type b->c and assign it to a new variable of type pointer to b->c.

More interesting syntax:

auto p = std::string("xxx"); // p has type of std::string
auto p[] = "xxx"; // p has type of char[4]
auto* p = "xxx"; // p has type char*
auto a = 10; // a has type integer

References:
http://std.dkuug.dk/JTC1/SC22/WG21/docs/papers/2003/n1527.pdf

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=219