1. Trang chủ
  2. » Công Nghệ Thông Tin

HandBooks Professional Java-C-Scrip-SQL part 41 ppt

5 74 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 5
Dung lượng 21,79 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Another case is when the size of a smart pointer must be exactly the size of a raw pointer, or when performance is hurt by the allocation of the reference count for shared_ptr a rare cas

Trang 1

intrusive_ptr

Header: "boost/intrusive_ptr.hpp"

intrusive_ptr is the intrusive analogue to shared_ptr Sometimes, there's no other choice than using an intrusive, reference-counted smart pointer The typical

scenario is for code that has already been written with an internal reference

counter, and where there's no time to rewrite it (or where the code's not available) Another case is when the size of a smart pointer must be exactly the size of a raw pointer, or when performance is hurt by the allocation of the reference count for shared_ptr (a rare case, I'm sure!) The only case where it would seem that an intrusive smart pointer is required, from a functional perspective, is when a

member function of a pointed-to class needs to return this, such that it can be used

in another smart pointer (Actually, there are ways to solve that problem with non-intrusive smart pointers too, as we saw earlier in this chapter.) non-intrusive_ptr is different from the other smart pointers because it requires you to provide the

reference counter that it manipulates

When intrusive_ptr increments or decrements a reference count on a non-null pointer, it does so by making unqualified calls to the functions

intrusive_ptr_add_ref and intrusive_ptr_release, respectively These functions are responsible for making sure that the reference count is always correct and, if the reference counter drops to zero, to delete the pointer Therefore, you must overload those functions for your type, as we shall see later

This is a partial synopsis for intrusive_ptr, showing the most important functions

namespace boost {

template<class T> class intrusive_ptr {

public:

intrusive_ptr(T* p,bool add_ref=true);

intrusive_ptr(const intrusive_ptr& r);

~intrusive_ptr();

T& operator*() const;

T* operator->() const;

T* get() const;

operator unspecified-bool-type() const;

};

template <class T> T* get_pointer(const intrusive_ptr<T>& p);

template <class T,class U> intrusive_ptr<T>

Trang 2

static_pointer_cast(const intrusive_ptr<U>& r);

}

Members

intrusive_ptr(T* p,bool add_ref=true);

This constructor stores the pointer p in *this If p isn't null, and if add_ref is true, the constructor makes an unqualified call to intrusive_ptr_add_ref(p) If add_ref is false, the constructor makes no call to intrusive_ptr_add_ref This constructor can throw an exception if intrusive_ptr_add_ref can throw

intrusive_ptr(const intrusive_ptr& r);

The copy constructor saves a copy of r.get() and, if that pointer is not null, calls intrusive_ptr_add_ref with it This constructor never throws

~intrusive_ptr();

If the stored pointer is not null, the intrusive_ptr destructor makes an unqualified call to the function intrusive_ptr_release, with the stored pointer as argument intrusive_ptr_release is responsible for decrementing the reference count and

deleting the pointer if it becomes zero This function never throws

T& operator*() const;

This dereferencing operator returns and dereferences the stored pointer If the stored pointer is null, invoking this operator results in undefined behavior When in doubt, make sure that the intrusive_ptr has a non-null pointer This is done using either the function get or by testing the intrusive_ptr in a Boolean context The dereferencing operator never throws

T* operator->() const;

This operator returns the stored pointer Calling this operator when the referenced pointer is null invokes undefined behavior The operator never throws

T* get() const;

This member function returns the stored pointer It can be used when a raw pointer

is needed, and may be called even when the stored pointer is null This function never throws

Trang 3

operator unspecified-bool-type() const;

This conversion function returns a type that can be used in Boolean expressions, but it is not operator bool, because that would allow for other operations that

should be prohibited The conversion allows intrusive_ptr to be tested in Boolean contextsfor example, if (p), with p being an instance of intrusive_ptr The returned value is TRue if the intrusive_ptr references a non-null pointer; otherwise, it

returns false This conversion function never throws

Free Functions

template <class T> T* get_pointer(const intrusive_ptr<T>& p);

The function returns p.get(), and its purpose is mainly to support generic

programming.[10] It may also be used as a coding convention instead of calling the member function get, because it can be overloaded to work with raw pointers and third-party smart pointer classes Some simply prefer calling a free function over accessing a member function.[11] The function never throws

[10]

Such functions are known as shims See [12] in the Bibliography

[11]

The idea is that the line between operating on the smart pointer and operating

on what it points to can be blurred when using smart pointer member functions For example, p.get() and p->get() have completely different meanings and can be a little difficult to distinguish at a glance, whereas get_pointer(p) and p->get() look nothing alike Whether that's a problem for you is a matter of taste and experience

template <class T,class U>

intrusive_ptr<T> static_pointer_cast(const intrusive_ptr<U>& r);

This function returns intrusive_ptr<T>(static_cast<T*>(r.get())) Unlike with shared_ptr, you can use static_cast safely on pointers to objects stored in

intrusive_ptrs However, you may want to use this function for consistent usage of smart pointer casts static_pointer_cast never throws

Usage

There are two major differences when using intrusive_ptr compared to using

shared_ptr The first is that you need to provide the reference counting mechanism The second is that it becomes legal to treat this as a smart pointer,[12] which can sometimes be convenient, as we shall see Note that in most cases, the right smart pointer to use is the non-intrusive shared_ptr

Trang 4

You cannot do that with shared_ptr without special measures, such as

enable_shared_from_this

To use boost::intrusive_ptr, include "boost/intrusive_ptr.hpp" and then define the two free functions intrusive_ptr_add_ref and intrusive_ptr_release These should accept an argument that is a pointer to the type(s) that you want to use with

intrusive_ptr Any return value from these two functions is discarded Often, it makes sense to parameterize these functions, and simply forward to member

functions of the managed type to do the work (for example, calling add_ref and release) If the reference counter becomes zero, intrusive_ptr_release should take care of releasing the resource Here's how you might implement these functions generically:

template <typename T> void intrusive_ptr_add_ref(T* t) {

t->add_ref();

}

template <typename T> void intrusive_ptr_release(T* t) {

if (t->release()<=0)

delete t;

}

Note that these functions should be defined in the scope of their argument types This means that if this function is called with arguments from a namespace, the functions should be defined there, too The reason for this is that the calls are

unqualified, which means that argument-dependent lookup is permitted, and there may be cases where more than one version of these functions must be provided, which makes the global namespace a bad place to put them We'll see an example

of where to place these functions later, but first, we need to provide some sort of internal reference counter

Providing a Reference Counter

Now that the management functions have been defined, we must provide an

internal reference count In this example, the reference count is a private data

member that's initialized to zero, and we'll expose add_ref and release member functions to manipulate it add_ref increments the reference count and release

decrements it.[13] We could add a third member function to return the current value

of the reference count, but it suffices to have release return it The following base class, reference_counter, provides a counter and the add_ref and release member functions, making adding reference counting to a class as easy as using inheritance

Trang 5

Note that in a multithreaded environment, any operation on the variable holding the reference count needs to be synchronized

class reference_counter {

int ref_count_;

public:

reference_counter() : ref_count_(0) {}

virtual ~reference_counter() {}

void add_ref() {

++ref_count_;

}

int release() {

return ref_count_;

}

protected:

reference_counter& operator=(const reference_counter&) {

// No-op

return *this;

}

private:

// Copy construction disallowed

reference_counter(const reference_counter&);

};

The reason for making the destructor of reference_counter virtual is that the class

is publicly inherited, and thus it is possible to delete derived classes using a pointer

to reference_counter We want this deletion to do the right thingthat is, to call the destructor for the derived type The implementation is straightforward: add_ref increments the reference count and release decrements the current reference count and returns it To use this reference counter, all that's needed is to derive publicly from it Here's an example with a class some_ class that contains an internal

reference count, and intrusive_ptrs that use it

#include <iostream>

#include "boost/intrusive_ptr.hpp"

class some_class : public reference_counter {

Ngày đăng: 06/07/2014, 03:20

TỪ KHÓA LIÊN QUAN