Using RWTCountingPointer
The
RWTCountingPointer<Body,Counter> class is similar to
RWTCountedPointer<Body>, except that it doesn’t require the body to implement the reference-counter. Because
RWTCountingPointer supplies its own reference counting, it can garbage-collect objects that do not directly support reference counting. In particular, unlike
RWTCountedPointer,
RWTCountingPointer supports primitive data types as bodies.
The reference-counter for
RWTCountingPointer is provided by its
Counter template parameter, generally an instance of
RWAtomicCounter.
You can implement exception-safe aggregation relationships using the
RWTCountingPointer template class. When compared to implementations using raw pointers, this technique offers the following advantages:
Simplified assignment, copy construction and destruction implementations. In most cases, the default versions of these operations are sufficient.
Exception-safe resource allocation. Allocated memory is always released, even when an exception is thrown.
Consider the UML class diagram in
Figure 42, which shows a form of aggregation called composition. Copies of the same aggregate share one instance of its part.
This form of aggregation is effective when the shared part does not change, or when you need to keep changes to all instances of the aggregate in sync. It does not suit every situation. Keep in mind that if one instance of an aggregate changes a shared part, the change affects all the instances.
An implementation of the aggregation relationship idiom is shown in
Figure 65. For comparison, the aggregation relationship between
A and
B is implemented with
RWTCountingPointer, while the aggregation relationship between
B and
C uses a raw pointer. For the complete example, see
-buildspace\examples\pointer\RWTCountingPointerEx.cpp.
Example 65 – Implementing an aggregation relationship
class B {
…
};
class A {
public:
A() : myB_(new B) { …} //1
…
private:
RWTCountingPointer<B, RWAtomicCounter> myB_;
};
class C {
public:
C() : myB_(new B) {…}
C(const C& other) : myB_(new B(other.(*myB_) )) {;} //2
~C() { delete myB_;} //2
C & operator=(const C & other) { //2
if(this == &other) return *this;
delete myB_;
myB_ = new B(other.(*myB_));
return *this;
}
…
private:
B * myB_;
};
int main() {
A a1;
A a2 = a1; //3
C c1;
C c2 = c1; //4
return 0;
…
}